From: Myungjae Lee Date: Mon, 7 Mar 2011 08:22:01 +0000 (+0900) Subject: svn update: 57457 (latest:57457) X-Git-Tag: accepted/2.0/20130306.225542~384 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9ff4fbf8a1984daaf02d6ebf0076553f7d3cd877;p=profile%2Fivi%2Fevas.git svn update: 57457 (latest:57457) --- diff --git a/ChangeLog b/ChangeLog index bbcf3c6..3e796e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,137 @@ -20YY-MM-2DD NAME OF RELEASER +2011-01-29 Carsten Haitzler (The Rasterman) - MAJOR.MINOR.MICRO release - + 1.0.0 release + +2011-01-29 Carsten Haitzler (The Rasterman) + + * Enabled mempool for object allocation + * Allow shorter pre-render handler for rect objects if they are + invisible + +2011-01-30 Tom Hacohen (TAsn) + + * It's actually a merge from my local branch upstream so this + includes many changes. + * Fixed cursor/selection handling with BiDi text. + * Fixed many BiDi issues in both textblock and text objects. + * Cleaned up textblock and font engine a lot. + * Added auto-alignment to tetxblock and text objects. + * Added mixedwrap (word wrap, and if a word is too big cut it) support + to textblock. + * Renamed a lot of stuff. + * Made textblock faster, mostly by saving item sizes and caching + layout items when text doesn't change. + * Added harfbuzz (ot layouting/shaping and etc) support. + * Currently you need to set the env var EVAS_USE_OT to '1' in order to + use OT support (harfbuzz) that will change soon. + * More code cleanups will be coming in the future. This shipment is + mostly to get code review started (and also make sure I don't have a + merging hell later on). + +2011-01-31 ChunEon Park + + * Fix lurking free bug in key grabs. + + +2011-02-01 Carsten Haitzler (The Rasterman) + + * Added WBMP loader thanks to Samsung. + +2011-02-01 Tom Hacohen (TAsn) + + * Started using string objects instead of strings in most of the + font engine (everywhere except draw). Haven't removed the + paramteres yet, but did mark them as UNUSED. Removing them will be + part of a future change. + * Removed run-time OT toggling support, OT is now fast, no need for that. + * Renamed all of the intl_props->text_props (because it really + changed purpose + * Fixed spliting/merging of text_props to be fast and good, not + hacky and complex like before. + * Added "mirrored mode" to table object. + +2011-02-07 Brett Nash (nash@nash.id.au) + + * Proxy Objects; Now you can set an image to have a 'source' of + another object. The proxy will display the object as well. Proxy + objects should be mostly complete. + * Proxy objects should be complete; please report and bugs to me. + * Partial support for arbitrary clipping. Final support coming soon + (with some other changes). You can set most objects as a clip on + other objects. This will use the alpha channel of the object as a + clip on the object. This is still buggy. + * Software support for arbitrary maps. So you can use any size map + (not just 4 points) for maps. Once again this is a little buggy. + +2011-02-02 Carsten Haitzler (The Rasterman) + + * GL engine gets a speculative texture cache to shadow the + normal image cache to avoid excess texture uploads when + cycling images often. Should improve performance in some + cases. + +2011-02-12 Carsten Haitzler (The Rasterman) + + * Fix "rediculous scaling size" bug, where scaling images to + sizes like 1 billion pixels high or wide caused evas to try + allocate scaletables on the stack and the stack just couldn't + handle it. Now it only allocates a table for the visible + region which will always be sane, and even has insanity + checks now. At worst you'll get an unrendered image if the + values are silly and some slowness. No crashes. + +2011-02-13 Brett Nash (nash@nash.id.au) + + * Fix crash when deleting proxies. This _technically_ breaks + evas engines which realloc engine data when a border is set. + Practically no engines do this. There is a comment there (and + if the engine does that border set won't work), in which case + a more complex work-around is possible. + +2011-02-14 Tom Hacohen (TAsn) + + * Added a newline character mode API to textblock. This lets us set + the newline behavior to either normal (i.e only break a line, not + a paragraph) to "behave as a PS" mode. Default is the latter. + The former is the more correct approach but I guess everything else + is in e is not yet ready to use it. These API should help with the + transition. + * A lot of textblock speed improvements and reduced memory footprint. + +2011-02-16 Jeonghyun Yun + + * Patch from Jeonghyun Yun that + improves BMP loader support to handle malformed RLE BMP's that + encode more pixels per line than the image actuall has. + +2011-02-16 Tom Hacohen (TAsn) + + * Dropped Evas_Encoding and moved to use Eina_unicode_utf8 instead. + * Started showing the unicode replacement character instead of missing + glyphs. + +2011-02-20 Carsten Haitzler (The Rasterman) + + * Fix bug in font string parsing that can result in a crash if a + font element is long enough. + * Fix convert rgba8888 -> a8 bug so it wont crash. + +2011-02-21 Carsten Haitzler (The Rasterman) + + * Fixed bug with memory access of old utf8 string when + comparing prev and cur state with text obj. + +2011-02-22 Tom Hacohen (TAsn) + + * Fixed a bug in textblock cursor position with empty textblocks. + +2011-02-22 Carsten Haitzler (The Rasterman) + + * Fixed bug smart calc array where it'd nuke the array when nested + process calls hapen and leave some objects uncalculated, but + removed from the array and marked as needing a calc thus never + getting back into the array. + +2011-02-27 Vincent Torri + + * Fixed static linking of the bmp, wbmp and tga loaders diff --git a/autogen.sh b/autogen.sh index 995ff2f..6499736 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,8 +1,5 @@ #!/bin/sh -rm -rf autom4te.cache -rm -f aclocal.m4 ltmain.sh - touch README echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1 @@ -12,5 +9,5 @@ echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --au echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1 if [ -z "$NOCONFIGURE" ]; then - ./configure "$@" + ./configure -C "$@" fi diff --git a/configure.ac b/configure.ac index e22607f..d986ce2 100644 --- a/configure.ac +++ b/configure.ac @@ -2,11 +2,11 @@ ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## m4_define([v_maj], [1]) m4_define([v_min], [0]) -m4_define([v_mic], [0]) +m4_define([v_mic], [999]) m4_define([v_rev], m4_esyscmd([(svnversion "${SVN_REPO_PATH:-.}" | grep -v export || echo 0) | awk -F : '{printf("%s\n", $1);}' | tr -d ' :MSP\n'])) m4_if(v_rev, [0], [m4_define([v_rev], m4_esyscmd([git log 2> /dev/null | (grep -m1 git-svn-id || echo 0) | sed -e 's/.*@\([0-9]*\).*/\1/' | tr -d '\n']))]) ##-- When released, remove the dnl on the below line -m4_undefine([v_rev]) +dnl m4_undefine([v_rev]) ##-- When doing snapshots - change soname. remove dnl on below line dnl m4_define([relname], [ver-pre-svn-07]) dnl m4_define([v_rel], [-release relname]) @@ -21,17 +21,17 @@ m4_define([lt_age], v_min) # rw_PROG_OBJC_WORKS # Check whether the Objective C compiler works. AC_DEFUN([rw_PROG_OBJC_WORKS], -[AC_REQUIRE([AC_PROG_OBJC])dnl +[m4_ifdef([AC_PROG_OBJC], [AC_REQUIRE([AC_PROG_OBJC])dnl AC_CACHE_CHECK([whether the Objective C compiler works], [rw_cv_prog_objc_works], [AC_LANG_PUSH([Objective C]) AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [rw_cv_prog_objc_works=yes], [rw_cv_prog_objc_works=no]) - AC_LANG_POP([Objective C])]) + AC_LANG_POP([Objective C])])], [rw_cv_prog_objc_works=no]) ]) -AC_INIT([evas], [v_ver.beta3], [enlightenment-devel@lists.sourceforge.net]) +AC_INIT([evas], [v_ver], [enlightenment-devel@lists.sourceforge.net]) AC_PREREQ([2.52]) AC_CONFIG_SRCDIR([configure.ac]) AC_CONFIG_MACRO_DIR([m4]) @@ -89,6 +89,7 @@ AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture") want_fontconfig="auto" want_fribidi="auto" +want_harfbuzz="auto" want_evas_cserve="yes" want_evas_engine_buffer="yes" @@ -193,9 +194,9 @@ m4_ifdef([AC_PROG_OBJC], _AM_DEPENDENCIES(OBJC) ], [ - AC_CHECK_TOOL([OBJC], [gcc]) - AC_SUBST([OBJC]) - AC_SUBST([OBJCFLAGS]) + dnl#AC_CHECK_TOOL([OBJC], [gcc]) + dnl#AC_SUBST([OBJC]) + dnl#AC_SUBST([OBJCFLAGS]) ]) rw_PROG_OBJC_WORKS @@ -303,6 +304,68 @@ if test "x${have_fribidi}" = "xno"; then HAS_BIDI=0 fi +# harfbuzz support +have_harfbuzz="no" +have_harfbuzz_glib="no" +have_harfbuzz_ft="no" +AC_ARG_ENABLE([harfbuzz], + AC_HELP_STRING([--disable-harfbuzz], + [disable complex text shaping and layouting support. @<:@default=enabled@:>@]), + [ + if test "x${enableval}" = "xyes" ; then + want_harfbuzz="yes" + else + want_harfbuzz="no" + fi + ]) + +if test "x${want_harfbuzz}" = "xyes" -o "x${want_harfbuzz}" = "xauto" ; then + PKG_CHECK_MODULES([HARFBUZZ], + [harfbuzz >= 0.2], + [ + have_harfbuzz="yes" + requirement_evas="harfbuzz ${requirement_evas}" + ], + [ + if test "x$want_harfbuzz" = "xyes" -a "x$use_strict" = "xyes" ; then + AC_MSG_ERROR([Harfbuzz not found (strict dependencies checking)]) + fi + ]) + if test "x$have_harfbuzz" = "xyes" ; then + + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $HARFBUZZ_CFLAGS $FREETYPE_CFLAGS" +# must have for usage with harfbuzz although harfbuzz may not have it. + + AC_CHECK_HEADER(hb-ft.h, + [ + have_harfbuzz_ft="yes" + #Depend on harfbuzz ft for harfbuzz support + AC_DEFINE(HAVE_HARFBUZZ, 1, [have harfbuzz support]) + ], + [ + if test "x$want_harfbuzz" = "xyes" -a "x$use_strict" = "xyes" ; then + AC_MSG_ERROR([Harfbuzz-ft not found (strict dependencies checking)]) + fi + have_harfbuzz="no" + ]) +# nice to have if harfbuzz has it + AC_CHECK_HEADER(hb-glib.h, + [ + have_harfbuzz_glib="yes" + AC_DEFINE(HAVE_HARFBUZZ_GLIB, 1, [have harfbuzz glib support]) + ], + [ + have_harfbuzz_glib="no" + ]) + CPPFLAGS="$CPPFLAGS_SAVE" + fi +fi + +if test "x${have_harfbuzz}" = "xno"; then + HAS_HARFBUZZ=0 +fi + ### Checks for header files AC_HEADER_STDC AC_CHECK_HEADERS([unistd.h stdint.h sys/param.h]) @@ -734,6 +797,7 @@ case "$host_os" in ;; *) if test "x${have_evas_image_loader_jpeg}" = "xyes" ; then + AC_DEFINE(EVAS_BUILD_SAVER_JPEG, [1], [Build JPEG saver]) have_evas_image_saver_jpeg="yes" fi ;; @@ -1644,7 +1708,10 @@ echo " EET.....................: $have_evas_font_loader_eet" echo echo "Font Searching Systems:" echo " Fontconfig..............: $have_fontconfig" +echo +echo "Font Rendering Helpers:" echo " Fribidi.................: $have_fribidi" +echo " Harfbuzz................: $have_harfbuzz" # FIXME: add non freetype2 font engine support # FIXME: make freetype2 optional echo diff --git a/doc/evas.dox.in b/doc/evas.dox.in index c9c3334..9ec03a0 100644 --- a/doc/evas.dox.in +++ b/doc/evas.dox.in @@ -25,8 +25,9 @@ @author Mathieu Taillefumier @author Iván Briano @author Gustavo Lima Chaves - -@date 2000-2010 +@author Samsung Electronics +@author Samsung SAIT +@date 2000-2011 @section toc Table of Contents diff --git a/evas.spec.in b/evas.spec.in index 9ef36ae..58d59bf 100644 --- a/evas.spec.in +++ b/evas.spec.in @@ -26,6 +26,7 @@ %bcond_with module_engine_software_xcb %bcond_with module_engine_xrender_x11 %bcond_with module_engine_xrender_xcb +%bcond_with module_loader_gif %bcond_with module_loader_svg ## enabled features @@ -37,7 +38,6 @@ %bcond_without module_saver_png %bcond_without module_loader_jpeg %bcond_without module_saver_jpeg -%bcond_without module_loader_gif %bcond_without module_loader_tiff %bcond_without module_saver_tiff %bcond_without module_loader_eet @@ -267,6 +267,7 @@ Software X11 rendering engine module for Evas %package module_engine_software_x11 Summary: Software X11 rendering engine module for Evas Group: System Environment/Libraries +BuildRequires: libX11-devel, libICE-devel, libXext-devel Requires: evas-module_engine_software_generic Requires: evas %description module_engine_software_x11 @@ -297,8 +298,8 @@ Framebuffer rendering engine module for Evas %package module_engine_xrender_x11 Summary: XRender rendering engine module for Evas Group: System Environment/Libraries -#BuildSuggests: xorg-x11-devel, XFree86-devel -BuildRequires: xrender-devel +#BuildSuggests: xorg-x11-devel, XFree86-devel, xrender-devel +BuildRequires: libXrender-devel Requires: evas-module_engine_software_generic Requires: evas %description module_engine_xrender_x11 @@ -383,7 +384,7 @@ Software XCB X11 rendering engine module for Evas %package module_engine_xrender_xcb Summary: Xrender XCB X11 rendering engine module for Evas Group: System Environment/Libraries -BuildRequires: xcb-devel +BuildRequires: libxcb-devel Requires: evas-module_engine_xrender_x11 Requires: evas %description module_engine_xrender_xcb @@ -391,7 +392,7 @@ Xrender XCB X11 rendering engine module for Evas %endif %prep -%setup -q -n %{name}-%{version} +%setup -q %build %{configure} --prefix=%{_prefix} --x-libraries=%{_prefix}/X11R6/%{_lib} \ @@ -450,7 +451,7 @@ test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT %{_libdir}/*.la %{_libdir}/*.a %{_libdir}/pkgconfig/* -%{_includedir}/*.h +%{_includedir}/evas-1/*.h %{_datadir}/evas/examples/*.c %files module_engine_software_generic %defattr(-, root, root) diff --git a/m4/evas_check_engine.m4 b/m4/evas_check_engine.m4 index 178355f..fdc2870 100644 --- a/m4/evas_check_engine.m4 +++ b/m4/evas_check_engine.m4 @@ -435,16 +435,14 @@ AC_REQUIRE([EVAS_MAYBE_GET_OBJCPP]) AS_IF([test "x${rw_cv_prog_objc_works}" = "xyes"], [ - AC_LANG_PUSH([Objective C]) - AC_CHECK_HEADER([/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h], - [ - have_dep="yes" - evas_engine_[]$1[]_libs="-framework Cocoa" - ], - [have_dep="no"]) - AC_LANG_POP([Objective C]) - -]) + m4_ifdef([AC_PROG_OBJC], [AC_LANG_PUSH([Objective C])]) + AC_CHECK_HEADER([/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h], [ + have_dep="yes" + evas_engine_[]$1[]_libs="-framework Cocoa" + ],[ + have_dep="no" + ]) + m4_ifdef([AC_PROG_OBJC], [AC_LANG_POP([Objective C])], [:])]) AC_SUBST([evas_engine_$1_cflags]) AC_SUBST([evas_engine_$1_libs]) @@ -461,7 +459,7 @@ dnl Helper macro for EVAS_CHECK_ENGINE_DEP_QUARTZ AC_DEFUN([EVAS_MAYBE_GET_OBJCPP], [AS_IF([test "x${rw_cv_prog_objc_works}" = "xyes"], - [AC_PROG_OBJCPP]) + [m4_ifdef([AC_PROG_OBJC], [AC_PROG_OBJCPP], [:])]) ]) dnl use: EVAS_CHECK_ENGINE_DEP_GL_GLEW(engine, simple, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) diff --git a/m4/evas_check_loader.m4 b/m4/evas_check_loader.m4 index 83b15b8..00a9618 100644 --- a/m4/evas_check_loader.m4 +++ b/m4/evas_check_loader.m4 @@ -114,7 +114,7 @@ if test "x${have_dep}" = "xyes" ; then [jpeg_CreateDecompress], [ evas_image_loader_[]$1[]_libs="-ljpeg" - AC_COMPILE_IFELSE([[ + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include #include #include @@ -122,7 +122,7 @@ if test "x${have_dep}" = "xyes" ; then struct jpeg_decompress_struct decomp; decomp.region_x = 0; } - ]], + ])], [have_jpeg_region="yes"], [have_jpeg_region="no"]) ], diff --git a/src/lib/Evas.h b/src/lib/Evas.h index 7e9fc5f..d9fd805 100644 --- a/src/lib/Evas.h +++ b/src/lib/Evas.h @@ -1293,6 +1293,11 @@ typedef void (*Evas_Object_Image_Pixels_Get_Cb) (void *data, Evas_Object *o); EAPI void evas_object_image_content_hint_set (Evas_Object *obj, Evas_Image_Content_Hint hint) EINA_ARG_NONNULL(1); EAPI Evas_Image_Content_Hint evas_object_image_content_hint_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; + EAPI void evas_object_image_alpha_mask_set (Evas_Object *obj, Eina_Bool ismask) EINA_ARG_NONNULL(1); + EAPI Eina_Bool evas_object_image_source_set (Evas_Object *obj, Evas_Object *src) EINA_ARG_NONNULL(1); + EAPI Evas_Object *evas_object_image_source_get (Evas_Object *obj) EINA_ARG_NONNULL(1); + EAPI Eina_Bool evas_object_image_source_unset (Evas_Object *obj) EINA_ARG_NONNULL(1); + /** * @defgroup Evas_Object_Text Text Object Functions * @@ -1344,6 +1349,7 @@ typedef void (*Evas_Object_Image_Pixels_Get_Cb) (void *data, Evas_Object *o); EAPI void evas_object_text_outline_color_set(Evas_Object *obj, int r, int g, int b, int a) EINA_ARG_NONNULL(1); EAPI void evas_object_text_outline_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a) EINA_ARG_NONNULL(1); EAPI void evas_object_text_style_pad_get (const Evas_Object *obj, int *l, int *r, int *t, int *b) EINA_ARG_NONNULL(1); + EAPI Evas_BiDi_Direction evas_object_text_direction_get (const Evas_Object *obj) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; /** * @defgroup Evas_Object_Textblock Textblock Object Functions @@ -1399,6 +1405,8 @@ typedef void (*Evas_Object_Image_Pixels_Get_Cb) (void *data, Evas_Object *o); EAPI const Evas_Textblock_Style *evas_object_textblock_style_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; EAPI void evas_object_textblock_replace_char_set(Evas_Object *obj, const char *ch) EINA_ARG_NONNULL(1); EAPI const char *evas_object_textblock_replace_char_get(Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; + EAPI void evas_object_textblock_newline_mode_set(Evas_Object *obj, Eina_Bool mode) EINA_ARG_NONNULL(1); + EAPI Eina_Bool evas_object_textblock_newline_mode_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; EAPI void evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text) EINA_ARG_NONNULL(1); EAPI void evas_object_textblock_text_markup_prepend(Evas_Textblock_Cursor *cur, const char *text) EINA_ARG_NONNULL(1, 2); @@ -1454,6 +1462,7 @@ typedef void (*Evas_Object_Image_Pixels_Get_Cb) (void *data, Evas_Object *o); EAPI int 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) EINA_ARG_NONNULL(1); EAPI int evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) EINA_ARG_NONNULL(1); + EAPI int evas_textblock_cursor_pen_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cpen_x, Evas_Coord *cy, Evas_Coord *cadv, Evas_Coord *ch) EINA_ARG_NONNULL(1); EAPI int evas_textblock_cursor_line_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) EINA_ARG_NONNULL(1); EAPI Eina_Bool evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y) EINA_ARG_NONNULL(1); EAPI int evas_textblock_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y) EINA_ARG_NONNULL(1); @@ -2079,6 +2088,8 @@ struct _Evas_Smart_Cb_Description EAPI void evas_object_table_padding_get (const Evas_Object *o, Evas_Coord *horizontal, Evas_Coord *vertical) EINA_ARG_NONNULL(1); EAPI void evas_object_table_align_set (Evas_Object *o, double horizontal, double vertical) EINA_ARG_NONNULL(1); EAPI void evas_object_table_align_get (const Evas_Object *o, double *horizontal, double *vertical) EINA_ARG_NONNULL(1); + EAPI void evas_object_table_mirrored_set (Evas_Object *o, Eina_Bool mirrored) EINA_ARG_NONNULL(1); + EAPI Eina_Bool evas_object_table_mirrored_get (const Evas_Object *o) EINA_ARG_NONNULL(1); EAPI Eina_Bool evas_object_table_pack (Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan) EINA_ARG_NONNULL(1, 2); EAPI Eina_Bool evas_object_table_unpack (Evas_Object *o, Evas_Object *child) EINA_ARG_NONNULL(1, 2); diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 16e0def..382e26e 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -113,6 +113,11 @@ SUBDIRS += ../modules/engines/xrender_x11/ EVAS_STATIC_MODULE += ../modules/engines/xrender_x11/libevas_engine_xrender_x11.la EVAS_STATIC_LIBADD += @evas_engine_xrender_x11_libs@ @evas_engine_xrender_xcb_libs@ endif +if EVAS_STATIC_BUILD_BMP +SUBDIRS += ../modules/loaders/bmp +EVAS_STATIC_MODULE += ../modules/loaders/bmp/libevas_loader_bmp.la +EVAS_STATIC_LIBADD += @evas_image_loader_bmp_libs@ +endif if EVAS_STATIC_BUILD_EDB SUBDIRS += ../modules/savers/edb ../modules/loaders/edb EVAS_STATIC_MODULE += ../modules/savers/edb/libevas_saver_edb.la ../modules/loaders/edb/libevas_loader_edb.la @@ -129,8 +134,12 @@ EVAS_STATIC_MODULE += ../modules/loaders/gif/libevas_loader_gif.la EVAS_STATIC_LIBADD += @evas_image_loader_gif_libs@ endif if EVAS_STATIC_BUILD_JPEG -SUBDIRS += ../modules/savers/jpeg ../modules/loaders/jpeg -EVAS_STATIC_MODULE += ../modules/savers/jpeg/libevas_saver_jpeg.la ../modules/loaders/jpeg/libevas_loader_jpeg.la +SUBDIRS += ../modules/loaders/jpeg +EVAS_STATIC_MODULE += ../modules/loaders/jpeg/libevas_loader_jpeg.la +if BUILD_SAVER_JPEG +SUBDIRS += ../modules/savers/jpeg +EVAS_STATIC_MODULE += ../modules/savers/jpeg/libevas_saver_jpeg.la +endif EVAS_STATIC_LIBADD += @evas_image_loader_jpeg_libs@ endif if EVAS_STATIC_BUILD_PMAPS @@ -148,11 +157,21 @@ SUBDIRS += ../modules/loaders/svg EVAS_STATIC_MODULE += ../modules/loaders/svg/libevas_loader_svg.la EVAS_STATIC_LIBADD += @evas_image_loader_svg_libs@ endif +if EVAS_STATIC_BUILD_TGA +SUBDIRS += ../modules/loaders/tga +EVAS_STATIC_MODULE += ../modules/loaders/tga/libevas_loader_tga.la +EVAS_STATIC_LIBADD += @evas_image_loader_tga_libs@ +endif if EVAS_STATIC_BUILD_TIFF SUBDIRS += ../modules/savers/tiff ../modules/loaders/tiff EVAS_STATIC_MODULE += ../modules/savers/tiff/libevas_saver_tiff.la ../modules/loaders/tiff/libevas_loader_tiff.la EVAS_STATIC_LIBADD += @evas_image_loader_tiff_libs@ endif +if EVAS_STATIC_BUILD_WBMP +SUBDIRS += ../modules/loaders/wbmp +EVAS_STATIC_MODULE += ../modules/loaders/wbmp/libevas_loader_wbmp.la +EVAS_STATIC_LIBADD += @evas_image_loader_wbmp_libs@ +endif if EVAS_STATIC_BUILD_XPM SUBDIRS += ../modules/loaders/xpm EVAS_STATIC_MODULE += ../modules/loaders/xpm/libevas_loader_xpm.la @@ -185,6 +204,7 @@ AM_CPPFLAGS = \ @EINA_CFLAGS@ \ @FREETYPE_CFLAGS@ \ @FRIBIDI_CFLAGS@ \ +@HARFBUZZ_CFLAGS@ \ @EET_CFLAGS@ \ @FONTCONFIG_CFLAGS@ \ @pthread_cflags@ @@ -212,6 +232,7 @@ $(libevas_cserve_la) \ engines/common/libevas_engine_common.la \ @FREETYPE_LIBS@ \ @FRIBIDI_LIBS@ \ +@HARFBUZZ_LIBS@ \ @EET_LIBS@ \ @FONTCONFIG_LIBS@ \ @pthread_libs@ \ diff --git a/src/lib/canvas/evas_key_grab.c b/src/lib/canvas/evas_key_grab.c index a8e8979..5152842 100644 --- a/src/lib/canvas/evas_key_grab.c +++ b/src/lib/canvas/evas_key_grab.c @@ -48,8 +48,8 @@ evas_key_grab_new(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modi if (eina_error_get()) { MERR_FATAL(); - free(g); free(g->keyname); + free(g); return NULL; } } @@ -63,8 +63,8 @@ evas_key_grab_new(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modi { MERR_FATAL(); g->object->grabs = eina_list_remove(g->object->grabs, g); - free(g); free(g->keyname); + free(g); return NULL; } } diff --git a/src/lib/canvas/evas_map.c b/src/lib/canvas/evas_map.c index 90e4dca..f383e8f 100644 --- a/src/lib/canvas/evas_map.c +++ b/src/lib/canvas/evas_map.c @@ -1244,11 +1244,10 @@ evas_map_util_3d_lighting(Evas_Map *m, x = m->points[i].x; y = m->points[i].y; z = m->points[i].z; -printf("Normal %d\n",i); + // calc normal h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point j = (i + 1) % 4 + (i & ~0x3); // next point -printf("\tNext/Prev: %2d/%2d\n",h,j); x1 = m->points[h].x - x; y1 = m->points[h].y - y; @@ -1257,16 +1256,12 @@ printf("\tNext/Prev: %2d/%2d\n",h,j); x2 = m->points[j].x - x; y2 = m->points[j].y - y; z2 = m->points[j].z - z; -printf("\tX: %3.2lf,%3.2lf,%3.2lf\n",x,y,z); -printf("\tX1: %3.2lf,%3.2lf,%3.2lf\n",x1,y1,z1); -printf("\tX2: %3.2lf,%3.2lf,%3.2lf\n",x2,y2,z2); nx = (y1 * z2) - (z1 * y2); ny = (z1 * x2) - (x1 * z2); nz = (x1 * y2) - (y1 * x2); ln = (nx * nx) + (ny * ny) + (nz * nz); ln = sqrt(ln); -printf("\tLength: %3.2lf\n",ln); if (ln != 0.0) { @@ -1274,7 +1269,6 @@ printf("\tLength: %3.2lf\n",ln); ny /= ln; nz /= ln; } -printf("\tpoint %2d: %3.2lf,%3.2lf,%3.2lf normal: %3.2lf %3.2lf %3.2lf\n",i,x,y,z,nx,ny,nz); // calc point -> light vector x = lx - x; diff --git a/src/lib/canvas/evas_object_box.c b/src/lib/canvas/evas_object_box.c index fcdc910..8503cf4 100644 --- a/src/lib/canvas/evas_object_box.c +++ b/src/lib/canvas/evas_object_box.c @@ -1,5 +1,9 @@ #include "evas_common.h" +#ifdef _WIN32_WCE +# undef remove +#endif + typedef struct _Evas_Object_Box_Iterator Evas_Object_Box_Iterator; typedef struct _Evas_Object_Box_Accessor Evas_Object_Box_Accessor; diff --git a/src/lib/canvas/evas_object_image.c b/src/lib/canvas/evas_object_image.c index 553ed57..8f71561 100644 --- a/src/lib/canvas/evas_object_image.c +++ b/src/lib/canvas/evas_object_image.c @@ -311,6 +311,10 @@ evas_object_image_file_get(const Evas_Object *obj, const char **file, const char /** * Set the source object on a proxy object. * + * The source must be another object. The proxy will have the same base + * appearance of the source object. Obviously other effects may be applied to + * the proxy, such as a map to create a reflection of the original object. + * * Any existing source object will be removed. Setting the src to NULL clears * the proxy object. * @@ -337,7 +341,8 @@ evas_object_image_source_set(Evas_Object *obj, Evas_Object *src) if (o->cur.source == src) return EINA_TRUE; /* Kill the image if any */ - evas_object_image_file_set(obj, NULL, NULL); + if (o->cur.file || o->cur.key) + evas_object_image_file_set(obj, NULL, NULL); if (o->cur.source) { @@ -1752,7 +1757,7 @@ evas_object_image_load_dpi_get(const Evas_Object *obj) * * @param obj The given canvas object. * @param w The new width of the canvas image given. - * @param h Th new height of the canvas image given. + * @param h The new height of the canvas image given. * * This function sets a new size for the given canvas image. * @@ -2143,6 +2148,39 @@ evas_object_image_content_hint_set(Evas_Object *obj, Evas_Image_Content_Hint hin } /** + * Enable an image to be used as an alpha mask. + * + * This will set any flags, and discard any excess image data not used as an + * alpha mask. + * + * Note there is little point in using a image as alpha mask unless it has an + * alpha channel. + * + * @param obj Object to use as an alpha mask. + * @param ismask Use image as alphamask, must be true. + */ +EAPI void +evas_object_image_alpha_mask_set(Evas_Object *obj, Eina_Bool ismask) +{ + Evas_Object_Image *o; + + if (!ismask) return; + + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + o = (Evas_Object_Image *)(obj->object_data); + MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE); + return; + MAGIC_CHECK_END(); + + /* Convert to A8 if not already */ + + /* done */ + +} + +/** * Get the content hint of a given image of the canvas. * * @param obj The given canvas pointer. @@ -2698,10 +2736,11 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su obj->layer->evas->engine.func->context_render_op_set(output, context, obj->cur.render_op); - if (0)// o->cur.source) - printf("Proxy: %p Source: %p Surface %p Redraw %s Type %s\n",obj, - o->cur.source,o->cur.source->proxy.surface, - o->cur.source->proxy.redraw?"yep":"nope",o->cur.source->type); + if (0) + printf("Proxy: %p Source: %p Surface %p Redraw %s Type %s/%s %p %d %d\n", + obj, o->cur.source,o->cur.source->proxy.surface, + o->cur.source->proxy.redraw?"yep ":"nope",o->cur.source->type, + o_type,obj->cur.map,obj->cur.map->count, obj->cur.usemap); if (!o->cur.source) { @@ -2757,7 +2796,7 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su p = obj->cur.map->points; p_end = p + obj->cur.map->count; pt = pts; - + pts[0].px = obj->cur.map->persp.px << FP; pts[0].py = obj->cur.map->persp.py << FP; pts[0].foc = obj->cur.map->persp.foc << FP; @@ -2773,6 +2812,10 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su pt->fz = p->z; pt->u = p->u * FP1; pt->v = p->v * FP1; + if (pt->u < 0) pt->u = 0; + else if (pt->u > (o->cur.image.w * FP1)) pt->u = (imagew * FP1); + if (pt->v < 0) pt->v = 0; + else if (pt->v > (o->cur.image.h * FP1)) pt->v = (imageh * FP1); pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b); } if (obj->cur.map->count & 0x1) @@ -2789,9 +2832,12 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su obj->layer->evas->engine.func->image_scale_hint_set(output, pixels, o->scale_hint); - o->engine_data = obj->layer->evas->engine.func->image_border_set(output, pixels, - o->cur.border.l, o->cur.border.r, - o->cur.border.t, o->cur.border.b); + /* This is technically a bug here: If the value is recreated + * (which is returned)it may be a new object, however exactly 0 + * of all the evas engines do this. */ + obj->layer->evas->engine.func->image_border_set(output, pixels, + o->cur.border.l, o->cur.border.r, + o->cur.border.t, o->cur.border.b); idx = evas_object_image_figure_x_fill(obj, o->cur.fill.x, o->cur.fill.w, &idw); idy = evas_object_image_figure_y_fill(obj, o->cur.fill.y, o->cur.fill.h, &idh); if (idw < 1) idw = 1; diff --git a/src/lib/canvas/evas_object_main.c b/src/lib/canvas/evas_object_main.c index c394e93..5f44d72 100644 --- a/src/lib/canvas/evas_object_main.c +++ b/src/lib/canvas/evas_object_main.c @@ -399,9 +399,10 @@ evas_object_del(Evas_Object *obj) obj->mouse_in = 0; evas_object_hide(obj); evas_object_grabs_cleanup(obj); - while (obj->clip.clipees) evas_object_clip_unset(obj->clip.clipees->data); + while (obj->clip.clipees) + evas_object_clip_unset(obj->clip.clipees->data); while (obj->proxy.proxies) - evas_object_image_source_unset(obj->proxy.proxies->data); + evas_object_image_source_unset(obj->proxy.proxies->data); if (obj->cur.clipper) evas_object_clip_unset(obj); if (obj->smart.smart) evas_object_smart_del(obj); evas_object_map_set(obj, NULL); diff --git a/src/lib/canvas/evas_object_rectangle.c b/src/lib/canvas/evas_object_rectangle.c index 74ecac8..50728ff 100644 --- a/src/lib/canvas/evas_object_rectangle.c +++ b/src/lib/canvas/evas_object_rectangle.c @@ -201,6 +201,7 @@ evas_object_rectangle_render_pre(Evas_Object *obj) /* if it just became visible or invisible */ is_v = evas_object_is_visible(obj); was_v = evas_object_was_visible(obj); + if (!(is_v | was_v)) goto done; if (is_v != was_v) { evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, obj, is_v, was_v); diff --git a/src/lib/canvas/evas_object_smart.c b/src/lib/canvas/evas_object_smart.c index c3cde73..cdb81d7 100644 --- a/src/lib/canvas/evas_object_smart.c +++ b/src/lib/canvas/evas_object_smart.c @@ -735,8 +735,7 @@ evas_object_smart_need_recalculate_set(Evas_Object *obj, Eina_Bool value) return; o->need_recalculate = value; - if (!obj->smart.smart->smart_class->calculate) - return; + if (!obj->smart.smart->smart_class->calculate) return; /* XXX: objects can be present multiple times in calculate_objects() * XXX: after a set-unset-set cycle, but it's not a problem since @@ -745,8 +744,7 @@ evas_object_smart_need_recalculate_set(Evas_Object *obj, Eina_Bool value) */ if (o->need_recalculate) { - Evas *e; - e = obj->layer->evas; + Evas *e = obj->layer->evas; eina_array_push(&e->calculate_objects, obj); } /* TODO: else, remove from array */ @@ -831,17 +829,21 @@ evas_call_smarts_calculate(Evas *e) { Eina_Array *calculate; unsigned int i; + static int in_smart_calc = 0; + in_smart_calc++; calculate = &e->calculate_objects; - for (i = 0; i < calculate->count; ++i) + for (i = 0; i < calculate->count; i++) { Evas_Object *obj; Evas_Object_Smart *o; + int before; obj = eina_array_data_get(calculate, i); if (obj->delete_me) continue; + before = calculate->count; o = obj->object_data; if (o->need_recalculate) { @@ -849,8 +851,8 @@ evas_call_smarts_calculate(Evas *e) obj->smart.smart->smart_class->calculate(obj); } } - - eina_array_flush(calculate); + in_smart_calc--; + if (in_smart_calc == 0) eina_array_flush(calculate); } /** diff --git a/src/lib/canvas/evas_object_table.c b/src/lib/canvas/evas_object_table.c index 2d8e056..0addce1 100644 --- a/src/lib/canvas/evas_object_table.c +++ b/src/lib/canvas/evas_object_table.c @@ -62,6 +62,7 @@ struct _Evas_Object_Table_Data Eina_Bool hints_changed : 1; Eina_Bool expand_h : 1; Eina_Bool expand_v : 1; + Eina_Bool is_mirrored : 1; }; struct _Evas_Object_Table_Iterator @@ -515,7 +516,14 @@ _evas_object_table_calculate_layout_homogeneous(Evas_Object *o, Evas_Object_Tabl _evas_object_table_calculate_cell(opt, &cx, &cy, &cw, &ch); - evas_object_move(child, cx, cy); + if (priv->is_mirrored) + { + evas_object_move(opt->obj, x + w - (cx - x + cw), cy); + } + else + { + evas_object_move(child, cx, cy); + } evas_object_resize(child, cw, ch); } } @@ -782,18 +790,25 @@ _evas_object_table_calculate_layout_regular(Evas_Object *o, Evas_Object_Table_Da { Evas_Object *child = opt->obj; Evas_Coord cx, cy, cw, ch; - + cx = x + opt->col * (priv->pad.h); cx += _evas_object_table_sum_sizes(cols, 0, opt->col); cw = _evas_object_table_sum_sizes(cols, opt->col, opt->end_col); - + cy = y + opt->row * (priv->pad.v); cy += _evas_object_table_sum_sizes(rows, 0, opt->row); ch = _evas_object_table_sum_sizes(rows, opt->row, opt->end_row); - + _evas_object_table_calculate_cell(opt, &cx, &cy, &cw, &ch); - - evas_object_move(child, cx, cy); + + if (priv->is_mirrored) + { + evas_object_move(opt->obj, x + w - (cx - x + cw), cy); + } + else + { + evas_object_move(child, cx, cy); + } evas_object_resize(child, cw, ch); } @@ -1379,5 +1394,42 @@ evas_object_table_child_get(const Evas_Object *o, unsigned short col, unsigned s } /** + * Gets the mirrored mode of the table. In mirrored mode the table items go + * from right to left instead of left to right. That is, 1,1 is top right, not + * to left. + * + * @param obj The table object. + * @return EINA_TRUE if it's a mirrored table, EINA_FALSE otherwise. + * @since 1.1.0 + */ +EAPI Eina_Bool +evas_object_table_mirrored_get(const Evas_Object *obj) +{ + EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(obj, priv, EINA_FALSE); + + return priv->is_mirrored; +} + +/** + * Sets the mirrored mode of the table. In mirrored mode the table items go + * from right to left instead of left to right. That is, 1,1 is top right, not + * to left. + * + * @param obj The table object. + * @param mirrored the mirrored mode to set + * @since 1.1.0 + */ +EAPI void +evas_object_table_mirrored_set(Evas_Object *obj, Eina_Bool mirrored) +{ + EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(obj, priv); + if (priv->is_mirrored != mirrored) + { + priv->is_mirrored = mirrored; + _evas_object_table_smart_calculate_regular(obj, priv); + } +} + +/** * @} */ diff --git a/src/lib/canvas/evas_object_text.c b/src/lib/canvas/evas_object_text.c index 8605cfe..73d03b6 100644 --- a/src/lib/canvas/evas_object_text.c +++ b/src/lib/canvas/evas_object_text.c @@ -10,13 +10,13 @@ static const char o_type[] = "text"; /* private struct for text object internal data */ typedef struct _Evas_Object_Text Evas_Object_Text; +typedef struct _Evas_Object_Text_Item Evas_Object_Text_Item; struct _Evas_Object_Text { DATA32 magic; struct { - const Eina_Unicode *text; /*The shaped text */ const char *utf8_text; /* The text exposed to the API */ const char *font; const char *source; @@ -26,15 +26,27 @@ struct _Evas_Object_Text } outline, shadow, glow, glow2; unsigned char style; - Evas_BiDi_Props intl_props; } cur, prev; - float ascent, descent; - float max_ascent, max_descent; + float ascent, descent; + float max_ascent, max_descent; + Evas_BiDi_Paragraph_Props *bidi_par_props; + Evas_Object_Text_Item *items; - void *engine_data; + void *engine_data; - char changed : 1; + char changed : 1; +}; + +struct _Evas_Object_Text_Item +{ + EINA_INLIST; + + Eina_Unicode *text; /*The shaped text */ + size_t text_pos; + size_t visual_pos; + Evas_Text_Props text_props; + Evas_Coord x, w, h, adv; }; /* private methods for text objects */ @@ -53,6 +65,7 @@ static int evas_object_text_is_opaque(Evas_Object *obj); static int evas_object_text_was_opaque(Evas_Object *obj); static void evas_object_text_scale_update(Evas_Object *obj); +static void _evas_object_text_recalc(Evas_Object *obj); static const Evas_Object_Func object_func = { @@ -90,6 +103,202 @@ static const Evas_Object_Func object_func = EVAS_MEMPOOL(_mp_obj); +/* FIXME: doc */ +static int +_evas_object_text_char_coords_get(const Evas_Object *obj, + const Evas_Object_Text *o, + size_t pos, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) +{ + Evas_Object_Text_Item *it; + + EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it) + { + if ((it->text_pos <= pos) && + (pos < it->text_pos + eina_unicode_strlen(it->text))) + { + return ENFN->font_char_coords_get(ENDT, o->engine_data, it->text, + &it->text_props, pos - it->text_pos, x, y, w, h); + } + } + return 0; +} + +/* FIXME: doc */ +static void +_evas_object_text_item_clean(Evas_Object_Text_Item *it) +{ + evas_common_text_props_content_unref(&it->text_props); + if (it->text) + { + free(it->text); + } +} + +/* FIXME: doc */ +static void +_evas_object_text_items_clear(Evas_Object_Text *o) +{ + Evas_Object_Text_Item *it; + + while (o->items) + { + it = o->items; + o->items = (Evas_Object_Text_Item *) eina_inlist_remove( + EINA_INLIST_GET(o->items), + EINA_INLIST_GET(it)); + _evas_object_text_item_clean(it); + free(it); + } +} + +#ifdef BIDI_SUPPORT +static int +_evas_object_text_it_compare_logical(const void *_it1, const void *_it2) +{ + const Evas_Object_Text_Item *it1 = _it1, *it2 = _it2; + if (it1->text_pos < it2->text_pos) + return -1; + else if (it1->text_pos == it2->text_pos) + return 0; + else + return 1; + +} +#endif +/* FIXME: doc */ +static int +_evas_object_text_last_up_to_pos(const Evas_Object *obj, + const Evas_Object_Text *o, Evas_Coord cx, Evas_Coord cy) +{ + Evas_Object_Text_Item *it; + +#ifdef BIDI_SUPPORT + /*FIXME: not very efficient, sort the items arrays. */ + /* Reorder if it's a bidi text */ + if (o->bidi_par_props) + { + Eina_List *logical_it = NULL; + Evas_Object_Text_Item *i; + Eina_List *itr; + Evas_Coord x = 0; + /* Insert all to the logical list */ + EINA_INLIST_FOREACH(o->items, i) + { + logical_it = eina_list_sorted_insert(logical_it, + _evas_object_text_it_compare_logical, i); + } + EINA_LIST_FOREACH(logical_it, itr, it) + { + if ((x <= cx) && (cx < x + it->adv)) + { + return it->text_pos + ENFN->font_last_up_to_pos(ENDT, + o->engine_data, + it->text, &it->text_props, + cx - x, + cy); + } + x += it->adv; + } + eina_list_free(logical_it); + } + else +#endif + { + EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it) + { + if ((it->x <= cx) && (cx < it->x + it->adv)) + { + return it->text_pos + ENFN->font_last_up_to_pos(ENDT, + o->engine_data, + it->text, &it->text_props, + cx - it->x, + cy); + } + } + } + return -1; +} + +/* FIXME: doc */ +static int +_evas_object_text_char_at_coords(const Evas_Object *obj, + const Evas_Object_Text *o, Evas_Coord cx, Evas_Coord cy, + Evas_Coord *rx, Evas_Coord *ry, Evas_Coord *rw, Evas_Coord *rh) +{ + Evas_Object_Text_Item *it; + + EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it) + { + if ((it->x <= cx) && (cx < it->x + it->adv)) + { + return it->text_pos + ENFN->font_char_at_coords_get(ENDT, + o->engine_data, + it->text, &it->text_props, + cx, + cy, + rx, ry, + rw, rh); + } + } + return -1; +} + +/* FIXME: doc */ +static Evas_Coord +_evas_object_text_horiz_advance_get(const Evas_Object *obj, + const Evas_Object_Text *o) +{ + Evas_Object_Text_Item *it; + Evas_Coord adv; + (void) obj; + + adv = 0; + EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it) + { + adv += it->adv; + } + return adv; +} + +/* FIXME: doc */ +static Evas_Coord +_evas_object_text_vert_advance_get(const Evas_Object *obj __UNUSED__, + const Evas_Object_Text *o) +{ + return o->max_ascent + o->max_descent; +} + +/* FIXME: returns the advance instead of the width just because it's usuallly + * bigger, major hack, should fix. */ +static void +_evas_object_text_string_size_get(const Evas_Object *obj, + const Evas_Object_Text *o, + Evas_Coord *cw, Evas_Coord *ch) +{ + Evas_Object_Text_Item *it, *last_it = NULL; + Evas_Coord w, h; + (void) obj; + + w = h = 0; + EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it) + { + w += it->adv; + if (it->h > h) + { + h = it->h; + } + last_it = it; + } + /* Take the width, not the advance of the last item */ + if (last_it) + { + w += last_it->w - last_it->adv; + } + + if (cw) *cw = w; + if (ch) *ch = h; +} + /** * Creates a new text @c Evas_Object on the provided @c Evas canvas. * @@ -176,7 +385,6 @@ EAPI void evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size size) { Evas_Object_Text *o; - int l = 0, r = 0, t = 0, b = 0; int is, was = 0, pass = 0; int same_font = 0; @@ -227,44 +435,21 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz o->cur.size = size; o->engine_data = evas_font_load(obj->layer->evas, o->cur.font, o->cur.source, (int)(((double)o->cur.size) * obj->cur.scale)); - evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); - if ((o->engine_data) && (o->cur.text)) + if (o->engine_data) { - int w, h; - - o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data); - ENFN->font_string_size_get(ENDT, - o->engine_data, - o->cur.text, &o->cur.intl_props, - &w, &h); - o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data); - o->descent = ENFN->font_descent_get(ENDT, o->engine_data); - o->max_ascent = ENFN->font_max_ascent_get(ENDT, o->engine_data); - o->max_descent = ENFN->font_max_descent_get(ENDT, o->engine_data); - obj->cur.geometry.w = w + l + r; - obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b; -//// obj->cur.cache.geometry.validity = 0; + o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data); + o->descent = ENFN->font_descent_get(ENDT, o->engine_data); + o->max_ascent = ENFN->font_max_ascent_get(ENDT, o->engine_data); + o->max_descent = ENFN->font_max_descent_get(ENDT, o->engine_data); } else { - if (o->engine_data) - { - o->ascent = ENFN->font_ascent_get(ENDT, o->engine_data); - o->descent = ENFN->font_descent_get(ENDT, o->engine_data); - o->max_ascent = ENFN->font_max_ascent_get(ENDT, o->engine_data); - o->max_descent = ENFN->font_max_descent_get(ENDT, o->engine_data); - } - else - { - o->ascent = 0; - o->descent = 0; - o->max_ascent = 0; - o->max_descent = 0; - } - obj->cur.geometry.w = 0; - obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b; -//// obj->cur.cache.geometry.validity = 0; + o->ascent = 0; + o->descent = 0; + o->max_ascent = 0; + o->max_descent = 0; } + _evas_object_text_recalc(obj); o->changed = 1; evas_object_change(obj); evas_object_clip_dirty(obj); @@ -319,6 +504,155 @@ evas_object_text_font_get(const Evas_Object *obj, const char **font, Evas_Font_S if (size) *size = o->cur.size; } + +/** + * @internal + * Create a new text layout item from the string and the format. + * + * @param c the context to work on - Not NULL. + * @param fmt the format to use. + * @param str the string to use. + */ +static Evas_Object_Text_Item * +_evas_object_text_item_new(Evas_Object *obj, Evas_Object_Text *o, + const Eina_Unicode *str, + size_t pos, size_t visual_pos, size_t len) +{ + Evas_Object_Text_Item *it; + + it = calloc(1, sizeof(Evas_Object_Text_Item)); + it->text = calloc(sizeof(Eina_Unicode), len + 1); + it->text_pos = pos; + it->visual_pos = visual_pos; + eina_unicode_strncpy(it->text, str + pos, len); + evas_common_text_props_bidi_set(&it->text_props, o->bidi_par_props, + it->text_pos); + evas_common_text_props_script_set(&it->text_props, it->text); + if (o->engine_data) + { + ENFN->font_text_props_info_create(ENDT, + o->engine_data, it->text, &it->text_props, + o->bidi_par_props, it->text_pos, len); + ENFN->font_string_size_get(ENDT, + o->engine_data, + it->text, &it->text_props, + &it->w, &it->h); + it->adv = ENFN->font_h_advance_get(ENDT, o->engine_data, it->text, + &it->text_props); + } + o->items = (Evas_Object_Text_Item *) + eina_inlist_append(EINA_INLIST_GET(o->items), EINA_INLIST_GET(it)); + return it; +} + +/** + * @internal + * Orders o->items according to the visual position. + * + * @param obj the evas object + * @param o the text object + */ +static void +_evas_object_text_item_order(Evas_Object *obj, Evas_Object_Text *o) +{ + (void) obj; +#ifdef BIDI_SUPPORT + /*FIXME: not very efficient, sort the items arrays. */ + /* Reorder if it's a bidi text */ + if (o->bidi_par_props) + { + Evas_Object_Text_Item *i, *j, *min; + i = o->items; + while (i) + { + min = i; + EINA_INLIST_FOREACH(i, j) + { + if (j->visual_pos < min->visual_pos) + { + min = j; + } + } + if (min != i) + { + o->items = (Evas_Object_Text_Item *) eina_inlist_remove(EINA_INLIST_GET(o->items), EINA_INLIST_GET(min)); + o->items = (Evas_Object_Text_Item *) eina_inlist_prepend_relative(EINA_INLIST_GET(o->items), EINA_INLIST_GET(min), EINA_INLIST_GET(i)); + } + + i = (Evas_Object_Text_Item *) EINA_INLIST_GET(min)->next; + } + } +#endif + + /* calculate the positions according to the order. */ + { + Evas_Object_Text_Item *it = o->items; + Evas_Coord x = 0; + + while (it) + { + it->x = x; + x += it->adv; + it = (Evas_Object_Text_Item *) EINA_INLIST_GET(it)->next; + } + } +} + +/** + * @internal + * Populates o->items with the items of the text according to text + * + * @param obj the evas object + * @param o the text object + * @param text the text to layout + */ +static void +_evas_object_text_layout(Evas_Object *obj, Evas_Object_Text *o, const Eina_Unicode *text) +{ + EvasBiDiStrIndex *v_to_l = NULL; + size_t pos, visual_pos; + int cutoff; + int len = eina_unicode_strlen(text); +#ifdef BIDI_SUPPORT + evas_bidi_paragraph_props_unref(o->bidi_par_props); + o->bidi_par_props = evas_bidi_paragraph_props_get(text); + evas_bidi_props_reorder_line(NULL, 0, len, o->bidi_par_props, &v_to_l); +#endif + visual_pos = pos = 0; + + do + { + cutoff = evas_common_language_script_end_of_run_get( + text + pos, + o->bidi_par_props, + pos, len - pos); + if (cutoff > 0) + { +#ifdef BIDI_SUPPORT + visual_pos = evas_bidi_position_logical_to_visual( + v_to_l, len, pos); +#else + visual_pos = pos; +#endif + _evas_object_text_item_new(obj, o, text, pos, visual_pos, cutoff); + pos += cutoff; + } + } + while (cutoff > 0); +#ifdef BIDI_SUPPORT + visual_pos = evas_bidi_position_logical_to_visual( + v_to_l, len, pos); +#else + visual_pos = pos; +#endif + _evas_object_text_item_new(obj, o, text, pos, visual_pos, len - pos); + + _evas_object_text_item_order(obj, o); + + if (v_to_l) free(v_to_l); +} + + /** * Sets the text to be displayed by the given evas text object. * @param obj Evas text object. @@ -339,63 +673,35 @@ evas_object_text_text_set(Evas_Object *obj, const char *_text) return; MAGIC_CHECK_END(); - text = evas_common_encoding_utf8_to_unicode(_text, &len); + if ((o->cur.utf8_text) && (_text) && (!strcmp(o->cur.utf8_text, _text))) + return; + text = eina_unicode_utf8_to_unicode(_text, &len); if (!text) text = eina_unicode_strdup(EINA_UNICODE_EMPTY_STRING); - if ((o->cur.text) && (text) && (!eina_unicode_strcmp(o->cur.text, text))) - { - free(text); - return; - } was = evas_object_is_in_output_rect(obj, obj->layer->evas->pointer.x, obj->layer->evas->pointer.y, 1, 1); /* DO II */ - /*Update intl_props*/ -#ifdef BIDI_SUPPORT - evas_bidi_paragraph_props_unref(o->cur.intl_props.props); - o->cur.intl_props.props = evas_bidi_paragraph_props_get(text); - evas_bidi_shape_string(text, &o->cur.intl_props, len); -#endif - if (o->cur.text) eina_ustringshare_del(o->cur.text); - if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text); + /*Update bidi_props*/ + + if (o->items) _evas_object_text_items_clear(o); if ((text) && (*text)) { - o->cur.text = eina_ustringshare_add(text); - o->cur.utf8_text = eina_stringshare_add(_text); - } + _evas_object_text_layout(obj, o, text); + eina_stringshare_replace(&o->cur.utf8_text, _text); + o->prev.utf8_text = NULL; + } else { - o->cur.text = NULL; - o->cur.utf8_text = NULL; + eina_stringshare_replace(&o->cur.utf8_text, NULL); } - - o->prev.text = NULL; - - if ((o->engine_data) && (o->cur.text)) + if (text) { - int w, h; - int l = 0, r = 0, t = 0, b = 0; - - ENFN->font_string_size_get(ENDT, - o->engine_data, - o->cur.text, &o->cur.intl_props, - &w, &h); - evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); - obj->cur.geometry.w = w + l + r; - obj->cur.geometry.h = h + t + b; -//// obj->cur.cache.geometry.validity = 0; - } - else - { - int t = 0, b = 0; - - evas_text_style_pad_get(o->cur.style, NULL, NULL, &t, &b); - obj->cur.geometry.w = 0; - obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b; -//// obj->cur.cache.geometry.validity = 0; + free(text); + text = NULL; } + _evas_object_text_recalc(obj); o->changed = 1; evas_object_change(obj); evas_object_clip_dirty(obj); @@ -434,6 +740,31 @@ evas_object_text_text_get(const Evas_Object *obj) } /** + * Retrieves the direction of the text currently being displayed in the + * text object. + * @param obj The given evas text object. + * @return the direction of the text + */ +EAPI Evas_BiDi_Direction +evas_object_text_direction_get(const Evas_Object *obj) +{ + Evas_Object_Text *o; + + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return EVAS_BIDI_DIRECTION_NATURAL; + MAGIC_CHECK_END(); + o = (Evas_Object_Text *)(obj->object_data); + MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT); + return EVAS_BIDI_DIRECTION_NATURAL; + MAGIC_CHECK_END(); + if (o->items) + { + return o->items->text_props.bidi.dir; + } + return EVAS_BIDI_DIRECTION_NATURAL; +} + +/** * To be documented. * * FIXME: To be fixed. @@ -536,8 +867,8 @@ evas_object_text_inset_get(const Evas_Object *obj) return 0; MAGIC_CHECK_END(); if (!o->engine_data) return 0; - if (!o->cur.text) return 0; - return ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text); + if (!o->items) return 0; + return ENFN->font_inset_get(ENDT, o->engine_data, &o->items->text_props); } /** @@ -559,8 +890,8 @@ evas_object_text_horiz_advance_get(const Evas_Object *obj) return 0; MAGIC_CHECK_END(); if (!o->engine_data) return 0; - if (!o->cur.text) return 0; - return ENFN->font_h_advance_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props); + if (!o->items) return 0; + return _evas_object_text_horiz_advance_get(obj, o); } /** @@ -582,8 +913,8 @@ evas_object_text_vert_advance_get(const Evas_Object *obj) return 0; MAGIC_CHECK_END(); if (!o->engine_data) return 0; - if (!o->cur.text) return o->ascent + o->descent; - return ENFN->font_v_advance_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props); + if (!o->items) return o->ascent + o->descent; + return _evas_object_text_vert_advance_get(obj, o); } /** @@ -619,9 +950,9 @@ evas_object_text_char_pos_get(const Evas_Object *obj, int pos, Evas_Coord *cx, E return EINA_FALSE; MAGIC_CHECK_END(); if (!o->engine_data) return EINA_FALSE; - if (!o->cur.text) return EINA_FALSE; - ret = ENFN->font_char_coords_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props, - pos, &x, &y, &w, &h); + if (!o->items || (pos < 0)) return EINA_FALSE; + ret = _evas_object_text_char_coords_get(obj, o, (size_t) pos, + &x, &y, &w, &h); evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); y += o->max_ascent - t; x -= l; @@ -669,12 +1000,8 @@ evas_object_text_last_up_to_pos(const Evas_Object *obj, Evas_Coord x, Evas_Coord return -1; MAGIC_CHECK_END(); if (!o->engine_data) return -1; - if (!o->cur.text) return -1; - return ENFN->font_last_up_to_pos(ENDT, - o->engine_data, - o->cur.text, &o->cur.intl_props, - x, - y - o->max_ascent); + if (!o->items) return -1; + return _evas_object_text_last_up_to_pos(obj, o, x, y - o->max_ascent); } /** @@ -698,14 +1025,9 @@ evas_object_text_char_coords_get(const Evas_Object *obj, Evas_Coord x, Evas_Coor return -1; MAGIC_CHECK_END(); if (!o->engine_data) return -1; - if (!o->cur.text) return -1; - ret = ENFN->font_char_at_coords_get(ENDT, - o->engine_data, - o->cur.text, &o->cur.intl_props, - x, - y - o->max_ascent, - &rx, &ry, - &rw, &rh); + if (!o->items) return -1; + ret = _evas_object_text_char_at_coords(obj, o, x, y - o->max_ascent, + &rx, &ry, &rw, &rh); evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); ry += o->max_ascent - t; rx -= l; @@ -753,7 +1075,7 @@ evas_object_text_style_set(Evas_Object *obj, Evas_Text_Style_Type style) evas_text_style_pad_get(o->cur.style, &pl, &pr, &pt, &pb); o->cur.style = style; evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); - if (o->cur.text) + if (o->items) obj->cur.geometry.w += (l - pl) + (r - pr); else obj->cur.geometry.w = 0; @@ -1344,7 +1666,7 @@ evas_string_char_next_get(const char *str, int pos, int *decoded) if (decoded) *decoded = 0; if ((!str) || (pos < 0)) return 0; p = pos; - d = evas_common_encoding_utf8_get_next(str, &p); + d = eina_unicode_utf8_get_next(str, &p); if (decoded) *decoded = d; return p; } @@ -1376,7 +1698,7 @@ evas_string_char_prev_get(const char *str, int pos, int *decoded) if (decoded) *decoded = 0; if ((!str) || (pos < 1)) return 0; p = pos; - d = evas_common_encoding_utf8_get_prev(str, &p); + d = eina_unicode_utf8_get_prev(str, &p); if (decoded) *decoded = d; return p; } @@ -1391,7 +1713,7 @@ EAPI int evas_string_char_len_get(const char *str) { if (!str) return 0; - return evas_common_encoding_utf8_get_len(str); + return eina_unicode_utf8_get_len(str); } /** @@ -1519,7 +1841,7 @@ evas_object_text_new(void) o->magic = MAGIC_OBJ_TEXT; o->prev = o->cur; #ifdef BIDI_SUPPORT - o->cur.intl_props.props = evas_bidi_paragraph_props_new(); + o->bidi_par_props = evas_bidi_paragraph_props_new(); #endif return o; } @@ -1535,13 +1857,13 @@ evas_object_text_free(Evas_Object *obj) return; MAGIC_CHECK_END(); /* free obj */ - if (o->cur.text) eina_ustringshare_del(o->cur.text); + if (o->items) _evas_object_text_items_clear(o); if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text); if (o->cur.font) eina_stringshare_del(o->cur.font); if (o->cur.source) eina_stringshare_del(o->cur.source); if (o->engine_data) evas_font_free(obj->layer->evas, o->engine_data); #ifdef BIDI_SUPPORT - evas_bidi_props_clean(&o->cur.intl_props); + evas_bidi_paragraph_props_unref(o->bidi_par_props); #endif o->magic = 0; EVAS_MEMPOOL_FREE(_mp_obj, o); @@ -1552,6 +1874,7 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur { int i, j; Evas_Object_Text *o; + Evas_Object_Text_Item *it; const char vals[5][5] = { {0, 1, 2, 1, 0}, @@ -1615,12 +1938,12 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur (((int)object->sub.col.a) * (amul)) / 255); #define DRAW_TEXT(ox, oy) \ - if ((o->engine_data) && (o->cur.text)) \ + if ((o->engine_data) && (it->text)) \ ENFN->font_draw(output, \ context, \ surface, \ o->engine_data, \ - obj->cur.geometry.x + x + sl + ox, \ + obj->cur.geometry.x + x + sl + ox + it->x, \ obj->cur.geometry.y + y + st + oy + \ (int) \ (((o->max_ascent * obj->cur.geometry.h) / obj->cur.geometry.h) - 0.5), \ @@ -1628,116 +1951,102 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur obj->cur.geometry.h, \ obj->cur.geometry.w, \ obj->cur.geometry.h, \ - o->cur.text, &o->cur.intl_props); -#if 0 -#define DRAW_TEXT(ox, oy) \ - if ((o->engine_data) && (o->cur.text)) \ - ENFN->font_draw(output, \ - context, \ - surface, \ - o->engine_data, \ - obj->cur.cache.geometry.x + x + sl + ox, \ - obj->cur.cache.geometry.y + y + st + oy + \ - (int) \ - (((o->max_ascent * obj->cur.cache.geometry.h) / obj->cur.geometry.h) - 0.5), \ - obj->cur.cache.geometry.w, \ - obj->cur.cache.geometry.h, \ - obj->cur.geometry.w, \ - obj->cur.geometry.h, \ - o->cur.text, &o->cur.intl_props); -#endif - /* shadows */ - if (o->cur.style == EVAS_TEXT_STYLE_SHADOW) + it->text, &it->text_props); + EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it) { - COLOR_SET(o, cur, shadow); - DRAW_TEXT(1, 1); + /* shadows */ + if (o->cur.style == EVAS_TEXT_STYLE_SHADOW) + { + COLOR_SET(o, cur, shadow); + DRAW_TEXT(1, 1); + } + else if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || + (o->cur.style == EVAS_TEXT_STYLE_FAR_SHADOW)) + { + COLOR_SET(o, cur, shadow); + DRAW_TEXT(2, 2); + } + else if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW) || + (o->cur.style == EVAS_TEXT_STYLE_FAR_SOFT_SHADOW)) + { + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + if (vals[i][j] != 0) + { + COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50); + DRAW_TEXT(i, j); + } + } + } + } + else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_SHADOW) + { + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + if (vals[i][j] != 0) + { + COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50); + DRAW_TEXT(i - 1, j - 1); + } + } + } + } + + /* glows */ + if (o->cur.style == EVAS_TEXT_STYLE_GLOW) + { + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + if (vals[i][j] != 0) + { + COLOR_SET_AMUL(o, cur, glow, vals[i][j] * 50); + DRAW_TEXT(i - 2, j - 2); + } + } + } + COLOR_SET(o, cur, glow2); + DRAW_TEXT(-1, 0); + DRAW_TEXT(1, 0); + DRAW_TEXT(0, -1); + DRAW_TEXT(0, 1); + } + + /* outlines */ + if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE) || + (o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || + (o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW)) + { + COLOR_SET(o, cur, outline); + DRAW_TEXT(-1, 0); + DRAW_TEXT(1, 0); + DRAW_TEXT(0, -1); + DRAW_TEXT(0, 1); + } + else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_OUTLINE) + { + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + if (((i != 2) || (j != 2)) && (vals[i][j] != 0)) + { + COLOR_SET_AMUL(o, cur, outline, vals[i][j] * 50); + DRAW_TEXT(i - 2, j - 2); + } + } + } + } + + /* normal text */ + COLOR_ONLY_SET(obj, cur.cache, clip); + DRAW_TEXT(0, 0); } - else if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || - (o->cur.style == EVAS_TEXT_STYLE_FAR_SHADOW)) - { - COLOR_SET(o, cur, shadow); - DRAW_TEXT(2, 2); - } - else if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW) || - (o->cur.style == EVAS_TEXT_STYLE_FAR_SOFT_SHADOW)) - { - for (j = 0; j < 5; j++) - { - for (i = 0; i < 5; i++) - { - if (vals[i][j] != 0) - { - COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50); - DRAW_TEXT(i, j); - } - } - } - } - else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_SHADOW) - { - for (j = 0; j < 5; j++) - { - for (i = 0; i < 5; i++) - { - if (vals[i][j] != 0) - { - COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50); - DRAW_TEXT(i - 1, j - 1); - } - } - } - } - - /* glows */ - if (o->cur.style == EVAS_TEXT_STYLE_GLOW) - { - for (j = 0; j < 5; j++) - { - for (i = 0; i < 5; i++) - { - if (vals[i][j] != 0) - { - COLOR_SET_AMUL(o, cur, glow, vals[i][j] * 50); - DRAW_TEXT(i - 2, j - 2); - } - } - } - COLOR_SET(o, cur, glow2); - DRAW_TEXT(-1, 0); - DRAW_TEXT(1, 0); - DRAW_TEXT(0, -1); - DRAW_TEXT(0, 1); - } - - /* outlines */ - if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE) || - (o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || - (o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW)) - { - COLOR_SET(o, cur, outline); - DRAW_TEXT(-1, 0); - DRAW_TEXT(1, 0); - DRAW_TEXT(0, -1); - DRAW_TEXT(0, 1); - } - else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_OUTLINE) - { - for (j = 0; j < 5; j++) - { - for (i = 0; i < 5; i++) - { - if (((i != 2) || (j != 2)) && (vals[i][j] != 0)) - { - COLOR_SET_AMUL(o, cur, outline, vals[i][j] * 50); - DRAW_TEXT(i - 2, j - 2); - } - } - } - } - - /* normal text */ - COLOR_ONLY_SET(obj, cur.cache, clip); - DRAW_TEXT(0, 0); } static void @@ -1827,14 +2136,8 @@ evas_object_text_render_pre(Evas_Object *obj) if (o->changed) { if ((o->cur.size != o->prev.size) || - ((o->cur.font) && (o->prev.font) && - (strcmp(o->cur.font, o->prev.font))) || - ((o->cur.font) && (!o->prev.font)) || - ((!o->cur.font) && (o->prev.font)) || - ((o->cur.text) && (o->prev.text) && - (eina_unicode_strcmp(o->cur.text, o->prev.text))) || - ((o->cur.text) && (!o->prev.text)) || - ((!o->cur.text) && (o->prev.text)) || + ((o->cur.font != o->prev.font)) || + ((o->cur.utf8_text != o->prev.utf8_text)) || ((o->cur.style != o->prev.style)) || ((o->cur.shadow.r != o->prev.shadow.r)) || ((o->cur.shadow.g != o->prev.shadow.g)) || @@ -1961,30 +2264,7 @@ _evas_object_text_rehint(Evas_Object *obj) obj->layer->evas->pointer.x, obj->layer->evas->pointer.y, 1, 1); /* DO II */ - o->prev.text = NULL; - if ((o->engine_data) && (o->cur.text)) - { - int w, h; - int l = 0, r = 0, t = 0, b = 0; - - ENFN->font_string_size_get(ENDT, - o->engine_data, - o->cur.text, &o->cur.intl_props, - &w, &h); - evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); - obj->cur.geometry.w = w + l + r; - obj->cur.geometry.h = h + t + b; -//// obj->cur.cache.geometry.validity = 0; - } - else - { - int t = 0, b = 0; - - evas_text_style_pad_get(o->cur.style, NULL, NULL, &t, &b); - obj->cur.geometry.w = 0; - obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b; -//// obj->cur.cache.geometry.validity = 0; - } + _evas_object_text_recalc(obj); o->changed = 1; evas_object_change(obj); evas_object_clip_dirty(obj); @@ -2000,3 +2280,44 @@ _evas_object_text_rehint(Evas_Object *obj) NULL); evas_object_inform_call_resize(obj); } + +static void +_evas_object_text_recalc(Evas_Object *obj) +{ + Evas_Object_Text *o; + Eina_Unicode *text = NULL; + o = (Evas_Object_Text *)(obj->object_data); + + if (o->items) _evas_object_text_items_clear(o); + if (o->cur.utf8_text) + text = eina_unicode_utf8_to_unicode(o->cur.utf8_text, + NULL); + + if (!text) text = eina_unicode_strdup(EINA_UNICODE_EMPTY_STRING); + + _evas_object_text_layout(obj, o, text); + + if (text) free(text); + + if ((o->engine_data) && (o->items)) + { + int w, h; + int l = 0, r = 0, t = 0, b = 0; + + _evas_object_text_string_size_get(obj, o, &w, &h); + evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b); + obj->cur.geometry.w = w + l + r; + obj->cur.geometry.h = h + t + b; +//// obj->cur.cache.geometry.validity = 0; + } + else + { + int t = 0, b = 0; + + evas_text_style_pad_get(o->cur.style, NULL, NULL, &t, &b); + obj->cur.geometry.w = 0; + obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b; +//// obj->cur.cache.geometry.validity = 0; + } +} + diff --git a/src/lib/canvas/evas_object_textblock.c b/src/lib/canvas/evas_object_textblock.c index eb75d33..3f81b65 100644 --- a/src/lib/canvas/evas_object_textblock.c +++ b/src/lib/canvas/evas_object_textblock.c @@ -132,6 +132,8 @@ * @subsection textblock_layout The layout system * @todo write @ref textblock_layout */ +#include + #include "evas_common.h" #include "evas_private.h" @@ -189,6 +191,12 @@ typedef struct _Evas_Object_Textblock_Line Evas_Object_Textblock_Line; typedef struct _Evas_Object_Textblock_Item Evas_Object_Textblock_Item; /** * @internal + * @typedef Evas_Object_Textblock_Item + * A layouting text item. + */ +typedef struct _Evas_Object_Textblock_Text_Item Evas_Object_Textblock_Text_Item; +/** + * @internal * @typedef Evas_Object_Textblock_Format_Item * A layouting format item. */ @@ -235,6 +243,7 @@ struct _Evas_Object_Textblock_Node_Text char *utf8; Evas_Object_Textblock_Node_Format *format_node; Evas_BiDi_Paragraph_Props *bidi_props; + Eina_Bool dirty : 1; }; struct _Evas_Object_Textblock_Node_Format @@ -258,47 +267,90 @@ struct _Evas_Object_Textblock_Node_Format * A convinience macro for casting to a format node. */ #define _NODE_FORMAT(x) ((Evas_Object_Textblock_Node_Format *) (x)) +/** + * @internal + * @def _ITEM(x) + * A convinience macro for casting to a generic item. + */ +#define _ITEM(x) ((Evas_Object_Textblock_Item *) (x)) +/** + * @internal + * @def _ITEM_TEXT(x) + * A convinience macro for casting to a text item. + */ +#define _ITEM_TEXT(x) ((Evas_Object_Textblock_Text_Item *) (x)) +/** + * @internal + * @def _ITEM_FORMAT(x) + * A convinience macro for casting to a format item. + */ +#define _ITEM_FORMAT(x) ((Evas_Object_Textblock_Format_Item *) (x)) struct _Evas_Object_Textblock_Paragraph { EINA_INLIST; Evas_Object_Textblock_Line *lines; + Evas_Object_Textblock_Node_Text *text_node; + Eina_List *logical_items; int x, y, w, h; - int par_no; + int line_no; }; struct _Evas_Object_Textblock_Line { EINA_INLIST; Evas_Object_Textblock_Item *items; - Evas_Object_Textblock_Format_Item *format_items; + Evas_Object_Textblock_Paragraph *par; + Evas_Object_Textblock_Text_Item *ellip_ti; int x, y, w, h; int baseline; int line_no; }; +typedef enum _Evas_Textblock_Item_Type +{ + EVAS_TEXTBLOCK_ITEM_TEXT, + EVAS_TEXTBLOCK_ITEM_FORMAT, +} Evas_Textblock_Item_Type; + struct _Evas_Object_Textblock_Item { EINA_INLIST; + Evas_Textblock_Item_Type type; + Evas_Object_Textblock_Node_Text *text_node; + Evas_Object_Textblock_Format *format; + size_t text_pos; +#ifdef BIDI_SUPPORT + size_t visual_pos; +#endif + Evas_Coord adv, x, w, h; + Eina_Bool merge : 1; /* Indicates whether this + item should merge to the + previous item or not */ + Eina_Bool visually_deleted : 1; + /* Indicates whether this + item is used in the visual + layout or not. */ +}; + +struct _Evas_Object_Textblock_Text_Item +{ + Evas_Object_Textblock_Item parent; Eina_Unicode *text; - Evas_Object_Textblock_Format *format; - Evas_Object_Textblock_Node_Text *source_node; - int x, w, h; + Evas_Text_Props text_props; int inset, baseline; - size_t source_pos; - Evas_BiDi_Props bidi_props; }; struct _Evas_Object_Textblock_Format_Item { - EINA_INLIST; + Evas_Object_Textblock_Item parent; + Evas_BiDi_Direction bidi_dir; const char *item; Evas_Object_Textblock_Node_Format *source_node; - int x, w, h, y, ascent, descent; + int y, ascent, descent; unsigned char vsize : 2; unsigned char size : 2; unsigned char formatme : 1; - unsigned char ___padding___ : 3; }; struct _Evas_Object_Textblock_Format @@ -329,9 +381,11 @@ struct _Evas_Object_Textblock_Format int linegap; double linerelgap; double linefill; + double ellipsis; unsigned char style; unsigned char wrap_word : 1; unsigned char wrap_char : 1; + unsigned char wrap_mixed : 1; unsigned char underline : 1; unsigned char underline2 : 1; unsigned char strikethrough : 1; @@ -341,7 +395,7 @@ struct _Evas_Object_Textblock_Format struct _Evas_Textblock_Style { - char *style_text; + const char *style_text; char *default_tag; Evas_Object_Style_Tag *tags; Eina_List *objects; @@ -378,6 +432,8 @@ struct _Evas_Object_Textblock } formatted, native; unsigned char redraw : 1; unsigned char changed : 1; + unsigned char content_changed : 1; + Eina_Bool newline_is_ps : 1; }; /* private methods for textblock objects */ @@ -458,20 +514,21 @@ static Eina_Bool _evas_textblock_format_is_visible(const char *s); static void _evas_textblock_node_format_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Format *n, int visual_adjustment); static void _evas_textblock_node_format_free(Evas_Object_Textblock_Node_Format *n); static void _evas_textblock_node_text_free(Evas_Object_Textblock_Node_Text *n); -static void _evas_textblock_changed(Evas_Object_Textblock *o, Evas_Object *obj); +static void _evas_textblock_text_node_changed(Evas_Object_Textblock *o, Evas_Object *obj, Evas_Object_Textblock_Node_Text *n); static void _evas_textblock_cursors_update_offset(const Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Text *n, size_t start, int offset); 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); /* styles */ /** * @internal - * Clears the textblock style passed. + * Clears the textblock style passed except for the style_text which is replaced. * @param ts The ts to be cleared. Must not be NULL. + * @param style_text the style's text. */ static void -_style_clear(Evas_Textblock_Style *ts) +_style_replace(Evas_Textblock_Style *ts, const char *style_text) { - if (ts->style_text) free(ts->style_text); + eina_stringshare_replace(&ts->style_text, style_text); if (ts->default_tag) free(ts->default_tag); while (ts->tags) { @@ -483,13 +540,23 @@ _style_clear(Evas_Textblock_Style *ts) free(tag->replace); free(tag); } - ts->style_text = NULL; ts->default_tag = NULL; ts->tags = NULL; } /** * @internal + * Clears the textblock style passed. + * @param ts The ts to be cleared. Must not be NULL. + */ +static void +_style_clear(Evas_Textblock_Style *ts) +{ + _style_replace(ts, NULL); +} + +/** + * @internal * Searches inside the tags stored in the style for the tag who's * replacement is s of size replace_len; * @param ts The ts to be cleared. Must not be NULL. @@ -559,7 +626,9 @@ _nodes_clear(const Evas_Object *obj) Evas_Object_Textblock_Node_Text *n; n = o->text_nodes; - _evas_textblock_node_text_remove(o, n); + o->text_nodes = _NODE_TEXT(eina_inlist_remove( + EINA_INLIST_GET(o->text_nodes), EINA_INLIST_GET(n))); + _evas_textblock_node_text_free(n); } while (o->format_nodes) { @@ -591,33 +660,47 @@ _format_unref_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt) /** * @internal - * Free a layout line. + * Free a layout item * @param obj The evas object, must not be NULL. - * @param ln the layout line to be freed, must not be NULL. + * @param ln the layout line on which the item is in, must not be NULL. + * @param it the layout item to be freed */ static void -_line_free(const Evas_Object *obj, Evas_Object_Textblock_Line *ln) +_item_free(const Evas_Object *obj, Evas_Object_Textblock_Line *ln, Evas_Object_Textblock_Item *it) { - while (ln->items) + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) { - Evas_Object_Textblock_Item *it; + Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it); - it = (Evas_Object_Textblock_Item *)ln->items; - ln->items = (Evas_Object_Textblock_Item *)eina_inlist_remove(EINA_INLIST_GET(ln->items), EINA_INLIST_GET(ln->items)); - if (it->text) free(it->text); - _format_unref_free(obj, it->format); - free(it); + evas_common_text_props_content_unref(&ti->text_props); + if (ti->text) free(ti->text); } - while (ln->format_items) + else { - Evas_Object_Textblock_Format_Item *fi; + Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it); - fi = (Evas_Object_Textblock_Format_Item *)ln->format_items; - ln->format_items = (Evas_Object_Textblock_Format_Item *)eina_inlist_remove(EINA_INLIST_GET(ln->format_items), - EINA_INLIST_GET(ln->format_items)); if (fi->item) eina_stringshare_del(fi->item); - free(fi); } + _format_unref_free(obj, it->format); + if (ln) + { + ln->items = (Evas_Object_Textblock_Item *) eina_inlist_remove( + EINA_INLIST_GET(ln->items), EINA_INLIST_GET(ln->items)); + } + free(it); +} + +/** + * @internal + * Free a layout line. + * @param obj The evas object, must not be NULL. + * @param ln the layout line to be freed, must not be NULL. + */ +static void +_line_free(const Evas_Object *obj, Evas_Object_Textblock_Line *ln) +{ + /* Items are freed from the logical list, except for the ellip item */ + if (ln->ellip_ti) _item_free(obj, NULL, _ITEM(ln->ellip_ti)); if (ln) free(ln); } @@ -1060,6 +1143,7 @@ static const char *linegapstr = NULL; static const char *linerelgapstr = NULL; static const char *itemstr = NULL; static const char *linefillstr = NULL; +static const char *ellipsisstr = NULL; static const char *passwordstr = NULL; /** @@ -1100,6 +1184,7 @@ _format_command_init(void) linerelgapstr = eina_stringshare_add("linerelgap"); itemstr = eina_stringshare_add("item"); linefillstr = eina_stringshare_add("linefill"); + ellipsisstr = eina_stringshare_add("ellipsis"); passwordstr = eina_stringshare_add("password"); } format_refcount++; @@ -1143,6 +1228,7 @@ _format_command_shutdown(void) eina_stringshare_del(linerelgapstr); eina_stringshare_del(itemstr); eina_stringshare_del(linefillstr); + eina_stringshare_del(ellipsisstr); eina_stringshare_del(passwordstr); } @@ -1325,17 +1411,21 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char if (!strcmp(tmp_param, "word")) { fmt->wrap_word = 1; - fmt->wrap_char = 0; + fmt->wrap_char = fmt->wrap_mixed = 0; } else if (!strcmp(tmp_param, "char")) { - fmt->wrap_word = 0; + fmt->wrap_word = fmt->wrap_mixed = 0; fmt->wrap_char = 1; } + else if (!strcmp(tmp_param, "mixed")) + { + fmt->wrap_word = fmt->wrap_char = 0; + fmt->wrap_mixed = 1; + } else { - fmt->wrap_word = 0; - fmt->wrap_char = 0; + fmt->wrap_word = fmt->wrap_mixed = fmt->wrap_char = 0; } } else if (cmd == left_marginstr) @@ -1484,6 +1574,13 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char } } } + else if (cmd == ellipsisstr) + { + char *endptr = NULL; + fmt->ellipsis = strtod(tmp_param, &endptr); + if ((fmt->ellipsis < 0.0) || (fmt->ellipsis > 1.0)) + fmt->ellipsis = -1.0; + } else if (cmd == passwordstr) { if (!strcmp(tmp_param, "off")) @@ -1709,6 +1806,8 @@ struct _Ctxt Eina_Bool align_auto; }; +static void _layout_text_add_logical_item(Ctxt *c, Evas_Object_Textblock_Text_Item *ti, Eina_List *rel); +static void _text_item_update_sizes(Ctxt *c, Evas_Object_Textblock_Text_Item *ti); /** * @internal * Adjust the ascent/descent of the format and context. @@ -1778,6 +1877,7 @@ _layout_line_new(Ctxt *c, Evas_Object_Textblock_Format *fmt) c->x = 0; c->maxascent = c->maxdescent = 0; c->ln->line_no = -1; + c->ln->par = c->par; _layout_format_ascent_descent_adjust(c, fmt); } @@ -1788,20 +1888,21 @@ _layout_line_new(Ctxt *c, Evas_Object_Textblock_Format *fmt) * @param c The context to work on - Not NULL. */ static void -_layout_paragraph_new(Ctxt *c) +_layout_paragraph_new(Ctxt *c, Evas_Object_Textblock_Node_Text *n) { c->par = calloc(1, sizeof(Evas_Object_Textblock_Paragraph)); c->paragraphs = (Evas_Object_Textblock_Paragraph *)eina_inlist_append(EINA_INLIST_GET(c->paragraphs), EINA_INLIST_GET(c->par)); - c->x = 0; - c->par->par_no= -1; + c->ln = NULL; + c->par->text_node = n; + c->par->line_no = -1; } /** * @internal - * Free the layout paragraph and all of it's lines. + * Free the visual lines in the paragraph (logical items are kept) */ static void -_paragraph_free(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *par) +_paragraph_clear(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *par) { while (par->lines) { @@ -1811,6 +1912,27 @@ _paragraph_free(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *par) par->lines = (Evas_Object_Textblock_Line *)eina_inlist_remove(EINA_INLIST_GET(par->lines), EINA_INLIST_GET(par->lines)); _line_free(obj, ln); } + par->line_no = -1; +} + +/** + * @internal + * Free the layout paragraph and all of it's lines and logical items. + */ +static void +_paragraph_free(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *par) +{ + _paragraph_clear(obj, par); + + { + Eina_List *i, *i_prev; + Evas_Object_Textblock_Item *it; + EINA_LIST_FOREACH_SAFE(par->logical_items, i, i_prev, it) + { + _item_free(obj, NULL, it); + } + eina_list_free(par->logical_items); + } free(par); } @@ -1825,6 +1947,28 @@ static void _paragraphs_clear(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *pars) { Evas_Object_Textblock *o; + Evas_Object_Textblock_Paragraph *par; + o = (Evas_Object_Textblock *)(obj->object_data); + + EINA_INLIST_FOREACH(EINA_INLIST_GET(pars), par) + { + _paragraph_clear(obj, par); + } +} + +/** + * @internal + * Free the paragraphs from the inlist pars, the difference between this and + * _paragraphs_clear is that the latter keeps the logical items and the par + * items, while the former frees them as well. + * + * @param obj the evas object - Not NULL. + * @param pars the paragraphs to clean - Not NULL. + */ +static void +_paragraphs_free(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *pars) +{ + Evas_Object_Textblock *o; o = (Evas_Object_Textblock *)(obj->object_data); while (pars) { @@ -1935,12 +2079,11 @@ static inline double _layout_line_align_get(Ctxt *c) { #ifdef BIDI_SUPPORT - if (c->align_auto && c->ln && c->ln->items) + if (c->align_auto && c->ln) { - if (c->ln->items->source_node && - + if (c->ln->items && c->ln->items->text_node && EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL( - c->ln->items->source_node->bidi_props)) + c->ln->items->text_node->bidi_props)) { /* Align right*/ return 1.0; @@ -1957,81 +2100,242 @@ _layout_line_align_get(Ctxt *c) /** * @internal - * Create a new line and append it to the lines in the context. + * Reorder the items in visual order + * + * @param line the line to reorder + */ +static void +_layout_line_order(Ctxt *c __UNUSED__, Evas_Object_Textblock_Line *line) +{ + /*FIXME: do it a bit more efficient - not very efficient ATM. */ +#ifdef BIDI_SUPPORT + Evas_Object_Textblock_Item *it; + EvasBiDiStrIndex *v_to_l = NULL; + size_t start, end; + size_t len; + + if (line->items && line->items->text_node && + line->items->text_node->bidi_props) + { + Evas_BiDi_Paragraph_Props *props; + props = line->items->text_node->bidi_props; + start = end = line->items->text_pos; + + /* Find the first and last positions in the line */ + + EINA_INLIST_FOREACH(line->items, it) + { + if (it->text_pos < start) + { + start = it->text_pos; + } + else + { + int tlen; + tlen = (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? + _ITEM_TEXT(it)->text_props.text_len : 1; + if (it->text_pos + tlen > end) + { + end = it->text_pos + tlen; + } + } + } + + len = end - start; + evas_bidi_props_reorder_line(NULL, start, len, props, &v_to_l); + + /* Update visual pos */ + { + Evas_Object_Textblock_Item *i; + i = line->items; + while (i) + { + i->visual_pos = evas_bidi_position_logical_to_visual( + v_to_l, len, i->text_pos - start); + i = (Evas_Object_Textblock_Item *) EINA_INLIST_GET(i)->next; + } + } + + /*FIXME: not very efficient, sort the items arrays. Anyhow, should only + * reorder if it's a bidi paragraph */ + { + Evas_Object_Textblock_Item *i, *j, *min; + i = line->items; + while (i) + { + min = i; + EINA_INLIST_FOREACH(i, j) + { + if (j->visual_pos < min->visual_pos) + { + min = j; + } + } + if (min != i) + { + line->items = (Evas_Object_Textblock_Item *) eina_inlist_remove(EINA_INLIST_GET(line->items), EINA_INLIST_GET(min)); + line->items = (Evas_Object_Textblock_Item *) eina_inlist_prepend_relative(EINA_INLIST_GET(line->items), EINA_INLIST_GET(min), EINA_INLIST_GET(i)); + } + + i = (Evas_Object_Textblock_Item *) EINA_INLIST_GET(min)->next; + } + } + } + + if (v_to_l) free(v_to_l); +#endif +} + +/** + * @internal + * Order the items in the line, update it's properties and update it's + * corresponding paragraph. * * @param c the context to work on - Not NULL. * @param fmt the format to use. + * @param add_line true if we should create a line, false otherwise. */ static void -_layout_line_advance(Ctxt *c, Evas_Object_Textblock_Format *fmt) +_layout_line_finalize(Ctxt *c, Evas_Object_Textblock_Format *fmt) { Evas_Object_Textblock_Item *it; - Evas_Object_Textblock_Format_Item *fi; + Eina_Bool no_text = EINA_TRUE; + Evas_Coord x = 0; + + _layout_line_order(c, c->ln); c->maxascent = c->maxdescent = 0; - if (!c->ln->items) + EINA_INLIST_FOREACH(c->ln->items, it) + { + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + no_text = EINA_FALSE; + break; + } + } + + if (no_text) _layout_format_ascent_descent_adjust(c, fmt); + EINA_INLIST_FOREACH(c->ln->items, it) { - int endx; - - if (it->format->font.font) - it->baseline = c->ENFN->font_max_ascent_get(c->ENDT, it->format->font.font); - _layout_format_ascent_descent_adjust(c, it->format); - endx = it->x + it->w; - if (endx > c->ln->w) c->ln->w = endx; - } - EINA_INLIST_FOREACH(c->ln->format_items, fi) - { - int endx; - - if (!fi->formatme) continue; - endx = fi->x + fi->w; - if (endx > c->ln->w) c->ln->w = endx; - switch (fi->size) - { - case SIZE: - case SIZE_ABS: - switch (fi->vsize) - { - case VSIZE_FULL: - if (fi->h > (c->maxdescent + c->maxascent)) - { - c->maxascent += fi->h - (c->maxdescent + c->maxascent); - fi->y = -c->maxascent; - } - else - fi->y = -(fi->h - c->maxdescent); - break; - case VSIZE_ASCENT: - if (fi->h > c->maxascent) - { - c->maxascent = fi->h; - fi->y = -fi->h; - } - else - fi->y = -fi->h; - break; - default: - break; - } - break; - case SIZE_REL: - switch (fi->vsize) - { - case VSIZE_FULL: - case VSIZE_ASCENT: - fi->y = -fi->ascent; - break; - default: - break; - } - break; - default: - break; + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it); + if (ti->parent.format->font.font) + ti->baseline = c->ENFN->font_max_ascent_get(c->ENDT, ti->parent.format->font.font); + _layout_format_ascent_descent_adjust(c, ti->parent.format); + } + else + { + Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it); + if (!fi->formatme) goto loop_advance; + fi->ascent = c->maxascent; + fi->descent = c->maxdescent; + /* Adjust sizes according to current line height/scale */ + { + Evas_Coord w, h; + const char *p, *s; + + s = eina_strbuf_string_get(fi->source_node->format); + w = fi->parent.w; + h = fi->parent.h; + switch (fi->size) + { + case SIZE: + if (!strncmp(s, "item", 4)) + { + p = strstr(s, " size="); + if (p) + { + p += 6; + if (sscanf(p, "%ix%i", &w, &h) == 2) + { + w = w * c->obj->cur.scale; + h = h * c->obj->cur.scale; + } + } + } + break; + case SIZE_REL: + p = strstr((char *) s, " relsize="); + p += 9; + if (sscanf(p, "%ix%i", &w, &h) == 2) + { + int sz = 1; + if (fi->vsize == VSIZE_FULL) + { + sz = c->maxdescent + c->maxascent; + } + else if (fi->vsize == VSIZE_ASCENT) + { + sz = c->maxascent; + } + w = (w * sz) / h; + h = sz; + } + break; + case SIZE_ABS: + /* Nothing to do */ + default: + break; + } + fi->parent.w = fi->parent.adv = w; + fi->parent.h = h; + } + + switch (fi->size) + { + case SIZE: + case SIZE_ABS: + switch (fi->vsize) + { + case VSIZE_FULL: + if (fi->parent.h > (c->maxdescent + c->maxascent)) + { + c->maxascent += fi->parent.h - (c->maxdescent + c->maxascent); + fi->y = -c->maxascent; + } + else + fi->y = -(fi->parent.h - c->maxdescent); + break; + case VSIZE_ASCENT: + if (fi->parent.h > c->maxascent) + { + c->maxascent = fi->parent.h; + fi->y = -fi->parent.h; + } + else + fi->y = -fi->parent.h; + break; + default: + break; + } + break; + case SIZE_REL: + switch (fi->vsize) + { + case VSIZE_FULL: + case VSIZE_ASCENT: + fi->y = -fi->ascent; + break; + default: + break; + } + break; + default: + break; + } } + +loop_advance: + it->x = x; + x += it->adv; + + if (x > c->ln->w) c->ln->w = x; } - c->ln->y = c->y + c->o->style_pad.t; + + c->ln->y = (c->y - c->par->y) + c->o->style_pad.t; c->ln->h = c->maxascent + c->maxdescent; c->ln->baseline = c->maxascent; if (c->have_underline2) @@ -2042,7 +2346,12 @@ _layout_line_advance(Ctxt *c, Evas_Object_Textblock_Format *fmt) { if (c->maxdescent < 2) c->underline_extend = 2 - c->maxdescent; } - c->ln->line_no = c->line_no; + /* Update the paragraphs line number. */ + if (c->par->line_no == -1) + { + c->par->line_no = c->line_no; + } + c->ln->line_no = c->line_no - c->ln->par->line_no; c->line_no++; c->y += c->maxascent + c->maxdescent; if (c->w >= 0) @@ -2051,36 +2360,55 @@ _layout_line_advance(Ctxt *c, Evas_Object_Textblock_Format *fmt) ((c->w - c->ln->w - c->o->style_pad.l - c->o->style_pad.r - c->marginl - c->marginr) * _layout_line_align_get(c)); - if ((c->ln->x + c->ln->w + c->marginr - c->o->style_pad.l) > c->wmax) - c->wmax = c->ln->x + c->ln->w + c->marginl + c->marginr - c->o->style_pad.l; + if ((c->par->x + c->ln->x + c->ln->w + c->marginr - c->o->style_pad.l) > c->wmax) + c->wmax = c->par->x + c->ln->x + c->ln->w + c->marginl + c->marginr - c->o->style_pad.l; } else { c->ln->x = c->marginl + c->o->style_pad.l; - if ((c->ln->x + c->ln->w + c->marginr - c->o->style_pad.l) > c->wmax) - c->wmax = c->ln->x + c->ln->w + c->marginl + c->marginr - c->o->style_pad.l; + if ((c->par->x + c->ln->x + c->ln->w + c->marginr - c->o->style_pad.l) > c->wmax) + c->wmax = c->par->x + c->ln->x + c->ln->w + c->marginl + c->marginr - c->o->style_pad.l; } + c->par->h = c->ln->y + c->ln->h; + if (c->ln->w + c->ln->x > c->par->w) + c->par->w = c->ln->x + c->ln->w; +} + +/** + * @internal + * Create a new line and append it to the lines in the context. + * + * @param c the context to work on - Not NULL. + * @param fmt the format to use. + * @param add_line true if we should create a line, false otherwise. + */ +static void +_layout_line_advance(Ctxt *c, Evas_Object_Textblock_Format *fmt) +{ + _layout_line_finalize(c, fmt); _layout_line_new(c, fmt); } /** * @internal - * Create a new layout item from the string and the format. + * Create a new text layout item from the string and the format. * * @param c the context to work on - Not NULL. * @param fmt the format to use. * @param str the string to use. + * @param len the length of the string. */ -static Evas_Object_Textblock_Item * -_layout_item_new(Ctxt *c __UNUSED__, Evas_Object_Textblock_Format *fmt, const Eina_Unicode *str) +static Evas_Object_Textblock_Text_Item * +_layout_text_item_new(Ctxt *c __UNUSED__, Evas_Object_Textblock_Format *fmt, const Eina_Unicode *str, size_t len) { - Evas_Object_Textblock_Item *it; + Evas_Object_Textblock_Text_Item *ti; - it = calloc(1, sizeof(Evas_Object_Textblock_Item)); - it->format = fmt; - it->format->ref++; - it->text = eina_unicode_strdup(str); - return it; + ti = calloc(1, sizeof(Evas_Object_Textblock_Text_Item)); + ti->parent.format = fmt; + ti->parent.format->ref++; + ti->text = eina_unicode_strndup(str, len); + ti->parent.type = EVAS_TEXTBLOCK_ITEM_TEXT; + return ti; } /** @@ -2090,40 +2418,144 @@ _layout_item_new(Ctxt *c __UNUSED__, Evas_Object_Textblock_Format *fmt, const Ei * @param c the context to work on - Not NULL. * @param fmt the format to use. - Not NULL. * @param it the item to check - Not null. - * @return -1 on error, cutoff index on success. + * @return -1 if there is no cutoff (either because there is really none, + * or because of an error), cutoff index on success. */ static int -_layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textblock_Item *it) +_layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt, + const Evas_Object_Textblock_Text_Item *ti) { if (fmt->font.font) - return c->ENFN->font_last_up_to_pos(c->ENDT, fmt->font.font, it->text, &it->bidi_props, - c->w - - c->o->style_pad.l - - c->o->style_pad.r - - c->marginl - - c->marginr - - c->x, - 0); + { + Evas_Coord x; + x = c->w - c->o->style_pad.l - c->o->style_pad.r - c->marginl - + c->marginr - c->x; + if (x < 0) + x = 0; + return c->ENFN->font_last_up_to_pos(c->ENDT, fmt->font.font, ti->text, + &ti->text_props, x, 0); + } return -1; } /** * @internal - * Cut the text in the item up until cut. + * Cut the text up until cut and split * * @param c the context to work on - Not NULL. - * @param it the item to cut - not null. + * @param ti the item to cut - not null. + * @param lti the logical list item of the item. * @param cut the cut index. + * @return the second (newly created) item. */ -static void -_layout_item_text_cutoff(Ctxt *c __UNUSED__, Evas_Object_Textblock_Item *it, int cut) +static Evas_Object_Textblock_Text_Item * +_layout_item_text_split_strip_white(Ctxt *c, + Evas_Object_Textblock_Text_Item *ti, Eina_List *lti, int cut) { Eina_Unicode *ts; + Evas_Object_Textblock_Text_Item *new_ti = NULL, *white_ti = NULL; + int cut2; - ts = it->text; - ts[cut] = 0; - it->text = eina_unicode_strdup(ts); - free(ts); + ts = ti->text; + if (_is_white(ts[cut])) + cut2 = cut + 1; + else + cut2 = cut; + + if (ts[cut2] && (ti->text_props.text_len > 0)) + { + new_ti = _layout_text_item_new(c, ti->parent.format, &ts[cut2], + ti->text_props.text_len - cut2); + new_ti->parent.text_node = ti->parent.text_node; + new_ti->parent.text_pos = ti->parent.text_pos + cut2; + new_ti->parent.merge = EINA_TRUE; + ts[cut2] = 0; + + evas_common_text_props_split(&ti->text_props, + &new_ti->text_props, cut2); + _layout_text_add_logical_item(c, new_ti, lti); + } + + if ((cut2 > cut) && (ti->text_props.text_len > 0)) + { + white_ti = _layout_text_item_new(c, ti->parent.format, &ts[cut], + ti->text_props.text_len - cut); + white_ti->parent.text_node = ti->parent.text_node; + white_ti->parent.text_pos = ti->parent.text_pos + cut; + white_ti->parent.merge = EINA_TRUE; + white_ti->parent.visually_deleted = EINA_TRUE; + ts[cut] = 0; + + evas_common_text_props_split(&ti->text_props, + &white_ti->text_props, cut); + _layout_text_add_logical_item(c, white_ti, lti); + } + + if (new_ti || white_ti) + { +#if 0 + /* FIXME: This is more correct, but wayy slower, so until I make this + * fast I'll just take the less correct approach. At least until + * someone notices a glitch */ + _text_item_update_sizes(c, ti); +#else + if (new_ti) + { + ti->parent.w -= new_ti->parent.w; + ti->parent.adv -= new_ti->parent.adv; + } + if (white_ti) + { + ti->parent.w -= white_ti->parent.w; + ti->parent.adv -= white_ti->parent.adv; + } +#endif + + ti->text = eina_unicode_strndup(ts, cut); + free(ts); + } + return new_ti; +} + +/** + * @internal + * Merge item2 into item1 and free item2. + * + * @param c the context to work on - Not NULL. + * @param item1 the item to copy to + * @param item2 the item to copy from + */ +static void +_layout_item_merge_and_free(Ctxt *c, + Evas_Object_Textblock_Text_Item *item1, + Evas_Object_Textblock_Text_Item *item2) +{ + Eina_Unicode *tmp; + size_t len1, len2; + len1 = item1->text_props.text_len; + len2 = item2->text_props.text_len; + evas_common_text_props_merge(&item1->text_props, + &item2->text_props); + +#if 0 + /* FIXME: This is more correct, but wayy slower, so until I make this fast + * I'll just take the less correct approach. At least until someone + * notices a glitch */ + _text_item_update_sizes(c, item1); +#else + item1->parent.w += item2->parent.w; + item1->parent.adv += item2->parent.adv; +#endif + + tmp = realloc(item1->text, (len1 + len2 + 1) * sizeof(Eina_Unicode)); + eina_unicode_strncpy(tmp + len1, item2->text, len2); + item1->text = tmp; + item1->text[len1 + len2] = 0; + + item1->parent.merge = EINA_FALSE; + item1->parent.visually_deleted = EINA_FALSE; + + _item_free(c->obj, NULL, _ITEM(item2)); } /** @@ -2169,68 +2601,6 @@ _layout_word_start(const Eina_Unicode *str, int start) /** * @internal - * Strips trailing whitespace from the item's text. - * - * @param c the context to work with - NOT NULL. - * @param fmt does nothing. - * @param it the item to strip. - * - * @return #EINA_TRUE if it stripped, #EINA_FALSE otherwise. - */ -static Eina_Bool -_layout_strip_trailing_whitespace(Ctxt *c, Evas_Object_Textblock_Format *fmt __UNUSED__, Evas_Object_Textblock_Item *it) -{ - int p, tp, chr, adv, tw, th; - - p = eina_unicode_strlen(it->text) - 1; - tp = p; - if (p >= 0) - { - chr = GET_PREV(it->text, p); - if (_is_white(chr)) - { - _layout_item_text_cutoff(c, it, tp); - adv = 0; - if (it->format->font.font) - adv = c->ENFN->font_h_advance_get(c->ENDT, it->format->font.font, it->text, &it->bidi_props); - tw = th = 0; - if (it->format->font.font) - c->ENFN->font_string_size_get(c->ENDT, it->format->font.font, it->text, &it->bidi_props, &tw, &th); - it->w = tw; - it->h = th; - c->x = it->x + adv; - return EINA_TRUE; - } - } - return EINA_FALSE; -} - -/** - * FIXME: document - */ -static int -_layout_item_abort(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textblock_Item *it) -{ - if (it->text) free(it->text); - _format_unref_free(c->obj, it->format); -#ifdef BIDI_SUPPORT - /* FIXME: this also unrefs the paragraph props, we should either - * really count the usage of the paragraph props in the items, or just - * not use clean here. I prefer the latter but that might break if we'll - * start doing fancy stuff in clean in the future. */ - /* evas_bidi_props_clean(&it->bidi_props); */ -#endif - free(it); - if (c->ln->items) - { - it = (Evas_Object_Textblock_Item *)(EINA_INLIST_GET(c->ln->items))->last; - return _layout_strip_trailing_whitespace(c, fmt, it); - } - return 0; -} - -/** - * @internal * returns the index of the words end starting from p * * @param str the str to work on - NOT NULL. @@ -2287,8 +2657,58 @@ _layout_word_next(Eina_Unicode *str, int p) /** * @internal - * Appends the text from node n starting at start ending at off to the layout. - * It uses the fmt for the formatting. + * Calculates an item's size. + * + * @param c the context + * @param it the item itself. + */ +static void +_text_item_update_sizes(Ctxt *c, Evas_Object_Textblock_Text_Item *ti) +{ + int tw, th, adv, inset; + const Evas_Object_Textblock_Format *fmt = ti->parent.format; + + tw = th = 0; + if (fmt->font.font) + c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, ti->text, + &ti->text_props, &tw, &th); + ti->parent.w = tw; + ti->parent.h = th; + inset = 0; + if (fmt->font.font) + inset = c->ENFN->font_inset_get(c->ENDT, fmt->font.font, + &ti->text_props); + ti->inset = inset; + adv = 0; + if (fmt->font.font) + adv = c->ENFN->font_h_advance_get(c->ENDT, fmt->font.font, + ti->text, &ti->text_props); + ti->parent.adv = adv; + ti->parent.x = 0; +} + +/** + * @internal + * Adds the item to the list, updates the item's properties (e.g, x,w,h) + * + * @param c the context + * @param it the item itself. + * @param rel item ti will be appened after, NULL = last. + */ +static void +_layout_text_add_logical_item(Ctxt *c, Evas_Object_Textblock_Text_Item *ti, + Eina_List *rel) +{ + _text_item_update_sizes(c, ti); + + c->par->logical_items = eina_list_append_relative_list( + c->par->logical_items, ti, rel); +} + +/** + * @internal + * Appends the text from node n starting at start ending at off to the layout. + * It uses the fmt for the formatting. * * @param c the current context- NOT NULL. * @param fmt the format to use. @@ -2300,12 +2720,12 @@ _layout_word_next(Eina_Unicode *str, int p) static void _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textblock_Node_Text *n, int start, int off, const char *repch) { - int adv, inset, tw, th, new_line, empty_item; - int wrap, twrap, ch, index, white_stripped; + int new_line, empty_item; Eina_Unicode *alloc_str = NULL; const Eina_Unicode *str = EINA_UNICODE_EMPTY_STRING; const Eina_Unicode *tbase; - Evas_Object_Textblock_Item *it; + Evas_Object_Textblock_Text_Item *ti; + size_t cur_len = 0; /* prepare a working copy of the string, either filled by the repch or * filled with the true values */ @@ -2347,7 +2767,7 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text str = alloca((off + 1) * sizeof(Eina_Unicode)); tbase = str; ind = 0; - urepch = evas_common_encoding_utf8_get_next(repch, &ind); + urepch = eina_unicode_utf8_get_next(repch, &ind); for (i = 0, ptr = (Eina_Unicode *)tbase; i < off; ptr++, i++) *ptr = urepch; *ptr = 0; @@ -2359,214 +2779,61 @@ _layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Text alloc_str = eina_unicode_strndup(str + start, off); str = alloc_str; } + + cur_len = off; } + skip: tbase = str; - // printf("add: wrap: %i|%i, width: %i '%s'\n", fmt->wrap_word, fmt->wrap_char, c->w, str); new_line = 0; empty_item = 0; + while (str) { - /* if this is the first line item and it starts with spaces - remove them */ - wrap = 0; - white_stripped = 0; - - it = _layout_item_new(c, fmt, str); - it->source_node = n; - it->source_pos = start + str - tbase; - if (it->source_node) - { - it->bidi_props.start = it->source_pos; - it->bidi_props.props = it->source_node->bidi_props; -# ifdef BIDI_SUPPORT - evas_bidi_shape_string(it->text, &it->bidi_props, - eina_unicode_strlen(it->text)); -# endif - } - tw = th = 0; - if (fmt->font.font) - c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, it->text, &it->bidi_props, &tw, &th); - if ((c->w >= 0) && - ((fmt->wrap_word) || (fmt->wrap_char)) && - ((c->x + tw) > - (c->w - c->o->style_pad.l - c->o->style_pad.r - - c->marginl - c->marginr))) - { - int orig_wrap; - wrap = _layout_text_cutoff_get(c, fmt, it); - if (wrap == 0) - GET_NEXT(str, wrap); - orig_wrap = wrap; - if (wrap > 0) - { - if (fmt->wrap_word) - { - index = wrap; - ch = GET_NEXT(str, index); - if (!_is_white(ch)) - wrap = _layout_word_start(str, wrap); - if (wrap > 0) - { - twrap = wrap; - ch = GET_PREV(str, twrap); - /* the text intersects the wrap point on a whitespace char */ - if (_is_white(ch)) - { - _layout_item_text_cutoff(c, it, wrap); - twrap = wrap; - /*we don't want to move next, that's why it's - * commented out. - * ch = evas_common_font_utf8_get_next((unsigned char *)str, &twrap); - */ - str += twrap; - } - /* intersects a word */ - else - { - /* walk back to start of word */ - twrap = _layout_word_start(str, wrap); - if (twrap != 0) - { - wrap = twrap; - ch = GET_PREV(str, twrap); - _layout_item_text_cutoff(c, it, twrap); - str += wrap; - } - else - { - empty_item = 1; - if (it->text) free(it->text); - _format_unref_free(c->obj, it->format); - free(it); - if (c->ln->items) - { - it = (Evas_Object_Textblock_Item *)(EINA_INLIST_GET(c->ln->items))->last; - _layout_strip_trailing_whitespace(c, fmt, it); - twrap = _layout_word_end(str, wrap); - if (twrap >= 0) - { - ch = GET_NEXT(str, twrap); - str += twrap; - } - else - str = NULL; - } - } - } - } - else - { - /* wrap now is the index of the word START */ - index = wrap; - ch = GET_NEXT(str, index); - - if (c->ln->items) - { - white_stripped = _layout_item_abort(c, fmt, it); - empty_item = 1; - } - else - { -/* - wrap = 0; - twrap = _layout_word_end(it->text, wrap); - wrap = twrap; - if (twrap >= 0) - { - ch = GET_NEXT(str, wrap); - _layout_item_text_cutoff(c, it, twrap); - } - if (wrap > 0) - str += wrap; - else - str = NULL; -*/ - wrap = twrap = orig_wrap; - _layout_item_text_cutoff(c, it, wrap); - str += wrap; - } - } - } - else if (fmt->wrap_char) - { - _layout_item_text_cutoff(c, it, wrap); - str += wrap; - } - new_line = 1; - } - else - { - /* wrap now is the index of the word START */ - if (wrap < 0) wrap = 0; - index = wrap; - ch = GET_NEXT(str, index); + int tmp_len; - if (c->ln->items) - { - white_stripped = _layout_item_abort(c, fmt, it); - empty_item = 1; - new_line = 1; - } - else - { - if (wrap <= 0) - { - wrap = 0; - twrap = _layout_word_end(it->text, wrap); - wrap = _layout_word_next(it->text, wrap); - if (twrap >= 0) - _layout_item_text_cutoff(c, it, twrap); - if (wrap >= 0) - str += wrap; - else - str = NULL; - } - else - str = NULL; - new_line = 1; - } - } - if (!empty_item) - { - tw = th = 0; - if (fmt->font.font) - c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, it->text, &it->bidi_props, &tw, &th); - } - } - else - str = NULL; - if (empty_item) empty_item = 0; - else + ti = _layout_text_item_new(c, fmt, str, cur_len); + ti->parent.text_node = n; + ti->parent.text_pos = start + str - tbase; + tmp_len = off - (str - tbase); + if (ti->parent.text_node) { - it->w = tw; - it->h = th; - inset = 0; - if (fmt->font.font) - inset = c->ENFN->font_inset_get(c->ENDT, fmt->font.font, it->text); - it->inset = inset; - it->x = c->x; - adv = 0; - if (fmt->font.font) - adv = c->ENFN->font_h_advance_get(c->ENDT, fmt->font.font, it->text, &it->bidi_props); - c->x += adv; - c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(it)); - } - if (new_line) - { - if (str) + int tmp_cut; + tmp_cut = evas_common_language_script_end_of_run_get( + ti->text, + ti->parent.text_node->bidi_props, + ti->parent.text_pos, tmp_len); + if (tmp_cut > 0) { - if (!white_stripped) - { - index = 0; - ch = GET_NEXT(str, index); - if (_is_white(ch)) str += index; - } + Eina_Unicode *ts; + + ts = ti->text; + ts[tmp_cut] = 0; + ti->text = eina_unicode_strndup(ts, tmp_cut); + free(ts); + tmp_len = tmp_cut; } - new_line = 0; - _layout_line_advance(c, fmt); + evas_common_text_props_bidi_set(&ti->text_props, + ti->parent.text_node->bidi_props, ti->parent.text_pos); + evas_common_text_props_script_set (&ti->text_props, + ti->text); + c->ENFN->font_text_props_info_create(c->ENDT, + ti->parent.format->font.font, + ti->text, &ti->text_props, + ti->parent.text_node->bidi_props, + ti->parent.text_pos, tmp_len); } + str += tmp_len; + cur_len -= tmp_len; + + _layout_text_add_logical_item(c, ti, NULL); + + /* Break if we reached the end. */ + if (!*str) + break; } + if (alloc_str) free(alloc_str); } @@ -2576,20 +2843,37 @@ skip: * * @param c the current context- NOT NULL. * @param n the source format node - not null. - * @param item the format text - not null. + * @param item the format text. * * @return the new format item. */ static Evas_Object_Textblock_Format_Item * -_layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node_Format *n, const char *item) +_layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node_Format *n, const char *item, Evas_Object_Textblock_Format *fmt) { Evas_Object_Textblock_Format_Item *fi; fi = calloc(1, sizeof(Evas_Object_Textblock_Format_Item)); fi->item = eina_stringshare_add(item); fi->source_node = n; - c->ln->format_items = (Evas_Object_Textblock_Format_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->format_items), - EINA_INLIST_GET(fi)); + fi->parent.type = EVAS_TEXTBLOCK_ITEM_FORMAT; + fi->parent.format = fmt; + fi->parent.format->ref++; + c->par->logical_items = eina_list_append(c->par->logical_items, fi); + if (n) + { + fi->parent.text_node = n->text_node; + /* FIXME: make it more efficient */ + fi->parent.text_pos = _evas_textblock_node_format_pos_get(n); +#ifdef BIDI_SUPPORT + fi->bidi_dir = (evas_bidi_is_rtl_char( + fi->parent.text_node->bidi_props, + 0, + fi->parent.text_pos)) ? + EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR; +#else + fi->bidi_dir = EVAS_BIDI_DIRECTION_LTR; +#endif + } return fi; } @@ -2605,8 +2889,9 @@ _layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node_Format *n, const cha * Returns true if the item is a paragraph separator, false otherwise * @def _IS_PARAGRAPH_SEPARATOR(item) */ -#define _IS_PARAGRAPH_SEPARATOR(item) \ - (!strcmp(item, "ps")) /* Paragraph separator */ +#define _IS_PARAGRAPH_SEPARATOR(o, item) \ + (!strcmp(item, "ps") || \ + (o->newline_is_ps && _IS_LINE_SEPARATOR(item))) /* Paragraph separator */ /** * @internal @@ -2624,7 +2909,7 @@ _layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node_Format *n, const cha * @param style_pad_b the pad to update. */ static void -_layout_do_format(const Evas_Object *obj, Ctxt *c, +_layout_do_format(const Evas_Object *obj __UNUSED__, 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) { @@ -2656,7 +2941,7 @@ _layout_do_format(const Evas_Object *obj, Ctxt *c, // href == name of item - to be found and matched later and used for // positioning Evas_Object_Textblock_Format_Item *fi; - int x2, w = 1, h = 1; + int w = 1, h = 1; int vsize = 0, size = 0; char *p; @@ -2675,8 +2960,10 @@ _layout_do_format(const Evas_Object *obj, Ctxt *c, p += 6; if (sscanf(p, "%ix%i", &w, &h) == 2) { - w = w * obj->cur.scale; - h = h * obj->cur.scale; + /* this is handled somewhere else because it depends + * on the current scaling factor of the object which + * may change and break because the results of this + * function are cached */ size = SIZE; } } @@ -2696,46 +2983,24 @@ _layout_do_format(const Evas_Object *obj, Ctxt *c, p = strstr(s, " relsize="); if (p) { - p += 9; - if (sscanf(p, "%ix%i", &w, &h) == 2) - { - int sz = 1; - size = SIZE_REL; - if (vsize == VSIZE_FULL) - { - sz = c->maxdescent + c->maxascent; - } - else if (vsize == VSIZE_ASCENT) - { - sz = c->maxascent; - } - w = (w * sz) / h; - h = sz; - } + /* this is handled somewhere else because it depends + * on the line it resides in, which is not defined + * at this point and will change anyway, which will + * break because the results of this function are + * cached */ + size = SIZE_REL; } } } - x2 = c->x + w; - - if (x2 > - (c->w - c->o->style_pad.l - - c->o->style_pad.r - - c->marginl - c->marginr)) - { - _layout_line_advance(c, fmt); - x2 = w; - } - fi = _layout_format_item_add(c, n, NULL); - fi->x = c->x; + fi = _layout_format_item_add(c, n, NULL, fmt); fi->vsize = vsize; fi->size = size; fi->formatme = 1; - fi->w = w; - fi->h = h; - fi->ascent = c->maxascent; - fi->descent = c->maxdescent; - c->x = x2; + fi->parent.w = fi->parent.adv = w; /* For formats items it's usually + the same, we don't handle the + special cases yet. */ + fi->parent.h = h; handled = 1; } if (!handled) @@ -2761,52 +3026,21 @@ _layout_do_format(const Evas_Object *obj, Ctxt *c, } else { - if (_IS_PARAGRAPH_SEPARATOR(item)) + if ((_IS_PARAGRAPH_SEPARATOR(c->o, item)) || + (_IS_LINE_SEPARATOR(item))) { Evas_Object_Textblock_Format_Item *fi; - fi = _layout_format_item_add(c, n, item); - fi->x = c->x; - fi->w = 0; - _layout_line_advance(c, fmt); - - } - else if (_IS_LINE_SEPARATOR(item)) - { - Evas_Object_Textblock_Format_Item *fi; - - fi = _layout_format_item_add(c, n, item); - fi->x = c->x; - fi->w = 0; - _layout_line_advance(c, fmt); + fi = _layout_format_item_add(c, n, item, fmt); + fi->parent.w = fi->parent.adv = 0; } else if ((!strcmp(item, "\t")) || (!strcmp(item, "\\t"))) { Evas_Object_Textblock_Format_Item *fi; - int x2; - - x2 = c->x + fmt->tabstops; - /* Wrap lines if there's a size */ - if ((c->w > 0) && (x2 > - (c->w - c->o->style_pad.l - - c->o->style_pad.r - - c->marginl - c->marginr))) - { - _layout_line_advance(c, fmt); - x2 = c->x + fmt->tabstops; - } - if (c->ln->items) - { - Evas_Object_Textblock_Item *it; - it = (Evas_Object_Textblock_Item *)(EINA_INLIST_GET(c->ln->items))->last; - _layout_strip_trailing_whitespace(c, fmt, it); - } - fi = _layout_format_item_add(c, n, item); - fi->x = c->x; - fi->w = x2 - c->x; + fi = _layout_format_item_add(c, n, item, fmt); + fi->parent.w = fi->parent.adv = fmt->tabstops; fi->formatme = 1; - c->x = x2; } } } @@ -2821,6 +3055,395 @@ _layout_do_format(const Evas_Object *obj, Ctxt *c, *_fmt = fmt; } +static void +_layout_update_par(Ctxt *c) +{ + Evas_Object_Textblock_Paragraph *last_par; + last_par = (Evas_Object_Textblock_Paragraph *) + EINA_INLIST_GET(c->par)->prev; + if (last_par) + { + c->par->y = last_par->y + last_par->h; + } +} + +/* -1 means no wrap */ +static int +_layout_get_charwrap(Ctxt *c, Evas_Object_Textblock_Format *fmt, + const Evas_Object_Textblock_Text_Item *ti) +{ + int wrap; + + wrap = _layout_text_cutoff_get(c, fmt, ti); + if (wrap == 0) + GET_NEXT(ti->text, wrap); + if (!ti->text[wrap]) + wrap = -1; + + return wrap; +} + +/* -1 means no wrap */ +static int +_layout_get_word_mixwrap_common(Ctxt *c, Evas_Object_Textblock_Format *fmt, + const Evas_Object_Textblock_Text_Item *ti, Eina_Bool mixed_wrap) +{ + int wrap = -1, twrap; + int orig_wrap; + Eina_Unicode ch; + const Eina_Unicode *str = ti->text; + + wrap = _layout_text_cutoff_get(c, fmt, ti); + /* Avoiding too small textblocks to even contain one char */ + if (wrap == 0) + GET_NEXT(str, wrap); + orig_wrap = wrap; + /* We need to wrap and found the position that overflows */ + if (wrap > 0) + { + int index = wrap; + ch = GET_NEXT(str, index); + if (!_is_white(ch)) + wrap = _layout_word_start(str, wrap); + /* If we found where to cut the text at, i.e the start + * of the word we were pointing at */ + if (wrap > 0) + { + twrap = wrap; + ch = GET_PREV(str, twrap); + /* the text intersects the wrap point on a whitespace char */ + if (_is_white(ch)) + { + return wrap; + } + /* intersects a word */ + else + { + /* walk back to start of word */ + twrap = _layout_word_start(str, wrap); + if (twrap != 0) + { + wrap = twrap; + ch = GET_PREV(str, wrap); + return (str[wrap]) ? wrap : -1; + } + } + } + /* If we weren't able to find the start of the word we + * are currently pointing at, or we were able but it's + * the first word - the end of this word is the wrap point, o */ + else + { + /* wrap now is the index of the word START */ + index = wrap; + ch = GET_NEXT(str, index); + + /* If there are already items in this line, we + * should just try creating a new line for it */ + if (c->ln->items) + { + return 0; + } + /* If there were no items in this line, try to do + * our best wrapping possible since it's the middle + * of the word */ + else + { + if (mixed_wrap) + { + return (str[orig_wrap]) ? orig_wrap : -1; + } + else + { + wrap = 0; + twrap = _layout_word_end(ti->text, wrap); + wrap = twrap; + if (twrap >= 0) + { + ch = GET_NEXT(str, wrap); + return (str[wrap]) ? wrap : -1; + } + else + { + return -1; + } + } + } + } + } + /* We need to wrap, but for some reason we failed obatining the + * overflow position. */ + else + { + /*FIXME: sanitize this error handling - should probably + * never get here anyway unless something really bad + * has happend */ + /* wrap now is the index of the word START */ + if (wrap < 0) wrap = 0; + + /* If there are already items in the line, break before. */ + if (c->ln->items) + { + return 0; + } + else + { + twrap = _layout_word_end(ti->text, wrap); + wrap = _layout_word_next(ti->text, wrap); + if (wrap >= 0) + { + ch = GET_NEXT(str, wrap); + return (str[wrap]) ? wrap : -1; + } + else if (twrap >= 0) + { + ch = GET_NEXT(str, twrap); + return (str[twrap]) ? twrap : -1; + } + } + } + return -1; +} + +/* -1 means no wrap */ +static int +_layout_get_wordwrap(Ctxt *c, Evas_Object_Textblock_Format *fmt, + const Evas_Object_Textblock_Text_Item *ti) +{ + return _layout_get_word_mixwrap_common(c, fmt, ti, EINA_FALSE); +} + +/* -1 means no wrap */ +static int +_layout_get_mixedwrap(Ctxt *c, Evas_Object_Textblock_Format *fmt, + const Evas_Object_Textblock_Text_Item *ti) +{ + return _layout_get_word_mixwrap_common(c, fmt, ti, EINA_TRUE); +} + +static Evas_Object_Textblock_Text_Item * +_layout_ellipsis_item_new(Ctxt *c, const Evas_Object_Textblock_Item *cur_it) +{ + Evas_Object_Textblock_Text_Item *ellip_ti; + const Eina_Unicode _ellip_str[2] = { 0x2026, '\0' }; /* Ellipsis char */ + size_t len = 1; /* The length of _ellip_str */ + /* We assume that the format stack has at least one time, + * the only reason it may not have, is more than <>, other + * than that, we're safe. The last item is the base format. */ + ellip_ti = _layout_text_item_new(c, + eina_list_data_get(eina_list_last(c->format_stack)), + _ellip_str, len); + ellip_ti->parent.text_node = cur_it->text_node; + ellip_ti->parent.text_pos = cur_it->text_pos; + if (cur_it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + ellip_ti->parent.text_pos += _ITEM_TEXT(cur_it)->text_props.text_len; + } + else + { + ellip_ti->parent.text_pos++; + } + + evas_common_text_props_bidi_set(&ellip_ti->text_props, + ellip_ti->parent.text_node->bidi_props, ellip_ti->parent.text_pos); + evas_common_text_props_script_set (&ellip_ti->text_props, + ellip_ti->text); + c->ENFN->font_text_props_info_create(c->ENDT, + ellip_ti->parent.format->font.font, + ellip_ti->text, &ellip_ti->text_props, + ellip_ti->parent.text_node->bidi_props, + ellip_ti->parent.text_pos, len); + _text_item_update_sizes(c, ellip_ti); + + return ellip_ti; +} + +/* 0 means go ahead, 1 means break without an error, 2 means + * break with an error, should probably clean this a bit (enum/macro) + * FIXME ^ */ +static int +_layout_visualize_par(Ctxt *c) +{ + Evas_Object_Textblock_Item *it; + Eina_List *i; + if (!c->par->logical_items) + return 2; + + it = _ITEM(eina_list_data_get(c->par->logical_items)); + _layout_line_new(c, it->format); + /* We walk on our own because we want to be able to add items from + * inside the list and then walk them on the next iteration. */ + for (i = c->par->logical_items ; i ; ) + { + int adv_line = 0; + int redo_item = 0; + it = _ITEM(eina_list_data_get(i)); + /* Skip visually deleted items */ + if (it->visually_deleted) + { + i = eina_list_next(i); + continue; + } + + /* Check if we need to wrap, i.e the text is bigger than the width */ + if ((c->w >= 0) && + ((c->x + it->adv) > + (c->w - c->o->style_pad.l - c->o->style_pad.r - + c->marginl - c->marginr))) + { + /* Handle ellipsis here */ + if ((it->format->ellipsis == 1.0) && (c->h >= 0) && + (2 * it->h + c->y > + c->h - c->o->style_pad.t - c->o->style_pad.b)) + { + Evas_Object_Textblock_Text_Item *ellip_ti, *last_ti; + Evas_Object_Textblock_Item *last_it; + Evas_Coord save_cx; + int wrap; + ellip_ti = _layout_ellipsis_item_new(c, it); + last_it = it; + last_ti = _ITEM_TEXT(it); + + save_cx = c->x; + c->w -= ellip_ti->parent.w; + do + { + wrap = _layout_text_cutoff_get(c, last_it->format, + last_ti); + if ((wrap > 0) && last_ti->text[wrap]) + { + _layout_item_text_split_strip_white(c, last_ti, i, + wrap); + } + else if (wrap == 0) + { + if (!c->ln->items) + break; + /* We haven't added it yet at this point */ + if (_ITEM(last_ti) != it) + { + last_it = + _ITEM(EINA_INLIST_GET(last_it)->prev); + c->ln->items = _ITEM(eina_inlist_remove( + EINA_INLIST_GET(c->ln->items), + EINA_INLIST_GET(_ITEM(last_ti)))); + } + else + { + last_it = + _ITEM(EINA_INLIST_GET(c->ln->items)->last); + } + last_ti = _ITEM_TEXT(last_it); + if (last_it) + { + c->x -= last_it->adv; + } + } + } + while (last_it && (wrap == 0)); + c->x = save_cx; + c->w += ellip_ti->parent.w; + /* If we should add this item, do it */ + if (last_it == it) + { + c->ln->items = (Evas_Object_Textblock_Item *) + eina_inlist_append(EINA_INLIST_GET(c->ln->items), + EINA_INLIST_GET(it)); + if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) + { + Evas_Object_Textblock_Format_Item *fi; + fi = _ITEM_FORMAT(it); + fi->y = c->y; + } + } + c->ln->items = (Evas_Object_Textblock_Item *) + eina_inlist_append(EINA_INLIST_GET(c->ln->items), + EINA_INLIST_GET(_ITEM(ellip_ti))); + c->ln->ellip_ti = ellip_ti; + _layout_line_finalize(c, ellip_ti->parent.format); + + return 1; + } + else if (it->format->wrap_word || it->format->wrap_char || + it->format->wrap_mixed) + { + if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) + { + /* Don't wrap if it's the only item */ + if (c->ln->items) + { + /*FIXME: I should handle tabs correctly, i.e like + * spaces */ + _layout_line_advance(c, it->format); + } + } + else + { + Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it); + int wrap; + + adv_line = 1; + if (it->format->wrap_word) + wrap = _layout_get_wordwrap(c, it->format, ti); + else if (it->format->wrap_char) + wrap = _layout_get_charwrap(c, it->format, ti); + else if (it->format->wrap_mixed) + wrap = _layout_get_mixedwrap(c, it->format, ti); + else + wrap = -1; + + if (wrap > 0) + { + _layout_item_text_split_strip_white(c, ti, i, wrap); + } + else if (wrap == 0) + { + /* Should wrap before the item */ + adv_line = 0; + redo_item = 1; + _layout_line_advance(c, it->format); + } + } + } + } + + if (!redo_item) + { + c->ln->items = (Evas_Object_Textblock_Item *) + eina_inlist_append(EINA_INLIST_GET(c->ln->items), + EINA_INLIST_GET(it)); + if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) + { + Evas_Object_Textblock_Format_Item *fi; + fi = _ITEM_FORMAT(it); + fi->y = c->y; + if (fi->item && _IS_LINE_SEPARATOR(fi->item)) + { + adv_line = 1; + } + } + c->x += it->adv; + i = eina_list_next(i); + } + if (adv_line) + { + /* Each line is according to the first item in it, and here + * i is already the next item (or the current if we redo it) */ + if (i) + { + it = _ITEM(eina_list_data_get(i)); + } + _layout_line_advance(c, it->format); + } + } + if (c->ln->items) + { + /* Here 'it' is the last format used */ + _layout_line_finalize(c, it->format); + } + return 0; +} + /** * @internal * Create the layout from the nodes. @@ -2837,9 +3460,7 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ { Evas_Object_Textblock *o; Ctxt ctxt, *c; - Evas_Object_Textblock_Line *ln; Evas_Object_Textblock_Node_Text *n; - Eina_List *removes = NULL; Evas_Object_Textblock_Format *fmt = NULL; int style_pad_l = 0, style_pad_r = 0, style_pad_t = 0, style_pad_b = 0; @@ -2864,6 +3485,9 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ c->align_auto = EINA_TRUE; c->ln = NULL; + + /* Start of logical layout creation */ + /* setup default base style */ if ((c->o->style) && (c->o->style->default_tag)) { @@ -2876,73 +3500,171 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ if (h_ret) *h_ret = 0; return; } - /* run through all text and format nodes generating lines */ - if (!c->o->text_nodes && !c->o->format_nodes) + + if (o->content_changed) { - /* If there are no nodes and lines, do the initial creation. */ - if (!c->par && !c->ln) + _paragraphs_free(obj, o->paragraphs); + /* Go through all the text nodes to create the logical layout */ + EINA_INLIST_FOREACH(c->o->text_nodes, n) { - _layout_paragraph_new(c); - _layout_line_new(c, fmt); - _layout_text_append(c, fmt, NULL, 0, 0, NULL); - _layout_line_advance(c, fmt); + Evas_Object_Textblock_Node_Format *fnode; + size_t start; + int off; + + n->dirty = 0; /* Mark as if we cleaned the paragraph, although + we should really use it to fine tune the + changes here, and not just blindly mark */ + _layout_paragraph_new(c, n); /* Each node is a paragraph */ + + /* For each text node to thorugh all of it's format nodes + * append text from the start to the offset of the next format + * using the last format got. if needed it also creates format items + * this is the core algorithm of the layout mechanism. + * Skip the unicode replacement chars when there are because + * we don't want to print them. */ + fnode = n->format_node; + start = off = 0; + while (fnode && (fnode->text_node == n)) + { + off += fnode->offset; + /* No need to skip on the first run, or a non-visible one */ + _layout_text_append(c, fmt, n, start, off, o->repch); + _layout_do_format(obj, c, &fmt, fnode, &style_pad_l, + &style_pad_r, &style_pad_t, &style_pad_b); + if ((c->have_underline2) || (c->have_underline)) + { + if (style_pad_b < c->underline_extend) + style_pad_b = c->underline_extend; + c->have_underline = 0; + c->have_underline2 = 0; + c->underline_extend = 0; + } + start += off; + if (fnode->visible) + { + off = -1; + start++; + } + else + { + off = 0; + } + fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next); + } + _layout_text_append(c, fmt, n, start, -1, o->repch); } + o->paragraphs = c->paragraphs; } - - /* Go through all the text nodes to create the layout from */ - EINA_INLIST_FOREACH(c->o->text_nodes, n) + else if (!calc_only) { - Evas_Object_Textblock_Node_Format *fnode; - size_t start; - int off; - - /*FIXME-tom: A hack, so we'll only have one paragraph - * until full support is implemented */ - if (!c->par) - { - _layout_paragraph_new(c); /* Each node is a paragraph */ - } - if (!c->ln) _layout_line_new(c, fmt); - - /* For each text node to thorugh all of it's format nodes - * append text from the start to the offset of the next format - * using the last format got. if needed it also creates format items - * this is the core algorithm of the layout mechanism. - * Skip the unicode replacement chars when there are because - * we don't want to print them. */ - fnode = n->format_node; - start = off = 0; - while (fnode && (fnode->text_node == n)) + _paragraphs_clear(obj, o->paragraphs); + c->paragraphs = o->paragraphs; + /* Merge the ones that need merging. */ + /* Go through all the paragraphs, lines, items and merge if should be + * merged we merge backwards!!! */ + Evas_Object_Textblock_Paragraph *par; + EINA_INLIST_FOREACH(EINA_INLIST_GET(c->paragraphs), par) { - off += fnode->offset; - /* No need to skip on the first run, or a non-visible one */ - _layout_text_append(c, fmt, n, start, off, o->repch); - _layout_do_format(obj, c, &fmt, fnode, &style_pad_l, &style_pad_r, &style_pad_t, &style_pad_b); - if ((c->have_underline2) || (c->have_underline)) - { - if (style_pad_b < c->underline_extend) - style_pad_b = c->underline_extend; - c->have_underline = 0; - c->have_underline2 = 0; - c->underline_extend = 0; - } - start += off; - if (fnode->visible) + Eina_List *itr, *itr_next; + Evas_Object_Textblock_Item *it, *prev_it = NULL; + EINA_LIST_FOREACH_SAFE(par->logical_items, itr, itr_next, it) { - off = -1; - start++; + if (it->merge && prev_it && + (prev_it->type == EVAS_TEXTBLOCK_ITEM_TEXT) && + (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)) + { + _layout_item_merge_and_free(c, _ITEM_TEXT(prev_it), + _ITEM_TEXT(it)); + par->logical_items = + eina_list_remove_list(par->logical_items, itr); + } + else + { + prev_it = it; + } } - else + } + } + else /* Calc only and content hasn't changed */ + { + c->paragraphs = o->paragraphs; + } + + /* If there are no paragraphs, create the minimum needed, + * if the last paragraph has no lines/text, create that as well */ + if (!c->paragraphs) + { + _layout_paragraph_new(c, NULL); + o->paragraphs = c->paragraphs; + } + c->par = (Evas_Object_Textblock_Paragraph *) + EINA_INLIST_GET(c->paragraphs)->last; + if (!c->par->logical_items) + { + _layout_text_append(c, fmt, NULL, 0, 0, NULL); + } + + /* In the case of calc only, we copy the items and the paragraphs, + * but because we don't change OT_DATA we can use it, just copy the item + * and ref */ + if (calc_only) + { + Evas_Object_Textblock_Paragraph *orig_pars, *par; + Eina_List *itr; + orig_pars = c->paragraphs; + c->paragraphs = NULL; + EINA_INLIST_FOREACH(EINA_INLIST_GET(orig_pars), par) + { + Evas_Object_Textblock_Item *it; + c->par = malloc(sizeof(Evas_Object_Textblock_Paragraph)); + memcpy(c->par, par, sizeof(Evas_Object_Textblock_Paragraph)); + /* Both of these should not be copied */ + c->par->lines = NULL; + c->par->logical_items = NULL; + c->paragraphs = (Evas_Object_Textblock_Paragraph *) + eina_inlist_append(EINA_INLIST_GET(c->paragraphs), + EINA_INLIST_GET(c->par)); + + /* Copy all the items */ + EINA_LIST_FOREACH(par->logical_items, itr, it) { - off = 0; + Evas_Object_Textblock_Item *new_it; + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + new_it = malloc(sizeof(Evas_Object_Textblock_Text_Item)); + memcpy(new_it, it, + sizeof(Evas_Object_Textblock_Text_Item)); + } + else + { + new_it = malloc( + sizeof(Evas_Object_Textblock_Format_Item)); + memcpy(new_it, it, + sizeof(Evas_Object_Textblock_Format_Item)); + } + c->par->logical_items = + eina_list_append(c->par->logical_items, new_it); } - fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next); } - _layout_text_append(c, fmt, n, start, -1, o->repch); } - /* Advance the line so it'll calculate the size */ - if ((c->ln) && (c->ln->items || c->ln->format_items) && (fmt)) - _layout_line_advance(c, fmt); + + + /* End of logical layout creation */ + + /* Start of visual layout creation */ + /* FIXME: move away? */ + { + Evas_Object_Textblock_Paragraph *par; + EINA_INLIST_FOREACH(c->paragraphs, par) + { + c->par = par; + _layout_update_par(c); + /* Break if we should stop here. */ + if (_layout_visualize_par(c)) + break; + } + } + /* End of visual layout creation */ /* Clean the rest of the format stack */ while (c->format_stack) @@ -2951,47 +3673,55 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ c->format_stack = eina_list_remove_list(c->format_stack, c->format_stack); _format_unref_free(c->obj, fmt); } - EINA_INLIST_FOREACH(c->par->lines, ln) - { - if (ln->line_no == -1) - { - removes = eina_list_append(removes, ln); - } - else - { - if ((ln->y + ln->h) > c->hmax) c->hmax = ln->y + ln->h; - } - } - /* Remove the lines we marked for removal, mostly lines added after - * just to force calculation of line sizes */ - while (removes) + + if (c->paragraphs) { - ln = removes->data; - c->par->lines = (Evas_Object_Textblock_Line *)eina_inlist_remove(EINA_INLIST_GET(c->par->lines), EINA_INLIST_GET(ln)); - removes = eina_list_remove_list(removes, removes); - _line_free(obj, ln); + Evas_Object_Textblock_Paragraph *last_par; + last_par = (Evas_Object_Textblock_Paragraph *) + EINA_INLIST_GET(c->paragraphs)->last; + c->hmax = last_par->y + last_par->h; } if (w_ret) *w_ret = c->wmax; if (h_ret) *h_ret = c->hmax; + if ((o->style_pad.l != style_pad_l) || (o->style_pad.r != style_pad_r) || (o->style_pad.t != style_pad_t) || (o->style_pad.b != style_pad_b)) { - c->par->lines = NULL; o->style_pad.l = style_pad_l; o->style_pad.r = style_pad_r; o->style_pad.t = style_pad_t; o->style_pad.b = style_pad_b; + if (!calc_only) + { + _paragraphs_clear(obj, c->paragraphs); + } _layout(obj, calc_only, w, h, w_ret, h_ret); - _paragraphs_clear(obj, c->paragraphs); return; } - if (!calc_only) + + if (calc_only) { - o->paragraphs = c->paragraphs; - return; + Evas_Object_Textblock_Paragraph *par; + while (c->paragraphs) + { + Eina_List *itr, *itrn; + Evas_Object_Textblock_Item *it; + par = c->paragraphs; + /* free all the items */ + EINA_LIST_FOREACH_SAFE(par->logical_items, itr, itrn, it) + { + par->logical_items = + eina_list_remove_list(par->logical_items, itr); + free(it); + } + c->paragraphs = (Evas_Object_Textblock_Paragraph *) + eina_inlist_remove(EINA_INLIST_GET(c->paragraphs), + EINA_INLIST_GET(c->paragraphs)); + _paragraph_clear(obj, par); + free(par); + } } - if (c->paragraphs) _paragraphs_clear(obj, c->paragraphs); } /* @@ -3004,21 +3734,16 @@ static void _relayout(const Evas_Object *obj) { Evas_Object_Textblock *o; - Evas_Object_Textblock_Paragraph *paragraphs; o = (Evas_Object_Textblock *)(obj->object_data); - paragraphs = o->paragraphs; - o->paragraphs = NULL; - o->formatted.valid = 0; - o->native.valid = 0; _layout(obj, 0, obj->cur.geometry.w, obj->cur.geometry.h, &o->formatted.w, &o->formatted.h); o->formatted.valid = 1; - if (paragraphs) _paragraphs_clear(obj, paragraphs); o->last_w = obj->cur.geometry.w; o->changed = 0; + o->content_changed = 0; o->redraw = 1; } @@ -3030,29 +3755,52 @@ _relayout(const Evas_Object *obj) * @param n the text node - Not null. * @param pos the position to look for - valid. * @param[out] lnr the line found - not null. - * @param[out] itr the item found - not null. + * @param[out] tir the item found - not null. * @see _find_layout_format_item_line_match() */ static void _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) { + Evas_Object_Textblock_Paragraph *par, *found_par = NULL; Evas_Object_Textblock_Line *ln; Evas_Object_Textblock *o; o = (Evas_Object_Textblock *)(obj->object_data); if (!o->formatted.valid) _relayout(obj); - EINA_INLIST_FOREACH(o->paragraphs->lines, ln) + EINA_INLIST_FOREACH(o->paragraphs, par) { - Evas_Object_Textblock_Item *it; - - EINA_INLIST_FOREACH(ln->items, it) + if (par->text_node == n) + { + found_par = par; + break; + } + } + if (found_par) + { + EINA_INLIST_FOREACH(found_par->lines, ln) { - if (it->source_node == n) + Evas_Object_Textblock_Item *it; + Evas_Object_Textblock_Line *lnn; + + lnn = (Evas_Object_Textblock_Line *)(((Eina_Inlist *)ln)->next); + EINA_INLIST_FOREACH(ln->items, it) { - int p; + /* FIXME: p should be size_t, same goes for pos */ + int p = (int) it->text_pos; + + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + Evas_Object_Textblock_Text_Item *ti = + _ITEM_TEXT(it); + + p += (int) ti->text_props.text_len; + } + else + { + p++; + } - p = (int)(it->source_pos + eina_unicode_strlen(it->text)); - if (((pos >= (int) it->source_pos) && (pos < p))) + if (((pos >= (int) it->text_pos) && (pos < p))) { *lnr = ln; *itr = it; @@ -3070,40 +3818,6 @@ _find_layout_item_line_match(Evas_Object *obj, Evas_Object_Textblock_Node_Text * /** * @internal - * Find the layout format item and line that match the format node passed. - * - * @param obj the evas object - NOT NULL. - * @param n the text node - Not null. - * @param[out] lnr the line found - not null. - * @param[out] fir the item found - not null. - * @see _find_layout_item_line_match() - */ -static void -_find_layout_format_item_line_match(Evas_Object *obj, Evas_Object_Textblock_Node_Format *n, Evas_Object_Textblock_Line **lnr, Evas_Object_Textblock_Format_Item **fir) -{ - Evas_Object_Textblock_Line *ln; - Evas_Object_Textblock *o; - - o = (Evas_Object_Textblock *)(obj->object_data); - if (!o->formatted.valid) _relayout(obj); - EINA_INLIST_FOREACH(o->paragraphs->lines, ln) - { - Evas_Object_Textblock_Format_Item *fi; - - EINA_INLIST_FOREACH(ln->format_items, fi) - { - if (fi->source_node == n) - { - *lnr = ln; - *fir = fi; - return; - } - } - } -} - -/** - * @internal * Return the line number 'line'. * * @param obj the evas object - NOT NULL. @@ -3113,13 +3827,25 @@ _find_layout_format_item_line_match(Evas_Object *obj, Evas_Object_Textblock_Node static Evas_Object_Textblock_Line * _find_layout_line_num(const Evas_Object *obj, int line) { + Evas_Object_Textblock_Paragraph *par, *prev_par = NULL; Evas_Object_Textblock_Line *ln; Evas_Object_Textblock *o; o = (Evas_Object_Textblock *)(obj->object_data); - EINA_INLIST_FOREACH(o->paragraphs->lines, ln) + EINA_INLIST_FOREACH(o->paragraphs, par) + { + if (prev_par && (prev_par->line_no <= line) && (line < par->line_no)) + { + break; + } + prev_par = par; + } + if (prev_par) { - if (ln->line_no == line) return ln; + EINA_INLIST_FOREACH(prev_par->lines, ln) + { + if (ln->par->line_no + ln->line_no == line) return ln; + } } return NULL; } @@ -3188,28 +3914,26 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text) Evas_Object *obj; if (!ts) return; + /* If the style wasn't really changed, abort. */ + if ((!ts->style_text && !text) || + (ts->style_text && text && !strcmp(text, ts->style_text))) + return; EINA_LIST_FOREACH(ts->objects, l, obj) { Evas_Object_Textblock *o; o = (Evas_Object_Textblock *)(obj->object_data); - if (o->markup_text) - { - free(o->markup_text); - o->markup_text = NULL; - evas_object_textblock_text_markup_get(obj); - } + _evas_textblock_text_node_changed(o, obj, NULL); } - _style_clear(ts); - if (text) ts->style_text = strdup(text); + _style_replace(ts, text); if (ts->style_text) { // format MUST be KEY='VALUE'[KEY='VALUE']... - char *p; - char *key_start, *key_stop, *val_start, *val_stop; + const char *p; + const char *key_start, *key_stop, *val_start, *val_stop; key_start = key_stop = val_start = val_stop = NULL; p = ts->style_text; @@ -3290,24 +4014,6 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text) p++; } } - - EINA_LIST_FOREACH(ts->objects, l, obj) - { - Evas_Object_Textblock *o; - - o = (Evas_Object_Textblock *)(obj->object_data); - if (o->markup_text) - { - char *m; - - m = strdup(o->markup_text); - if (m) - { - evas_object_textblock_text_markup_set(obj, m); - free(m); - } - } - } } /** @@ -3335,18 +4041,14 @@ evas_object_textblock_style_set(Evas_Object *obj, Evas_Textblock_Style *ts) TB_HEAD(); if (ts == o->style) return; if ((ts) && (ts->delete_me)) return; - if (o->markup_text) + if (o->style) { - if (o->style) + Evas_Textblock_Style *old_ts; + if (o->markup_text) { free(o->markup_text); o->markup_text = NULL; - evas_object_textblock_text_markup_get(obj); } - } - if (o->style) - { - Evas_Textblock_Style *old_ts; old_ts = o->style; old_ts->objects = eina_list_remove(old_ts->objects, obj); @@ -3356,14 +4058,10 @@ evas_object_textblock_style_set(Evas_Object *obj, Evas_Textblock_Style *ts) if (ts) { ts->objects = eina_list_append(ts->objects, obj); - o->style = ts; - } - else - { - o->style = NULL; } + o->style = ts; - _evas_textblock_changed(o, obj); + _evas_textblock_text_node_changed(o, obj, NULL); } /** @@ -3391,7 +4089,41 @@ evas_object_textblock_replace_char_set(Evas_Object *obj, const char *ch) if (o->repch) eina_stringshare_del(o->repch); if (ch) o->repch = eina_stringshare_add(ch); else o->repch = NULL; - _evas_textblock_changed(o, obj); + _evas_textblock_text_node_changed(o, obj, NULL); +} + +/** + * @brief Sets newline mode. When true, newline character will behave + * as a paragraph separator. + * + * @param obj The given textblock object. + * @param mode EINA_TRUE for PS mode, EINA_FALSE otherwise. + * @since 1.1.0 + */ +EAPI void +evas_object_textblock_newline_mode_set(Evas_Object *obj, Eina_Bool mode) +{ + TB_HEAD(); + if (o->newline_is_ps == mode) + return; + + o->newline_is_ps = mode; + _evas_textblock_text_node_changed(o, obj, NULL); +} + +/** + * @brief Gets newline mode. When true, newline character behaves + * as a paragraph separator. + * + * @param obj The given textblock object. + * @return EINA_TRUE if in PS mode, EINA_FALSE otherwise. + * @since 1.1.0 + */ +EAPI Eina_Bool +evas_object_textblock_newline_mode_get(const Evas_Object *obj) +{ + TB_HEAD_RETURN(EINA_FALSE); + return o->newline_is_ps; } /** @@ -3780,7 +4512,7 @@ evas_object_textblock_text_markup_prepend(Evas_Textblock_Cursor *cur, const char p++; } } - _evas_textblock_changed(o, obj); + _evas_textblock_text_node_changed(o, obj, o->cursor->node); } @@ -3835,7 +4567,7 @@ _markup_get_format_append(Evas_Object_Textblock *o, Eina_Strbuf *txt, Evas_Objec static void _markup_get_text_append(Eina_Strbuf *txt, const Eina_Unicode *text) { - char *p = evas_common_encoding_unicode_to_utf8(text, NULL); + char *p = eina_unicode_unicode_to_utf8(text, NULL); char *base = p; while (*p) { @@ -3884,7 +4616,8 @@ evas_object_textblock_text_markup_get(const Evas_Object *obj) * Skip the unicode replacement chars when there are because * we don't want to print them. */ text_base = text = - eina_unicode_strdup(eina_ustrbuf_string_get(n->unicode)); + eina_unicode_strndup(eina_ustrbuf_string_get(n->unicode), + eina_ustrbuf_length_get(n->unicode)); fnode = n->format_node; off = 0; while (fnode && (fnode->text_node == n)) @@ -4149,51 +4882,38 @@ _evas_textblock_cursor_node_format_before_or_at_pos_get(const Evas_Textblock_Cur /** * @internal - * Return the last format that applies to a specific cursor or at the specific - * position the cursor points to. This means the format node before the - * position of the cursor in the text node is returned or the previous's text - * node's format node. + * Find the layout item and line that match the cursor. * - * @param cur the position to look at. - * @return the format node found. + * @param cur the cursor we are currently at. - NOT NULL. + * @param[out] lnr the line found - not null. + * @param[out] itr the item found - not null. + * @return EINA_TRUE if we matched the previous format, EINA_FALSE otherwise. */ -#if 0 // not used anymore? -static Evas_Object_Textblock_Node_Format * -_evas_textblock_cursor_node_format_before_pos_get(const Evas_Textblock_Cursor *cur) +static Eina_Bool +_find_layout_item_match(const Evas_Textblock_Cursor *cur, Evas_Object_Textblock_Line **lnr, Evas_Object_Textblock_Item **itr) { - Evas_Object_Textblock_Node_Format *node, *pitr = NULL; - Evas_Object_Textblock_Node_Format *itr; - size_t position = 0; - - if (!cur->node) return NULL; + Evas_Textblock_Cursor cur2; + Eina_Bool previous_format = EINA_FALSE; - node = cur->node->format_node; - if (!node) return NULL; - /* If there is no exclusive format node to this paragraph return the - * previous's node */ - if (node->text_node != cur->node) + cur2.obj = cur->obj; + evas_textblock_cursor_copy(cur, &cur2); + if (cur2.pos > 0) { - return node; + cur2.pos--; } - else if (node->offset > cur->pos) + + if (_evas_textblock_cursor_is_at_the_end(cur) && + evas_textblock_cursor_format_is_visible_get(&cur2)) { - return _NODE_FORMAT(EINA_INLIST_GET(node)->prev); + _find_layout_item_line_match(cur2.obj, cur2.node, cur2.pos, lnr, itr); + previous_format = EINA_TRUE; } - /* Find the main format node */ - pitr = _NODE_FORMAT(EINA_INLIST_GET(node)->prev); - EINA_INLIST_FOREACH(node, itr) + else { - position += itr->offset; - if ((itr->text_node != cur->node) || - (position >= cur->pos)) - { - return pitr; - } - pitr = itr; + _find_layout_item_line_match(cur->obj, cur->node, cur->pos, lnr, itr); } - return pitr; + return previous_format; } -#endif /** * Return the object's main cursor. @@ -4370,7 +5090,7 @@ evas_textblock_node_format_remove_pair(Evas_Object *obj, cur.obj = obj; eina_ustrbuf_remove(n->text_node->unicode, index, index + 1); - if (format && _IS_PARAGRAPH_SEPARATOR(format)) + if (format && _IS_PARAGRAPH_SEPARATOR(o, format)) { evas_textblock_cursor_set_at_format(&cur, n); _evas_textblock_cursor_nodes_merge(&cur); @@ -4383,7 +5103,7 @@ evas_textblock_node_format_remove_pair(Evas_Object *obj, /* pnode can never be visible! (it's the closing format) */ _evas_textblock_node_format_remove(o, pnode, 0); } - _evas_textblock_changed(o, obj); + _evas_textblock_text_node_changed(o, obj, tnode); } /** @@ -4622,12 +5342,17 @@ evas_textblock_cursor_char_next(Evas_Textblock_Cursor *cur) { if (!evas_textblock_cursor_paragraph_next(cur)) { + /* If we already were at the end, that means we don't have + * where to go next we should return FALSE */ + if (cur->pos == (size_t) index) + return EINA_FALSE; + cur->pos = index; return EINA_TRUE; } else { - return EINA_FALSE; + return EINA_TRUE; } } } @@ -4684,6 +5409,7 @@ evas_textblock_cursor_paragraph_char_last(Evas_Textblock_Cursor *cur) cur->pos = index; else cur->pos = 0; + } /** @@ -4698,60 +5424,31 @@ evas_textblock_cursor_line_char_first(Evas_Textblock_Cursor *cur) Evas_Object_Textblock *o; Evas_Object_Textblock_Line *ln = NULL; Evas_Object_Textblock_Item *it = NULL; - Evas_Object_Textblock_Format_Item *fi = NULL; - Evas_Textblock_Cursor cur2; if (!cur) return; if (!cur->node) return; o = (Evas_Object_Textblock *)(cur->obj->object_data); if (!o->formatted.valid) _relayout(cur->obj); - /* Cur 2 is pointing to the previous char */ - cur2.obj = cur->obj; - evas_textblock_cursor_copy(cur, &cur2); - if (cur2.pos > 0) - { - cur2.pos--; - } - - if (evas_textblock_cursor_format_is_visible_get(cur)) - { - _find_layout_format_item_line_match(cur->obj, - _evas_textblock_node_visible_at_pos_get( - _evas_textblock_cursor_node_format_at_pos_get(cur)), - &ln, &fi); - } - else if (_evas_textblock_cursor_is_at_the_end(cur) && - evas_textblock_cursor_format_is_visible_get(&cur2)) - { - _find_layout_format_item_line_match(cur->obj, - _evas_textblock_node_visible_at_pos_get( - _evas_textblock_cursor_node_format_at_pos_get(&cur2)), - &ln, &fi); - } - else - { - _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it); - } + _find_layout_item_match(cur, &ln, &it); if (!ln) return; - - it = (Evas_Object_Textblock_Item *)ln->items; - fi = (Evas_Object_Textblock_Format_Item *)ln->format_items; - if ((it) && (fi)) + if (ln->items) { - if (it->x < fi->x) fi = NULL; - else it = NULL; + Evas_Object_Textblock_Item *i; + it = ln->items; + EINA_INLIST_FOREACH(ln->items, i) + { + if (it->text_pos > i->text_pos) + { + it = i; + } + } } if (it) { - cur->pos = it->source_pos; - cur->node = it->source_node; - } - else if (fi) - { - cur->node = fi->source_node->text_node; - cur->pos = _evas_textblock_node_format_pos_get(fi->source_node); + cur->pos = it->text_pos; + cur->node = it->text_node; } } @@ -4767,74 +5464,40 @@ evas_textblock_cursor_line_char_last(Evas_Textblock_Cursor *cur) Evas_Object_Textblock *o; Evas_Object_Textblock_Line *ln = NULL; Evas_Object_Textblock_Item *it = NULL; - Evas_Object_Textblock_Format_Item *fi = NULL; - Evas_Textblock_Cursor cur2; if (!cur) return; if (!cur->node) return; o = (Evas_Object_Textblock *)(cur->obj->object_data); if (!o->formatted.valid) _relayout(cur->obj); -// kills "click below text" and up/downm arrow. disable - - /* Cur 2 is pointing to the previous char */ - cur2.obj = cur->obj; - evas_textblock_cursor_copy(cur, &cur2); - if (cur2.pos > 0) - { - cur2.pos--; - } - if (evas_textblock_cursor_format_is_visible_get(cur)) - { - _find_layout_format_item_line_match(cur->obj, - _evas_textblock_node_visible_at_pos_get( - _evas_textblock_cursor_node_format_at_pos_get(cur)), - &ln, &fi); - } - else if (_evas_textblock_cursor_is_at_the_end(cur) && - evas_textblock_cursor_format_is_visible_get(&cur2)) - { - _find_layout_format_item_line_match(cur->obj, - _evas_textblock_node_visible_at_pos_get( - _evas_textblock_cursor_node_format_at_pos_get(&cur2)), - &ln, &fi); - } - else - { - _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it); - } + _find_layout_item_match(cur, &ln, &it); if (!ln) return; if (ln->items) - it = (Evas_Object_Textblock_Item *)((EINA_INLIST_GET(ln->items))->last); - else - it = NULL; - - if (ln->format_items) - fi = (Evas_Object_Textblock_Format_Item *)((EINA_INLIST_GET(ln->format_items))->last); - else - fi = NULL; - if ((it) && (fi)) { - if ((it->x + it->w) > (fi->x + fi->w)) fi = NULL; - else it = NULL; + Evas_Object_Textblock_Item *i; + it = ln->items; + EINA_INLIST_FOREACH(ln->items, i) + { + if (it->text_pos < i->text_pos) + { + it = i; + } + } } if (it) { - int index; + size_t index; - cur->pos = it->source_pos; - cur->node = it->source_node; - index = eina_unicode_strlen(it->text) - 1; - GET_NEXT(it->text, index); - cur->pos += index; - } - else if (fi) - { - cur->node = fi->source_node->text_node; - cur->pos = _evas_textblock_node_format_pos_get(fi->source_node); - /* If it's the last line, advance to the null */ - if (!EINA_INLIST_GET(ln)->next) + cur->node = it->text_node; + cur->pos = it->text_pos; + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + index = _ITEM_TEXT(it)->text_props.text_len - 1; + GET_NEXT(_ITEM_TEXT(it)->text, index); + cur->pos += index; + } + else if (!EINA_INLIST_GET(ln)->next && !EINA_INLIST_GET(ln->par)->next) { cur->pos++; } @@ -5154,7 +5817,7 @@ _evas_textblock_node_text_adjust_offsets_to_start(Evas_Object_Textblock *o, if (!itr || (itr && (itr->text_node != n))) { /* Remove the PS, and return since it's the end of the node */ - if (_IS_PARAGRAPH_SEPARATOR( + if (_IS_PARAGRAPH_SEPARATOR(o, eina_strbuf_string_get(last_node->format))) { _evas_textblock_node_format_remove(o, last_node, 0); @@ -5392,7 +6055,6 @@ evas_textblock_cursor_line_set(Evas_Textblock_Cursor *cur, int line) Evas_Object_Textblock *o; Evas_Object_Textblock_Line *ln; Evas_Object_Textblock_Item *it; - Evas_Object_Textblock_Format_Item *fi; if (!cur) return EINA_FALSE; o = (Evas_Object_Textblock *)(cur->obj->object_data); @@ -5401,22 +6063,10 @@ evas_textblock_cursor_line_set(Evas_Textblock_Cursor *cur, int line) ln = _find_layout_line_num(cur->obj, line); if (!ln) return EINA_FALSE; it = (Evas_Object_Textblock_Item *)ln->items; - fi = (Evas_Object_Textblock_Format_Item *)ln->format_items; - if ((it) && (fi)) - { - if (it->x < fi->x) fi = NULL; - else it = NULL; - } if (it) { - cur->pos = it->source_pos; - - cur->node = it->source_node; - } - else if (fi) - { - cur->node = fi->source_node->text_node; - cur->pos = _evas_textblock_node_format_pos_get(fi->source_node); + cur->pos = it->text_pos; + cur->node = it->text_node; } else { @@ -5518,6 +6168,8 @@ _evas_textblock_node_text_new(void) n = calloc(1, sizeof(Evas_Object_Textblock_Node_Text)); n->unicode = eina_ustrbuf_new(); + /* We want to layout each paragraph at least once. */ + n->dirty = EINA_TRUE; #ifdef BIDI_SUPPORT n->bidi_props = evas_bidi_paragraph_props_new(); n->bidi_props->direction = EVAS_BIDI_PARAGRAPH_NATURAL; @@ -5693,17 +6345,31 @@ _evas_textblock_cursors_update_offset(const Evas_Textblock_Cursor *cur, /** * @internal - * Mark and notifiy that the textblock has changed. + * Mark and notifiy that the textblock, and specifically a node has changed. * * @param o the textblock object. * @param obj the evas object. + * @param n the paragraph that changed - NULL means all. */ static void -_evas_textblock_changed(Evas_Object_Textblock *o, Evas_Object *obj) +_evas_textblock_text_node_changed(Evas_Object_Textblock *o, Evas_Object *obj, + Evas_Object_Textblock_Node_Text *n) { + if (!n) + { + Evas_Object_Textblock_Node_Text *itr; + EINA_INLIST_FOREACH(EINA_INLIST_GET(o->text_nodes), itr) + { + itr->dirty = EINA_TRUE; + } + } + else + { + n->dirty = EINA_TRUE; + } o->formatted.valid = 0; o->native.valid = 0; - o->changed = 1; + o->content_changed = 1; if (o->markup_text) { free(o->markup_text); @@ -5732,7 +6398,7 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *_text) int len = 0; if (!cur) return 0; - text = evas_common_encoding_utf8_to_unicode(_text, &len); + text = eina_unicode_utf8_to_unicode(_text, &len); o = (Evas_Object_Textblock *)(cur->obj->object_data); /* Update all the cursors after our position. */ _evas_textblock_cursors_update_offset(cur, cur->node, cur->pos, len); @@ -5783,7 +6449,7 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *_text) evas_bidi_paragraph_props_unref(n->bidi_props); n->bidi_props = evas_bidi_paragraph_props_get(eina_ustrbuf_string_get(n->unicode)); #endif - _evas_textblock_changed(o, cur->obj); + _evas_textblock_text_node_changed(o, cur->obj, n); free(text); return len; } @@ -5971,8 +6637,7 @@ evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *form /* Advance all the cursors after our cursor */ _evas_textblock_cursors_update_offset(cur, cur->node, cur->pos, 1); - - if (_IS_PARAGRAPH_SEPARATOR(format)) + if (_IS_PARAGRAPH_SEPARATOR(o, format)) { _evas_textblock_cursor_break_paragraph(cur, n); } @@ -5984,10 +6649,9 @@ evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *form eina_ustrbuf_string_get(cur->node->unicode)); #endif } - } - _evas_textblock_changed(o, cur->obj); + _evas_textblock_text_node_changed(o, cur->obj, cur->node); return is_visible; } @@ -6057,7 +6721,7 @@ evas_textblock_cursor_char_delete(Evas_Textblock_Cursor *cur) /* If there's a PS it must be the last become it delimits paragraphs */ last_fmt = _evas_textblock_node_format_last_at_off(fmt); format = eina_strbuf_string_get(last_fmt->format); - if (format && _IS_PARAGRAPH_SEPARATOR(format)) + if (format && _IS_PARAGRAPH_SEPARATOR(o, format)) { merge_nodes = 1; } @@ -6098,7 +6762,7 @@ evas_textblock_cursor_char_delete(Evas_Textblock_Cursor *cur) } _evas_textblock_cursors_update_offset(cur, n, ppos, -(index - ppos)); - _evas_textblock_changed(o, cur->obj); + _evas_textblock_text_node_changed(o, cur->obj, cur->node); } /** @@ -6199,7 +6863,7 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C if (reset_cursor) evas_textblock_cursor_copy(cur1, o->cursor); - _evas_textblock_changed(o, cur1->obj); + _evas_textblock_text_node_changed(o, cur1->obj, cur1->node); } @@ -6228,7 +6892,7 @@ evas_textblock_cursor_content_get(const Evas_Textblock_Cursor *cur) ustr = eina_ustrbuf_string_get(cur->node->unicode); buf[0] = ustr[cur->pos]; buf[1] = 0; - s = evas_common_encoding_unicode_to_utf8(buf, NULL); + s = eina_unicode_unicode_to_utf8(buf, NULL); return s; } @@ -6281,7 +6945,8 @@ evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Ev int off = 0; text_base = text = - eina_unicode_strdup(eina_ustrbuf_string_get(tnode->unicode)); + eina_unicode_strndup(eina_ustrbuf_string_get(tnode->unicode), + eina_ustrbuf_length_get(tnode->unicode)); if (tnode == cur2->node) { fnode = _evas_textblock_node_text_get_first_format_between(tnode, @@ -6499,46 +7164,75 @@ evas_textblock_cursor_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord dir_cur = cur; if (ctype == EVAS_TEXTBLOCK_CURSOR_UNDER) { - ret = evas_textblock_cursor_char_geometry_get(cur, cx, cy, cw, ch); + ret = evas_textblock_cursor_pen_geometry_get(cur, cx, cy, cw, ch); } else if (ctype == EVAS_TEXTBLOCK_CURSOR_BEFORE) { - /*FIXME: Rough sketch, not yet implemented - VERY buggy. */ /* In the case of a "before cursor", we should get the coordinates * of just after the previous char (which in bidi text may not be * just before the current char). */ Evas_Coord x, y, h, w; + Evas_Object_Textblock_Node_Format *fmt; /* If it's at the end of the line, we want to get the position, not * the position of the previous */ if ((cur->pos > 0) && !_evas_textblock_cursor_is_at_the_end(cur)) { - dir_cur = &cur2; + Eina_Bool before_char = EINA_FALSE; cur2.obj = cur->obj; evas_textblock_cursor_copy(cur, &cur2); - cur2.pos--; - ret = evas_textblock_cursor_char_geometry_get(&cur2, &x, &y, &w, &h); + evas_textblock_cursor_char_prev(&cur2); + + fmt = _evas_textblock_cursor_node_format_at_pos_get(&cur2); + + if (!fmt || + !_IS_LINE_SEPARATOR(eina_strbuf_string_get(fmt->format))) + { + dir_cur = &cur2; + before_char = EINA_FALSE; + } + else + { + before_char = EINA_TRUE; + } + ret = evas_textblock_cursor_pen_geometry_get( + dir_cur, &x, &y, &w, &h); #ifdef BIDI_SUPPORT /* Adjust if the char is an rtl char */ if (ret >= 0) { - Evas_BiDi_Props props; - props.props = cur2.node->bidi_props; - props.start = 0; + if ((!before_char && + evas_bidi_is_rtl_char(dir_cur->node->bidi_props, 0, + dir_cur->pos)) || + (before_char && + !evas_bidi_is_rtl_char(dir_cur->node->bidi_props, 0, + dir_cur->pos))) - if (evas_bidi_is_rtl_char(&props, cur2.pos)) { /* Just don't advance the width */ w = 0; } } #endif - + } + else if (cur->pos == 0) + { + ret = evas_textblock_cursor_pen_geometry_get( + dir_cur, &x, &y, &w, &h); +#ifdef BIDI_SUPPORT + /* Adjust if the char is an rtl char */ + if ((ret >= 0) && (!evas_bidi_is_rtl_char( + dir_cur->node->bidi_props, 0, dir_cur->pos))) + { + /* Just don't advance the width */ + w = 0; + } +#endif } else { - ret = evas_textblock_cursor_char_geometry_get(cur, &x, &y, &w, &h); - w = 0; + ret = evas_textblock_cursor_pen_geometry_get( + dir_cur, &x, &y, &w, &h); } if (ret >= 0) { @@ -6552,41 +7246,51 @@ evas_textblock_cursor_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord if (dir && dir_cur && dir_cur->node) { #ifdef BIDI_SUPPORT - Evas_BiDi_Props props; - props.props = dir_cur->node->bidi_props; - props.start = 0; - - *dir = (evas_bidi_is_rtl_char(&props, dir_cur->pos)) ? - EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR; -#else - *dir = EVAS_BIDI_DIRECTION_LTR; + if (_evas_textblock_cursor_is_at_the_end(dir_cur) && (dir_cur->pos > 0)) + { + *dir = (evas_bidi_is_rtl_char(dir_cur->node->bidi_props, 0, + dir_cur->pos - 1)) ? + EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR; + } + else if (dir_cur->pos > 0) + { + *dir = (evas_bidi_is_rtl_char(dir_cur->node->bidi_props, 0, + dir_cur->pos)) ? + EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR; + } + else #endif + { + *dir = EVAS_BIDI_DIRECTION_LTR; + } } return ret; } - /** - * Returns the geometry of the char at cur. + * @internal + * Returns the geometry/pen position (depending on query_func) of the char + * at pos. * * @param cur the position of the char. - * @param cx the x of the char. + * @param query_func the query function to use. + * @param cx the x of the char (or pen_x in the case of pen position). * @param cy the y of the char. - * @param cw the width of the char. - * @param ch the height of the char. + * @param cw the w of the char (or advance in the case pen position). + * @param ch the h of the char. * @return line number of the char on success, -1 on error. */ -EAPI int -evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) +static int +_evas_textblock_cursor_char_pen_geometry_common_get(int (*query_func) (void *data, void *font, const Eina_Unicode *text, 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) { Evas_Object_Textblock *o; Evas_Object_Textblock_Line *ln = NULL; Evas_Object_Textblock_Item *it = NULL; + Evas_Object_Textblock_Text_Item *ti = NULL; Evas_Object_Textblock_Format_Item *fi = NULL; - Evas_Textblock_Cursor cur2; int x = 0, y = 0, w = 0, h = 0; int pos, ret; - int previous_format = 0; + Eina_Bool previous_format; if (!cur) return -1; o = (Evas_Object_Textblock *)(cur->obj->object_data); @@ -6597,64 +7301,53 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C if (!o->paragraphs) return -1; ln = o->paragraphs->lines; if (!ln) return -1; - if (cx) *cx = ln->x; - if (cy) *cy = ln->y; + if (cx) *cx = ln->par->x + ln->x; + if (cy) *cy = ln->par->y + ln->y; if (cw) *cw = ln->w; if (ch) *ch = ln->h; - return ln->line_no; + return ln->par->line_no + ln->line_no; } else return -1; } if (!o->formatted.valid) _relayout(cur->obj); - /* Cur 2 is pointing to the previous char */ - cur2.obj = cur->obj; - evas_textblock_cursor_copy(cur, &cur2); - if (cur2.pos > 0) - { - cur2.pos--; - } - - if (evas_textblock_cursor_format_is_visible_get(cur)) + previous_format = _find_layout_item_match(cur, &ln, &it); + if (!it) { - _find_layout_format_item_line_match(cur->obj, - _evas_textblock_node_visible_at_pos_get( - _evas_textblock_cursor_node_format_at_pos_get(cur)), - &ln, &fi); + return -1; } - else if (_evas_textblock_cursor_is_at_the_end(cur) && - evas_textblock_cursor_format_is_visible_get(&cur2)) + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) { - _find_layout_format_item_line_match(cur->obj, - _evas_textblock_node_visible_at_pos_get( - _evas_textblock_cursor_node_format_at_pos_get(&cur2)), - &ln, &fi); - previous_format = 1; + ti = _ITEM_TEXT(it); } else { - _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it); + fi = _ITEM_FORMAT(it); } - if (ln && it) + + if (ln && ti) { - pos = cur->pos - it->source_pos; + pos = cur->pos - ti->parent.text_pos; ret = -1; if (pos < 0) pos = 0; - if (it->format->font.font) + if (ti->parent.format->font.font) { - ret = cur->ENFN->font_char_coords_get(cur->ENDT, it->format->font.font, - it->text, &it->bidi_props, + ret = query_func(cur->ENDT, + ti->parent.format->font.font, + ti->text, &ti->text_props, pos, &x, &y, &w, &h); } - x += ln->x + it->x; - if (x < ln->x) - { - x = ln->x; - } - y = ln->y; + + x += ln->par->x + ln->x + _ITEM(ti)->x; + + if (x < ln->par->x + ln->x) + { + x = ln->par->x + ln->x; + } + y = ln->par->y + ln->y; h = ln->h; } else if (ln && fi) @@ -6665,21 +7358,31 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C eina_strbuf_string_get(fi->source_node->format))) { x = 0; - y = ln->y + ln->h; + y = ln->par->y + ln->y + ln->h; } else { - x = ln->x + fi->x + fi->w; - y = ln->y; +#ifdef BIDI_SUPPORT + if (EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL( + fi->parent.text_node->bidi_props)) + { + x = ln->par->x + ln->x; + } + else +#endif + { + x = ln->par->x + ln->x + ln->w; + } + y = ln->par->y + ln->y; } w = 0; h = ln->h; } else { - x = ln->x + fi->x; - y = ln->y; - w = fi->w; + x = ln->par->x + ln->x + _ITEM(fi)->x; + y = ln->par->y + ln->y; + w = _ITEM(fi)->w; h = ln->h; } } @@ -6691,7 +7394,41 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C if (cy) *cy = y; if (cw) *cw = w; if (ch) *ch = h; - return ln->line_no; + return ln->par->line_no + ln->line_no; +} + +/** + * Returns the geometry of the char at cur. + * + * @param cur the position of the char. + * @param cx the x of the char. + * @param cy the y of the char. + * @param cw the w of the char. + * @param ch the h of the char. + * @return line number of the char on success, -1 on error. + */ +EAPI int +evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) +{ + return _evas_textblock_cursor_char_pen_geometry_common_get( + cur->ENFN->font_char_coords_get, cur, cx, cy, cw, ch); +} + +/** + * Returns the geometry of the pen at cur. + * + * @param cur the position of the char. + * @param cpen_x the pen_x of the char. + * @param cy the y of the char. + * @param cadv the adv of the char. + * @param ch the h of the char. + * @return line number of the char on success, -1 on error. + */ +EAPI int +evas_textblock_cursor_pen_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) +{ + return _evas_textblock_cursor_char_pen_geometry_common_get( + cur->ENFN->font_pen_coords_get, cur, cx, cy, cw, ch); } /** @@ -6710,8 +7447,6 @@ evas_textblock_cursor_line_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C Evas_Object_Textblock *o; Evas_Object_Textblock_Line *ln = NULL; Evas_Object_Textblock_Item *it = NULL; - Evas_Object_Textblock_Format_Item *fi = NULL; - Evas_Textblock_Cursor cur2; int x, y, w, h; if (!cur) return -1; @@ -6723,160 +7458,455 @@ evas_textblock_cursor_line_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C } else { - /* Cur 2 is pointing to the previous char */ - cur2.obj = cur->obj; - evas_textblock_cursor_copy(cur, &cur2); - if (cur2.pos > 0) + _find_layout_item_match(cur, &ln, &it); + } + if (!ln) return -1; + x = ln->par->x + ln->x; + y = ln->par->y + ln->y; + w = ln->w; + h = ln->h; + if (cx) *cx = x; + if (cy) *cy = y; + if (cw) *cw = w; + if (ch) *ch = h; + return ln->par->line_no + ln->line_no; +} + +/** + * Set the position of the cursor according to the X and Y coordinates. + * + * @param cur the cursor to set. + * @param x coord to set by. + * @param y coord to set by. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + */ +EAPI Eina_Bool +evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y) +{ + Evas_Object_Textblock *o; + Evas_Object_Textblock_Paragraph *par, *found_par = NULL; + Evas_Object_Textblock_Line *ln; + Evas_Object_Textblock_Item *it = NULL, *it_break = NULL; + + if (!cur) return EINA_FALSE; + o = (Evas_Object_Textblock *)(cur->obj->object_data); + if (!o->formatted.valid) _relayout(cur->obj); + x += o->style_pad.l; + y += o->style_pad.t; + EINA_INLIST_FOREACH(o->paragraphs, par) + { + if ((par->x <= x) && (par->x + par->w > x) && + (par->y <= y) && (par->y + par->h > y)) + { + found_par = par; + break; + } + } + if (found_par) + { + EINA_INLIST_FOREACH(found_par->lines, ln) + { + if (ln->par->y + ln->y > y) break; + if ((ln->par->y + ln->y <= y) && ((ln->par->y + ln->y + ln->h) > y)) + { + EINA_INLIST_FOREACH(ln->items, it) + { + if ((it->x + ln->par->x + ln->x) > x) + { + it_break = it; + break; + } + if (((it->x + ln->par->x + ln->x) <= x) && (((it->x + ln->par->x + ln->x) + it->adv) > x)) + { + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + int pos; + int cx, cy, cw, ch; + Evas_Object_Textblock_Text_Item *ti; + ti = _ITEM_TEXT(it); + + pos = -1; + if (ti->parent.format->font.font) + pos = cur->ENFN->font_char_at_coords_get( + cur->ENDT, + ti->parent.format->font.font, + ti->text, &ti->text_props, + x - it->x - ln->par->x - ln->x, 0, + &cx, &cy, &cw, &ch); + if (pos < 0) + return EINA_FALSE; + cur->pos = pos + it->text_pos; + cur->node = it->text_node; + return EINA_TRUE; + } + else + { + Evas_Object_Textblock_Format_Item *fi; + fi = _ITEM_FORMAT(it); + cur->pos = fi->parent.text_pos; + cur->node = fi->source_node->text_node; + return EINA_TRUE; + } + } + } + if (it_break) + { + it = it_break; + cur->node = it->text_node; + cur->pos = it->text_pos; + + /*FIXME: needs smarter handling, ATM just check, if it's + * the first item, then go to the end of the line, helps + * with rtl langs, doesn't affect ltr langs that much. */ + if (!EINA_INLIST_GET(it)->prev) + { + evas_textblock_cursor_line_char_last(cur); + } + + return EINA_TRUE; + } + } + } + } + return EINA_FALSE; +} + +/** + * Set the cursor position according to the y coord. + * + * @param cur the cur to be set. + * @param y the coord to set by. + * @return the line number found, -1 on error. + */ +EAPI int +evas_textblock_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y) +{ + Evas_Object_Textblock *o; + Evas_Object_Textblock_Paragraph *par, *found_par = NULL; + Evas_Object_Textblock_Line *ln; + + if (!cur) return -1; + o = (Evas_Object_Textblock *)(cur->obj->object_data); + if (!o->formatted.valid) _relayout(cur->obj); + y += o->style_pad.t; + + EINA_INLIST_FOREACH(o->paragraphs, par) + { + if ((par->y <= y) && (par->y + par->h > y)) + { + found_par = par; + break; + } + } + + if (found_par) + { + EINA_INLIST_FOREACH(found_par->lines, ln) + { + if (ln->par->y + ln->y > y) break; + if ((ln->par->y + ln->y <= y) && ((ln->par->y + ln->y + ln->h) > y)) + { + evas_textblock_cursor_line_set(cur, ln->par->line_no + + ln->line_no); + return ln->par->line_no + ln->line_no; + } + } + } + return -1; +} + +/** + * @internal + * Updates x and w according to the text direction, position in text and + * if it's a special case switch + * + * @param ti the text item we are working on + * @param x the current x (we get) and the x we return + * @param w the current w (we get) and the w we return + * @param start if this is the first item or not + * @param switch_items toogles item switching (rtl cases) + */ +static void +_evas_textblock_range_calc_x_w(const Evas_Object_Textblock_Item *it, + Evas_Coord *x, Evas_Coord *w, Eina_Bool start, Eina_Bool switch_items) +{ + if ((start && !switch_items) || (!start && switch_items)) + { +#ifdef BIDI_SUPPORT + if (((it->type == EVAS_TEXTBLOCK_ITEM_TEXT) && + _ITEM_TEXT(it)->text_props.bidi.dir == EVAS_BIDI_DIRECTION_RTL) + || + ((it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) && + _ITEM_FORMAT(it)->bidi_dir == EVAS_BIDI_DIRECTION_RTL)) + { + *w = *x + *w; + *x = 0; + } + else +#endif + { + *w = it->adv - *x; + } + } + else + { +#ifdef BIDI_SUPPORT + if (((it->type == EVAS_TEXTBLOCK_ITEM_TEXT) && + _ITEM_TEXT(it)->text_props.bidi.dir == EVAS_BIDI_DIRECTION_RTL) + || + ((it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) && + _ITEM_FORMAT(it)->bidi_dir == EVAS_BIDI_DIRECTION_RTL)) + { + *x = *x + *w; + *w = it->adv - *x; + } + else +#endif + { + *w = *x; + *x = 0; + } + } + +} + +/** + * @internal + * Returns the geometry of the range in line ln. Cur1 is the start cursor, + * cur2 is the end cursor, NULL means from the start or to the end accordingly. + * Assumes that ln is valid, and that at least one of cur1 and cur2 is not NULL. + * + * @param ln the line to work on. + * @param cur1 the start cursor + * @param cur2 the end cursor + * @return Returns the geometry of the range + */ +static Eina_List * +_evas_textblock_cursor_range_in_line_geometry_get( + const Evas_Object_Textblock_Line *ln, const Evas_Textblock_Cursor *cur1, + const Evas_Textblock_Cursor *cur2) +{ + Evas_Object_Textblock_Item *it; + Evas_Object_Textblock_Item *it1, *it2; + Eina_List *rects = NULL; + Evas_Textblock_Rectangle *tr; + size_t start, end; + Eina_Bool switch_items; + const Evas_Textblock_Cursor *cur; + + cur = (cur1) ? cur1 : cur2; + + /* Find the first and last items */ + it1 = it2 = NULL; + start = end = 0; + EINA_INLIST_FOREACH(ln->items, it) + { + size_t item_len; + item_len = (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? + _ITEM_TEXT(it)->text_props.text_len + : 1; + if ((!cur1 || (cur1->pos < it->text_pos + item_len)) && + (!cur2 || (cur2->pos >= it->text_pos))) + { + if (!it1) + { + it1 = it; + start = item_len; /* start stores the first item_len */ + } + it2 = it; + end = item_len; /* end stores the last item_len */ + } + } + + /* If we couldn't find even one item, return */ + if (!it1) return NULL; + + /* If the first item is logically before or equal the second item + * we have to set start and end differently than in the other case */ + if (it1->text_pos <= it2->text_pos) + { + start = (cur1) ? (cur1->pos - it1->text_pos) : 0; + end = (cur2) ? (cur2->pos - it2->text_pos) : end; + switch_items = EINA_FALSE; + } + else + { + start = (cur2) ? (cur2->pos - it1->text_pos) : start; + end = (cur1) ? (cur1->pos - it2->text_pos) : 0; + switch_items = EINA_TRUE; + } + + /* IMPORTANT: Don't use cur1/cur2 past this point (because they probably + * don't make sense anymore. That's why there are start and end), + * unless you know what you are doing */ + + /* Special case when they share the same item and it's a text item */ + if ((it1 == it2) && (it1->type == EVAS_TEXTBLOCK_ITEM_TEXT)) + { + Evas_Coord x1, w1, x2, w2; + Evas_Coord x, w, y, h; + Evas_Object_Textblock_Text_Item *ti; + int ret; + + ti = _ITEM_TEXT(it1); + ret = cur->ENFN->font_pen_coords_get(cur->ENDT, + ti->parent.format->font.font, + ti->text, &ti->text_props, + start, + &x1, &y, &w1, &h); + if (!ret) + { + return NULL; + } + ret = cur->ENFN->font_pen_coords_get(cur->ENDT, + ti->parent.format->font.font, + ti->text, &ti->text_props, + end, + &x2, &y, &w2, &h); + if (!ret) + { + return NULL; + } + + /* Make x2 the one on the right */ + if (x2 < x1) + { + Evas_Coord tmp; + tmp = x1; + x1 = x2; + x2 = tmp; + + tmp = w1; + w1 = w2; + w2 = tmp; + } + +#ifdef BIDI_SUPPORT + if (ti->text_props.bidi.dir == EVAS_BIDI_DIRECTION_RTL) + { + x = x1 + w1; + w = x2 + w2 - x; + } + else +#endif + { + x = x1; + w = x2 - x1; + } + if (w > 0) + { + tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); + rects = eina_list_append(rects, tr); + tr->x = ln->par->x + ln->x + it1->x + x; + tr->y = ln->par->y + ln->y; + tr->h = ln->h; + tr->w = w; + } + } + else if (it1 != it2) + { + /* Get the middle items */ + Evas_Coord min_x, max_x; + Evas_Coord x, w; + it = _ITEM(EINA_INLIST_GET(it1)->next); + min_x = max_x = it->x; + + if (it1->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + Evas_Coord y, h; + Evas_Object_Textblock_Text_Item *ti; + int ret; + ti = _ITEM_TEXT(it1); + + ret = cur->ENFN->font_pen_coords_get(cur->ENDT, + ti->parent.format->font.font, + ti->text, &ti->text_props, + start, + &x, &y, &w, &h); + if (!ret) + { + /* BUG! Skip the first item */ + x = w = 0; + } + else + { + _evas_textblock_range_calc_x_w(it1, &x, &w, EINA_TRUE, + switch_items); + } + } + else + { + x = 0; + w = it1->w; + _evas_textblock_range_calc_x_w(it1, &x, &w, EINA_TRUE, + switch_items); + } + if (w > 0) { - cur2.pos--; + tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); + rects = eina_list_append(rects, tr); + tr->x = ln->par->x + ln->x + it1->x + x; + tr->y = ln->par->y + ln->y; + tr->h = ln->h; + tr->w = w; } - if (evas_textblock_cursor_format_is_visible_get(cur)) + while (it && (it != it2)) + { + max_x = it->x + it->adv; + it = (Evas_Object_Textblock_Item *) EINA_INLIST_GET(it)->next; + } + if (min_x != max_x) { - _find_layout_format_item_line_match(cur->obj, - _evas_textblock_node_visible_at_pos_get( - _evas_textblock_cursor_node_format_at_pos_get(cur)), - &ln, &fi); + tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); + rects = eina_list_append(rects, tr); + tr->x = ln->par->x + ln->x + min_x; + tr->y = ln->par->y + ln->y; + tr->h = ln->h; + tr->w = max_x - min_x; } - else if (_evas_textblock_cursor_is_at_the_end(cur) && - evas_textblock_cursor_format_is_visible_get(&cur2)) + if (it2->type == EVAS_TEXTBLOCK_ITEM_TEXT) { - _find_layout_format_item_line_match(cur->obj, - _evas_textblock_node_visible_at_pos_get( - _evas_textblock_cursor_node_format_at_pos_get(&cur2)), - &ln, &fi); + Evas_Coord y, h; + Evas_Object_Textblock_Text_Item *ti; + int ret; + ti = _ITEM_TEXT(it2); + + ret = cur->ENFN->font_pen_coords_get(cur->ENDT, + ti->parent.format->font.font, + ti->text, &ti->text_props, + end, + &x, &y, &w, &h); + if (!ret) + { + /* BUG! skip the last item */ + x = w = 0; + } + else + { + _evas_textblock_range_calc_x_w(it2, &x, &w, EINA_FALSE, + switch_items); + } } else { - _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it); + x = 0; + w = it2->w; + _evas_textblock_range_calc_x_w(it2, &x, &w, EINA_FALSE, + switch_items); + } + if (w > 0) + { + tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); + rects = eina_list_append(rects, tr); + tr->x = ln->par->x + ln->x + it2->x + x; + tr->y = ln->par->y + ln->y; + tr->h = ln->h; + tr->w = w; } } - if (!ln) return -1; - x = ln->x; - y = ln->y; - w = ln->w; - h = ln->h; - if (cx) *cx = x; - if (cy) *cy = y; - if (cw) *cw = w; - if (ch) *ch = h; - return ln->line_no; -} - -/** - * Set the position of the cursor according to the X and Y coordinates. - * - * @param cur the cursor to set. - * @param x coord to set by. - * @param y coord to set by. - * @return #EINA_TRUE on success, #EINA_FALSE otherwise. - */ -EAPI Eina_Bool -evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y) -{ - Evas_Object_Textblock *o; - Evas_Object_Textblock_Line *ln; - Evas_Object_Textblock_Item *it = NULL, *it_break = NULL; - Evas_Object_Textblock_Format_Item *fi = NULL; - - if (!cur) return EINA_FALSE; - o = (Evas_Object_Textblock *)(cur->obj->object_data); - if (!o->formatted.valid) _relayout(cur->obj); - x += o->style_pad.l; - y += o->style_pad.t; - EINA_INLIST_FOREACH(o->paragraphs->lines, ln) - { - if (ln->y > y) break; - if ((ln->y <= y) && ((ln->y + ln->h) > y)) - { - EINA_INLIST_FOREACH(ln->items, it) - { - if ((it->x + ln->x) > x) - { - it_break = it; - break; - } - if (((it->x + ln->x) <= x) && (((it->x + ln->x) + it->w) > x)) - { - int pos; - int cx, cy, cw, ch; - - pos = -1; - if (it->format->font.font) - pos = cur->ENFN->font_char_at_coords_get(cur->ENDT, - it->format->font.font, - it->text, &it->bidi_props, - x - it->x - ln->x, 0, - &cx, &cy, &cw, &ch); - if (pos < 0) - return EINA_FALSE; - cur->pos = pos + it->source_pos; - cur->node = it->source_node; - return 1; - } - } - EINA_INLIST_FOREACH(ln->format_items, fi) - { - if ((fi->x + ln->x) > x) break; - if (((fi->x + ln->x) <= x) && (((fi->x + ln->x) + fi->w) > x)) - { - cur->pos = - _evas_textblock_node_format_pos_get(fi->source_node); - - cur->node = fi->source_node->text_node; - return EINA_TRUE; - } - } - if (it_break) - { - it = it_break; - cur->node = it->source_node; - cur->pos = it->source_pos; - - /*FIXME: needs smarter handling, ATM just check, if it's - * the first item, then go to the end of the line, helps - * with rtl langs, doesn't affect ltr langs that much. */ - if (!EINA_INLIST_GET(it)->prev) - { - evas_textblock_cursor_line_char_last(cur); - } - - return EINA_TRUE; - } - } - } - return EINA_FALSE; -} - -/** - * Set the cursor position according to the y coord. - * - * @param cur the cur to be set. - * @param y the coord to set by. - * @return the line number found, -1 on error. - */ -EAPI int -evas_textblock_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y) -{ - Evas_Object_Textblock *o; - Evas_Object_Textblock_Line *ln; - - if (!cur) return -1; - o = (Evas_Object_Textblock *)(cur->obj->object_data); - if (!o->formatted.valid) _relayout(cur->obj); - y += o->style_pad.t; - EINA_INLIST_FOREACH(o->paragraphs->lines, ln) - { - if (ln->y > y) break; - if ((ln->y <= y) && ((ln->y + ln->h) > y)) - { - evas_textblock_cursor_line_set(cur, ln->line_no); - return ln->line_no; - } - } - return -1; + return rects; } - /** * Get the geometry of a range. * @@ -6887,14 +7917,17 @@ evas_textblock_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y) EAPI Eina_List * evas_textblock_cursor_range_geometry_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2) { + Evas_Object_Textblock *o; + Evas_Object_Textblock_Line *ln1, *ln2; + Evas_Object_Textblock_Item *it1, *it2; Eina_List *rects = NULL; - Evas_Coord cx, cy, cw, ch, lx, ly, lw, lh; Evas_Textblock_Rectangle *tr; - int i, line, line2; - if (!cur1) return NULL; - if (!cur2) return NULL; + if (!cur1 || !cur1->node) return NULL; + if (!cur2 || !cur2->node) return NULL; if (cur1->obj != cur2->obj) return NULL; + o = (Evas_Object_Textblock *)(cur1->obj->object_data); + if (!o->formatted.valid) _relayout(cur1->obj); if (evas_textblock_cursor_compare(cur1, cur2) > 0) { const Evas_Textblock_Cursor *tc; @@ -6904,76 +7937,52 @@ evas_textblock_cursor_range_geometry_get(const Evas_Textblock_Cursor *cur1, cons cur2 = tc; } - line = evas_textblock_cursor_char_geometry_get(cur1, &cx, &cy, &cw, &ch); - if (line < 0) return NULL; - line = evas_textblock_cursor_line_geometry_get(cur1, &lx, &ly, &lw, &lh); - if (line < 0) return NULL; - line2 = evas_textblock_cursor_line_geometry_get(cur2, NULL, NULL, NULL, NULL); - if (line2 < 0) return NULL; + ln1 = ln2 = NULL; + it1 = it2 = NULL; + _find_layout_item_match(cur1, &ln1, &it1); + if (!ln1 || !it1) return NULL; + _find_layout_item_match(cur2, &ln2, &it2); + if (!ln2 || !it2) return NULL; - if (line == line2) + if (ln1 == ln2) { - tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); - rects = eina_list_append(rects, tr); - tr->x = cx; - tr->y = ly; - tr->h = lh; - line = evas_textblock_cursor_char_geometry_get(cur2, &cx, &cy, &cw, &ch); - if (line < 0) - { - while (rects) - { - free(rects->data); - rects = eina_list_remove_list(rects, rects); - } - return NULL; - } - tr->w = cx - tr->x; + rects = _evas_textblock_cursor_range_in_line_geometry_get(ln1, + cur1, cur2); } else { - tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); - rects = eina_list_append(rects, tr); - tr->x = cx; - tr->y = ly; - tr->h = lh; - tr->w = lx + lw - cx; - for (i = line +1; i < line2; i++) - { - evas_object_textblock_line_number_geometry_get(cur1->obj, i, &lx, &ly, &lw, &lh); + Evas_Object_Textblock_Line *plni, *lni; + Eina_List *rects2 = NULL; + /* Handle the first line */ + rects = _evas_textblock_cursor_range_in_line_geometry_get(ln1, + cur1, NULL); + + /* Handle the lines between the first and the last line */ + lni = (Evas_Object_Textblock_Line *) EINA_INLIST_GET(ln1)->next; + if (!lni && (ln1->par != ln2->par)) + { + lni = ((Evas_Object_Textblock_Paragraph *) + EINA_INLIST_GET(ln1->par)->next)->lines; + } + while (lni && (lni != ln2)) + { tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); rects = eina_list_append(rects, tr); - tr->x = lx; - tr->y = ly; - tr->h = lh; - tr->w = lw; - } - line = evas_textblock_cursor_char_geometry_get(cur2, &cx, &cy, &cw, &ch); - if (line < 0) - { - while (rects) - { - free(rects->data); - rects = eina_list_remove_list(rects, rects); - } - return NULL; - } - line = evas_textblock_cursor_line_geometry_get(cur2, &lx, &ly, &lw, &lh); - if (line < 0) - { - while (rects) - { - free(rects->data); - rects = eina_list_remove_list(rects, rects); - } - return NULL; - } - tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); - rects = eina_list_append(rects, tr); - tr->x = lx; - tr->y = ly; - tr->h = lh; - tr->w = cx - lx; + tr->x = lni->par->x + lni->x; + tr->y = lni->par->y + lni->y; + tr->h = lni->h; + tr->w = lni->w; + plni = lni; + lni = (Evas_Object_Textblock_Line *) EINA_INLIST_GET(lni)->next; + if (!lni && (plni->par != ln2->par)) + { + lni = ((Evas_Object_Textblock_Paragraph *) + EINA_INLIST_GET(plni->par)->next)->lines; + } + } + rects2 = _evas_textblock_cursor_range_in_line_geometry_get(ln2, + NULL, cur2); + rects = eina_list_merge(rects, rects2); } return rects; } @@ -6992,26 +8001,26 @@ evas_textblock_cursor_format_item_geometry_get(const Evas_Textblock_Cursor *cur, { Evas_Object_Textblock *o; Evas_Object_Textblock_Line *ln = NULL; - Evas_Object_Textblock_Format_Item *fi = NULL; + Evas_Object_Textblock_Format_Item *fi; + Evas_Object_Textblock_Item *it = NULL; Evas_Coord x, y, w, h; - if (!cur || !evas_textblock_cursor_format_is_visible_get(cur)) return 0; + if (!cur || !evas_textblock_cursor_format_is_visible_get(cur)) return EINA_FALSE; o = (Evas_Object_Textblock *)(cur->obj->object_data); if (!o->formatted.valid) _relayout(cur->obj); - _find_layout_format_item_line_match(cur->obj, - _evas_textblock_node_visible_at_pos_get( - _evas_textblock_cursor_node_format_at_pos_get(cur)), - &ln, &fi); - if ((!ln) || (!fi)) return 0; - x = ln->x + fi->x; - y = ln->y + ln->baseline + fi->y; - w = fi->w; - h = fi->h; + if (!evas_textblock_cursor_format_is_visible_get(cur)) return EINA_FALSE; + _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it); + fi = _ITEM_FORMAT(it); + if ((!ln) || (!fi)) return EINA_FALSE; + x = ln->par->x + ln->x + fi->parent.x; + y = ln->par->y + ln->y + ln->baseline + fi->y; + w = fi->parent.w; + h = fi->parent.h; if (cx) *cx = x; if (cy) *cy = y; if (cw) *cw = w; if (ch) *ch = h; - return 1; + return EINA_TRUE; } /** @@ -7056,8 +8065,8 @@ evas_object_textblock_line_number_geometry_get(const Evas_Object *obj, int line, TB_HEAD_RETURN(0); ln = _find_layout_line_num(obj, line); if (!ln) return EINA_FALSE; - if (cx) *cx = ln->x; - if (cy) *cy = ln->y; + if (cx) *cx = ln->par->x + ln->x; + if (cy) *cy = ln->par->y + ln->y; if (cw) *cw = ln->w; if (ch) *ch = ln->h; return EINA_TRUE; @@ -7088,10 +8097,10 @@ evas_object_textblock_clear(Evas_Object *obj) } if (o->paragraphs) { - _paragraphs_clear(obj, o->paragraphs); + _paragraphs_free(obj, o->paragraphs); o->paragraphs = NULL; } - _evas_textblock_changed(o, obj); + _evas_textblock_text_node_changed(o, obj, NULL); } /** @@ -7154,6 +8163,7 @@ evas_object_textblock_size_native_get(const Evas_Object *obj, Evas_Coord *w, Eva -1, -1, &o->native.w, &o->native.h); o->native.valid = 1; + o->content_changed = 0; } if (w) *w = o->native.w; if (h) *h = o->native.h; @@ -7205,6 +8215,7 @@ evas_object_textblock_init(Evas_Object *obj) o = (Evas_Object_Textblock *)(obj->object_data); o->cursor->obj = obj; + o->newline_is_ps = EINA_TRUE; } static void * @@ -7250,14 +8261,14 @@ evas_object_textblock_free(Evas_Object *obj) static void evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y) { + Evas_Object_Textblock_Paragraph *par; Evas_Object_Textblock_Line *ln; Evas_Object_Textblock *o; int i, j; - int pback = 0, backx = 0; - int pline = 0, linex = 0; - int pline2 = 0, line2x = 0; - int pstrike = 0, strikex = 0; - int x2; + int pbacking = 0, backingx = 0; + int punderline = 0, underlinex = 0; + int punderline2 = 0, underline2x = 0; + int pstrikethrough = 0, strikethroughx = 0; unsigned char r = 0, g = 0, b = 0, a = 0; unsigned char r2 = 0, g2 = 0, b2 = 0, a2 = 0; unsigned char r3 = 0, g3 = 0, b3 = 0, a3 = 0; @@ -7281,396 +8292,266 @@ evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void if (!o->paragraphs) return; #define ITEM_WALK() \ - EINA_INLIST_FOREACH(o->paragraphs->lines, ln) \ + EINA_INLIST_FOREACH(o->paragraphs, par) \ { \ - Evas_Object_Textblock_Item *it; \ - \ - pback = 0; \ - pline = 0; \ - pline2 = 0; \ - pstrike = 0; \ - if (clip) \ + EINA_INLIST_FOREACH(par->lines, ln) \ { \ - if ((obj->cur.geometry.y + y + ln->y + ln->h) < (cy - 20)) \ - continue; \ - if ((obj->cur.geometry.y + y + ln->y) > (cy + ch + 20)) \ - break; \ - } \ - EINA_INLIST_FOREACH(ln->items, it) \ - { \ - int yoff; \ + Evas_Object_Textblock_Item *itr; \ \ - yoff = ln->baseline; \ - if (it->format->valign != -1.0) \ - yoff = (it->format->valign * (double)(ln->h - it->h)) + it->baseline; \ + backingx = underlinex = underline2x = strikethroughx = 0; \ + pbacking = punderline = punderline2 = pstrikethrough = 0; \ if (clip) \ { \ - if ((obj->cur.geometry.x + x + ln->x + it->x + it->w) < (cx - 20)) \ + if ((obj->cur.geometry.y + y + ln->par->y + ln->y + ln->h) < (cy - 20)) \ continue; \ - if ((obj->cur.geometry.x + x + ln->x + it->x) > (cx + cw + 20)) \ + if ((obj->cur.geometry.y + y + ln->par->y + ln->y) > (cy + ch + 20)) \ break; \ - } + } \ + EINA_INLIST_FOREACH(ln->items, itr) \ + { \ + int yoff; \ + yoff = ln->baseline; \ + if (itr->format->valign != -1.0) \ + yoff = (itr->format->valign * (double)(ln->h - itr->h)) + \ + (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? \ + _ITEM_TEXT(itr)->baseline : ln->baseline; \ + if (clip) \ + { \ + if ((obj->cur.geometry.x + x + ln->par->x + ln->x + itr->x + itr->w) < (cx - 20)) \ + continue; \ + if ((obj->cur.geometry.x + x + ln->par->x + ln->x + itr->x) > (cx + cw + 20)) \ + break; \ + } \ + do #define ITEM_WALK_END() \ + while (0); \ + } \ } \ - } + } \ + do {} while(0) #define COLOR_SET(col) \ ENFN->context_color_set(output, context, \ - (obj->cur.cache.clip.r * it->format->color.col.r) / 255, \ - (obj->cur.cache.clip.g * it->format->color.col.g) / 255, \ - (obj->cur.cache.clip.b * it->format->color.col.b) / 255, \ - (obj->cur.cache.clip.a * it->format->color.col.a) / 255); + (obj->cur.cache.clip.r * ti->parent.format->color.col.r) / 255, \ + (obj->cur.cache.clip.g * ti->parent.format->color.col.g) / 255, \ + (obj->cur.cache.clip.b * ti->parent.format->color.col.b) / 255, \ + (obj->cur.cache.clip.a * ti->parent.format->color.col.a) / 255); #define COLOR_SET_AMUL(col, amul) \ ENFN->context_color_set(output, context, \ - (obj->cur.cache.clip.r * it->format->color.col.r * (amul)) / 65025, \ - (obj->cur.cache.clip.g * it->format->color.col.g * (amul)) / 65025, \ - (obj->cur.cache.clip.b * it->format->color.col.b * (amul)) / 65025, \ - (obj->cur.cache.clip.a * it->format->color.col.a * (amul)) / 65025); -# define DRAW_TEXT(ox, oy) \ - if (it->format->font.font) ENFN->font_draw(output, context, surface, it->format->font.font, \ - obj->cur.geometry.x + ln->x + it->x + x + (ox), \ - obj->cur.geometry.y + ln->y + yoff + y + (oy), \ - it->w, it->h, it->w, it->h, it->text, &it->bidi_props); -# if 0 + (obj->cur.cache.clip.r * ti->parent.format->color.col.r * (amul)) / 65025, \ + (obj->cur.cache.clip.g * ti->parent.format->color.col.g * (amul)) / 65025, \ + (obj->cur.cache.clip.b * ti->parent.format->color.col.b * (amul)) / 65025, \ + (obj->cur.cache.clip.a * ti->parent.format->color.col.a * (amul)) / 65025); #define DRAW_TEXT(ox, oy) \ - if (it->format->font.font) ENFN->font_draw(output, context, surface, it->format->font.font, \ - obj->cur.geometry.x + ln->x + it->x - it->inset + x + (ox), \ - obj->cur.geometry.y + ln->y + yoff + y + (oy), \ - obj->cur.cache.geometry.x + ln->x + it->x - it->inset + x + (ox), \ - obj->cur.cache.geometry.y + ln->y + yoff + y + (oy), \ - it->w, it->h, it->w, it->h, it->text, &it->bidi_props); -#endif + if (ti->parent.format->font.font) ENFN->font_draw(output, context, surface, ti->parent.format->font.font, \ + obj->cur.geometry.x + ln->par->x + ln->x + ti->parent.x + x + (ox), \ + obj->cur.geometry.y + ln->par->y + ln->y + yoff + y + (oy), \ + ti->parent.w, ti->parent.h, ti->parent.w, ti->parent.h, ti->text, &ti->text_props); #define ITEM_WALK_LINE_SKIP_DROP() \ - if ((ln->y + ln->h) <= 0) continue; \ - if (ln->y > obj->cur.geometry.h) break + if ((ln->par->y + ln->y + ln->h) <= 0) continue; \ + if (ln->par->y + ln->y > obj->cur.geometry.h) break + - pback = 0; /* backing */ - ITEM_WALK(); - ITEM_WALK_LINE_SKIP_DROP(); - if ((it->format->backing) && (!pback) && ((EINA_INLIST_GET(it))->next)) - { - pback = 1; - backx = it->x; - r = it->format->color.backing.r; - g = it->format->color.backing.g; - b = it->format->color.backing.b; - a = it->format->color.backing.a; - } - else if (((pback) && (!it->format->backing)) || - (!(EINA_INLIST_GET(it))->next) || - (it->format->color.backing.r != r) || - (it->format->color.backing.g != g) || - (it->format->color.backing.b != b) || - (it->format->color.backing.a != a)) - { - if ((it->format->backing) && (!pback) && (!(EINA_INLIST_GET(it))->next)) - { - r = it->format->color.backing.r; - g = it->format->color.backing.g; - b = it->format->color.backing.b; - a = it->format->color.backing.a; - pback = 1; - backx = it->x; - } - if (!it->format->backing) x2 = it->x; - else x2 = it->x + it->w; - if ((pback) && (x2 > backx)) - { - ENFN->context_color_set(output, - context, - (obj->cur.cache.clip.r * r) / 255, - (obj->cur.cache.clip.g * g) / 255, - (obj->cur.cache.clip.b * b) / 255, - (obj->cur.cache.clip.a * a) / 255); - ENFN->rectangle_draw(output, - context, - surface, - obj->cur.geometry.x + ln->x + backx + x, - obj->cur.geometry.y + ln->y + y, -//// obj->cur.cache.geometry.x + ln->x + backx + x, -//// obj->cur.cache.geometry.y + ln->y + y, - x2 - backx, - ln->h); - } - pback = it->format->backing; - backx = it->x; - r = it->format->color.backing.r; - g = it->format->color.backing.g; - b = it->format->color.backing.b; - a = it->format->color.backing.a; +#define DRAW_RECT(ox, oy, ow, oh, or, og, ob, oa) \ + do \ + { \ + ENFN->context_color_set(output, \ + context, \ + (obj->cur.cache.clip.r * or) / 255, \ + (obj->cur.cache.clip.g * og) / 255, \ + (obj->cur.cache.clip.b * ob) / 255, \ + (obj->cur.cache.clip.a * oa) / 255); \ + ENFN->rectangle_draw(output, \ + context, \ + surface, \ + obj->cur.geometry.x + ln->par->x + ln->x + x + (ox), \ + obj->cur.geometry.y + ln->par->y + ln->y + y + (oy), \ + (ow), \ + (oh)); \ + } \ + while (0) + +#define DRAW_FORMAT(oname, oy, oh, or, og, ob, oa) \ + do \ + { \ + if ((p ## oname) && (itr->x > oname ## x)) \ + { \ + DRAW_RECT(oname ## x, oy, itr->x - oname ## x, oh, or, og, ob, \ + oa); \ + } \ + \ + if (itr->format->oname) \ + { \ + p ## oname = 1; \ + or = itr->format->color.oname.r; \ + og = itr->format->color.oname.g; \ + ob = itr->format->color.oname.b; \ + oa = itr->format->color.oname.a; \ + } \ + else \ + { \ + p ## oname = 0; \ + } \ + \ + if (p ## oname && !EINA_INLIST_GET(itr)->next) \ + { \ + DRAW_RECT(itr->x, oy, itr->w, oh, or, og, ob, oa); \ + } \ + p ## oname = itr->format->oname; \ + oname ## x = itr->x; \ + } \ + while (0) + + + pbacking = punderline = punderline2 = pstrikethrough = 0; + ITEM_WALK() + { + ITEM_WALK_LINE_SKIP_DROP(); + + DRAW_FORMAT(backing, 0, ln->h, r, g, b, a); } ITEM_WALK_END(); /* prepare everything for text draw */ /* shadows */ - ITEM_WALK(); - ITEM_WALK_LINE_SKIP_DROP(); - if (it->format->style == EVAS_TEXT_STYLE_SHADOW) - { - COLOR_SET(shadow); - DRAW_TEXT(1, 1); - } - else if ((it->format->style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || - (it->format->style == EVAS_TEXT_STYLE_FAR_SHADOW)) - { - COLOR_SET(shadow); - DRAW_TEXT(2, 2); - } - else if ((it->format->style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW) || - (it->format->style == EVAS_TEXT_STYLE_FAR_SOFT_SHADOW)) - { - for (j = 0; j < 5; j++) - { - for (i = 0; i < 5; i++) - { - if (vals[i][j] != 0) - { - COLOR_SET_AMUL(shadow, vals[i][j] * 50); - DRAW_TEXT(i, j); - } - } - } - } - else if (it->format->style == EVAS_TEXT_STYLE_SOFT_SHADOW) + ITEM_WALK() { - for (j = 0; j < 5; j++) - { - for (i = 0; i < 5; i++) - { - if (vals[i][j] != 0) - { - COLOR_SET_AMUL(shadow, vals[i][j] * 50); - DRAW_TEXT(i - 1, j - 1); - } - } - } + Evas_Object_Textblock_Text_Item *ti; + ITEM_WALK_LINE_SKIP_DROP(); + ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL; + if (!ti) continue; + + if (ti->parent.format->style == EVAS_TEXT_STYLE_SHADOW) + { + COLOR_SET(shadow); + DRAW_TEXT(1, 1); + } + else if ((ti->parent.format->style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || + (ti->parent.format->style == EVAS_TEXT_STYLE_FAR_SHADOW)) + { + COLOR_SET(shadow); + DRAW_TEXT(2, 2); + } + else if ((ti->parent.format->style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW) || + (ti->parent.format->style == EVAS_TEXT_STYLE_FAR_SOFT_SHADOW)) + { + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + if (vals[i][j] != 0) + { + COLOR_SET_AMUL(shadow, vals[i][j] * 50); + DRAW_TEXT(i, j); + } + } + } + } + else if (ti->parent.format->style == EVAS_TEXT_STYLE_SOFT_SHADOW) + { + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + if (vals[i][j] != 0) + { + COLOR_SET_AMUL(shadow, vals[i][j] * 50); + DRAW_TEXT(i - 1, j - 1); + } + } + } + } } ITEM_WALK_END(); /* glows */ - ITEM_WALK(); - ITEM_WALK_LINE_SKIP_DROP(); - if (it->format->style == EVAS_TEXT_STYLE_GLOW) + ITEM_WALK() { - for (j = 0; j < 5; j++) - { - for (i = 0; i < 5; i++) - { - if (vals[i][j] != 0) - { - COLOR_SET_AMUL(glow, vals[i][j] * 50); - DRAW_TEXT(i - 2, j - 2); - } - } - } - COLOR_SET(glow2); - DRAW_TEXT(-1, 0); - DRAW_TEXT(1, 0); - DRAW_TEXT(0, -1); - DRAW_TEXT(0, 1); + Evas_Object_Textblock_Text_Item *ti; + ITEM_WALK_LINE_SKIP_DROP(); + ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL; + if (!ti) continue; + + if (ti->parent.format->style == EVAS_TEXT_STYLE_GLOW) + { + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + if (vals[i][j] != 0) + { + COLOR_SET_AMUL(glow, vals[i][j] * 50); + DRAW_TEXT(i - 2, j - 2); + } + } + } + COLOR_SET(glow2); + DRAW_TEXT(-1, 0); + DRAW_TEXT(1, 0); + DRAW_TEXT(0, -1); + DRAW_TEXT(0, 1); + } } ITEM_WALK_END(); /* outlines */ - ITEM_WALK(); - ITEM_WALK_LINE_SKIP_DROP(); - if ((it->format->style == EVAS_TEXT_STYLE_OUTLINE) || - (it->format->style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || - (it->format->style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW)) - { - COLOR_SET(outline); - DRAW_TEXT(-1, 0); - DRAW_TEXT(1, 0); - DRAW_TEXT(0, -1); - DRAW_TEXT(0, 1); - } - else if (it->format->style == EVAS_TEXT_STYLE_SOFT_OUTLINE) + ITEM_WALK() { - for (j = 0; j < 5; j++) - { - for (i = 0; i < 5; i++) - { - if (((i != 2) || (j != 2)) && (vals[i][j] != 0)) - { - COLOR_SET_AMUL(outline, vals[i][j] * 50); - DRAW_TEXT(i - 2, j - 2); - } - } - } + Evas_Object_Textblock_Text_Item *ti; + ITEM_WALK_LINE_SKIP_DROP(); + ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL; + if (!ti) continue; + + if ((ti->parent.format->style == EVAS_TEXT_STYLE_OUTLINE) || + (ti->parent.format->style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) || + (ti->parent.format->style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW)) + { + COLOR_SET(outline); + DRAW_TEXT(-1, 0); + DRAW_TEXT(1, 0); + DRAW_TEXT(0, -1); + DRAW_TEXT(0, 1); + } + else if (ti->parent.format->style == EVAS_TEXT_STYLE_SOFT_OUTLINE) + { + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + if (((i != 2) || (j != 2)) && (vals[i][j] != 0)) + { + COLOR_SET_AMUL(outline, vals[i][j] * 50); + DRAW_TEXT(i - 2, j - 2); + } + } + } + } } ITEM_WALK_END(); - /* normal text */ - ITEM_WALK(); - ITEM_WALK_LINE_SKIP_DROP(); - COLOR_SET(normal); - DRAW_TEXT(0, 0); - if ((it->format->strikethrough) && (!pstrike) && ((EINA_INLIST_GET(it))->next)) - { - pstrike = 1; - strikex = it->x; - r3 = it->format->color.strikethrough.r; - g3 = it->format->color.strikethrough.g; - b3 = it->format->color.strikethrough.b; - a3 = it->format->color.strikethrough.a; - } - else if (((pstrike) && (!it->format->strikethrough)) || - (!(EINA_INLIST_GET(it))->next) || - (it->format->color.strikethrough.r != r3) || - (it->format->color.strikethrough.g != g3) || - (it->format->color.strikethrough.b != b3) || - (it->format->color.strikethrough.a != a3)) - { - if ((it->format->strikethrough) && (!pstrike)) - { - strikex = it->x; - r3 = it->format->color.strikethrough.r; - g3 = it->format->color.strikethrough.g; - b3 = it->format->color.strikethrough.b; - a3 = it->format->color.strikethrough.a; - } - x2 = it->x + it->w; - if (!it->format->strikethrough) - { - x2 = it->x; - pstrike = 0; - } - if (x2 > strikex) - { - ENFN->context_color_set(output, - context, - (obj->cur.cache.clip.r * r3) / 255, - (obj->cur.cache.clip.g * g3) / 255, - (obj->cur.cache.clip.b * b3) / 255, - (obj->cur.cache.clip.a * a3) / 255); - ENFN->rectangle_draw(output, - context, - surface, - obj->cur.geometry.x + ln->x + strikex + x, - obj->cur.geometry.y + ln->y + y + (ln->h / 2), -//// obj->cur.cache.geometry.x + ln->x + strikex + x, -//// obj->cur.cache.geometry.y + ln->y + y + (ln->h / 2), - x2 - strikex, - 1); - } - if (it->format->strikethrough) pstrike = 1; - strikex = it->x; - r3 = it->format->color.strikethrough.r; - g3 = it->format->color.strikethrough.g; - b3 = it->format->color.strikethrough.b; - a3 = it->format->color.strikethrough.a; - } - if ((it->format->underline) && (!pline) && ((EINA_INLIST_GET(it))->next)) - { - pline = 1; - linex = it->x; - r = it->format->color.underline.r; - g = it->format->color.underline.g; - b = it->format->color.underline.b; - a = it->format->color.underline.a; - } - else if (((pline) && (!it->format->underline)) || - (!(EINA_INLIST_GET(it))->next) || - (it->format->color.underline.r != r) || - (it->format->color.underline.g != g) || - (it->format->color.underline.b != b) || - (it->format->color.underline.a != a)) - { - if ((it->format->underline) && (!pline)) - { - linex = it->x; - r = it->format->color.underline.r; - g = it->format->color.underline.g; - b = it->format->color.underline.b; - a = it->format->color.underline.a; - } - x2 = it->x + it->w; - if (!it->format->underline) - { - x2 = it->x; - pline = 0; - } - if (x2 > linex) - { - ENFN->context_color_set(output, - context, - (obj->cur.cache.clip.r * r) / 255, - (obj->cur.cache.clip.g * g) / 255, - (obj->cur.cache.clip.b * b) / 255, - (obj->cur.cache.clip.a * a) / 255); - ENFN->rectangle_draw(output, - context, - surface, - obj->cur.geometry.x + ln->x + linex + x, - obj->cur.geometry.y + ln->y + y + ln->baseline + 1, -//// obj->cur.cache.geometry.x + ln->x + linex + x, -//// obj->cur.cache.geometry.y + ln->y + y + ln->baseline + 1, - x2 - linex, - 1); - } - if (it->format->underline) pline = 1; - linex = it->x; - r = it->format->color.underline.r; - g = it->format->color.underline.g; - b = it->format->color.underline.b; - a = it->format->color.underline.a; - } - if ((it->format->underline2) && (!pline2) && ((EINA_INLIST_GET(it))->next)) - { - pline2 = 1; - line2x = it->x; - r2 = it->format->color.underline2.r; - g2 = it->format->color.underline2.g; - b2 = it->format->color.underline2.b; - a2 = it->format->color.underline2.a; - } - else if (((pline2) && (!it->format->underline2)) || - (!(EINA_INLIST_GET(it))->next) || - (it->format->color.underline2.r != r2) || - (it->format->color.underline2.g != g2) || - (it->format->color.underline2.b != b2) || - (it->format->color.underline2.a != a2)) - { - if ((it->format->underline2) && (!pline2)) - { - line2x = it->x; - r2 = it->format->color.underline2.r; - g2 = it->format->color.underline2.g; - b2 = it->format->color.underline2.b; - a2 = it->format->color.underline2.a; - } - x2 = it->x + it->w; - if (!it->format->underline2) - { - x2 = it->x; - pline2 = 0; - } - if (x2 > line2x) - { - ENFN->context_color_set(output, - context, - (obj->cur.cache.clip.r * r2) / 255, - (obj->cur.cache.clip.g * g2) / 255, - (obj->cur.cache.clip.b * b2) / 255, - (obj->cur.cache.clip.a * a2) / 255); - ENFN->rectangle_draw(output, - context, - surface, - obj->cur.geometry.x + ln->x + line2x + x, - obj->cur.geometry.y + ln->y + y + ln->baseline + 3, -//// obj->cur.cache.geometry.x + ln->x + line2x + x, -//// obj->cur.cache.geometry.y + ln->y + y + ln->baseline + 3, - x2 - line2x, - 1); - } - if (it->format->underline2) pline2 = 1; - line2x = it->x; - r2 = it->format->color.underline2.r; - g2 = it->format->color.underline2.g; - b2 = it->format->color.underline2.b; - a2 = it->format->color.underline2.a; + /* normal text and lines */ + ITEM_WALK() + { + Evas_Object_Textblock_Text_Item *ti; + ITEM_WALK_LINE_SKIP_DROP(); + ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL; + /* NORMAL TEXT */ + if (ti) + { + COLOR_SET(normal); + DRAW_TEXT(0, 0); + } + + /* STRIKETHROUGH */ + DRAW_FORMAT(strikethrough, (ln->h / 2), 1, r, g, b, a); + + /* UNDERLINE */ + DRAW_FORMAT(underline, ln->baseline + 1, 1, r2, g2, b2, a2); + + /* UNDERLINE2 */ + DRAW_FORMAT(underline2, ln->baseline + 3, 1, r3, g3, b3, a3); } ITEM_WALK_END(); } @@ -7690,28 +8571,20 @@ evas_object_textblock_render_pre(Evas_Object *obj) /* then when this is done the object needs to figure if it changed and */ /* if so what and where and add the appropriate redraw textblocks */ o = (Evas_Object_Textblock *)(obj->object_data); - if ((o->changed) || + if ((o->changed) || (o->content_changed) || (o->last_w != obj->cur.geometry.w)) { - Evas_Object_Textblock_Paragraph *paragraphs; - - paragraphs = o->paragraphs; - o->paragraphs = NULL; o->formatted.valid = 0; - o->native.valid = 0; _layout(obj, 0, obj->cur.geometry.w, obj->cur.geometry.h, &o->formatted.w, &o->formatted.h); o->formatted.valid = 1; - if (paragraphs) - { - _paragraphs_clear(obj, paragraphs); - } o->last_w = obj->cur.geometry.w; o->redraw = 0; evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); o->changed = 0; + o->content_changed = 0; is_v = evas_object_is_visible(obj); was_v = evas_object_was_visible(obj); goto done; @@ -7721,6 +8594,7 @@ evas_object_textblock_render_pre(Evas_Object *obj) o->redraw = 0; evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); o->changed = 0; + o->content_changed = 0; is_v = evas_object_is_visible(obj); was_v = evas_object_was_visible(obj); goto done; @@ -7777,10 +8651,11 @@ evas_object_textblock_render_pre(Evas_Object *obj) evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); goto done; } - if (o->changed) + if (o->changed || o->content_changed) { evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); o->changed = 0; + o->content_changed = 0; } done: evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, obj, is_v, was_v); @@ -7855,7 +8730,6 @@ evas_object_textblock_coords_recalc(Evas_Object *obj) if (obj->cur.geometry.w != o->last_w) { o->formatted.valid = 0; - o->native.valid = 0; o->changed = 1; } } @@ -7870,30 +8744,35 @@ void _evas_object_textblock_rehint(Evas_Object *obj) { Evas_Object_Textblock *o; + Evas_Object_Textblock_Paragraph *par; Evas_Object_Textblock_Line *ln; o = (Evas_Object_Textblock *)(obj->object_data); - EINA_INLIST_FOREACH(o->paragraphs->lines, ln) + EINA_INLIST_FOREACH(o->paragraphs, par) { - Evas_Object_Textblock_Item *it; + EINA_INLIST_FOREACH(par->lines, ln) + { + Evas_Object_Textblock_Item *it; - EINA_INLIST_FOREACH(ln->items, it) - { - if (it->format->font.font) - { + EINA_INLIST_FOREACH(ln->items, it) + { + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it); + if (ti->parent.format->font.font) + { #ifdef EVAS_FRAME_QUEUING - evas_common_pipe_op_text_flush(it->format->font.font); + evas_common_pipe_op_text_flush(ti->parent.format->font.font); #endif - evas_font_load_hinting_set(obj->layer->evas, - it->format->font.font, - obj->layer->evas->hinting); - } - } + evas_font_load_hinting_set(obj->layer->evas, + ti->parent.format->font.font, + obj->layer->evas->hinting); + } + } + } + } } - o->formatted.valid = 0; - o->native.valid = 0; - o->changed = 1; - evas_object_change(obj); + _evas_textblock_text_node_changed(o, obj, NULL); } /** @@ -7909,7 +8788,7 @@ pfnode(Evas_Object_Textblock_Node_Format *n) printf("Format Node: %p\n", n); printf("next = %p, prev = %p, last = %p\n", EINA_INLIST_GET(n)->next, EINA_INLIST_GET(n)->prev, EINA_INLIST_GET(n)->last); printf("text_node = %p, offset = %u, visible = %d\n", n->text_node, n->offset, n->visible); - printf("%s\n", eina_strbuf_string_get(n->format)); + printf("'%s'\n", eina_strbuf_string_get(n->format)); } void @@ -7918,7 +8797,49 @@ ptnode(Evas_Object_Textblock_Node_Text *n) printf("Text Node: %p\n", n); printf("next = %p, prev = %p, last = %p\n", EINA_INLIST_GET(n)->next, EINA_INLIST_GET(n)->prev, EINA_INLIST_GET(n)->last); printf("format_node = %p\n", n->format_node); - printf("%ls\n", eina_ustrbuf_string_get(n->unicode)); + printf("'%ls'\n", eina_ustrbuf_string_get(n->unicode)); +} + +void +pitem(Evas_Object_Textblock_Item *it) +{ + Evas_Object_Textblock_Text_Item *ti; + Evas_Object_Textblock_Format_Item *fi; + printf("Item: %p\n", it); + printf("Type: %s (%d)\n", (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? + "TEXT" : "FORMAT", it->type); + printf("Text pos: %d Visual pos: %d\n", it->text_pos, +#ifdef BIDI_SUPPORT + it->visual_pos +#else + it->text_pos +#endif + ); + printf("Coords: x = %d w = %d adv = %d\n", (int) it->x, (int) it->w, + (int) it->adv); + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + ti = _ITEM_TEXT(it); + printf("Text: '%ls'\n", ti->text); + } + else + { + fi = _ITEM_FORMAT(it); + printf("Format: '%s'\n", fi->item); + } } + +void +ppar(Evas_Object_Textblock_Paragraph *par) +{ + Evas_Object_Textblock_Item *it; + Eina_List *i; + EINA_LIST_FOREACH(par->logical_items, i, it) + { + printf("***********************\n"); + pitem(it); + } +} + #endif diff --git a/src/lib/canvas/evas_render.c b/src/lib/canvas/evas_render.c index 8eaebf5..f3f07ee 100644 --- a/src/lib/canvas/evas_render.c +++ b/src/lib/canvas/evas_render.c @@ -746,6 +746,10 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, pt->fz = p->z; pt->u = p->u * FP1; pt->v = p->v * FP1; + if (pt->u < 0) pt->u = 0; + else if (pt->u > (sw * FP1)) pt->u = (sw * FP1); + if (pt->v < 0) pt->v = 0; + else if (pt->v > (sh * FP1)) pt->v = (sh * FP1); pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b); } /* Copy last for software engine */ @@ -887,7 +891,7 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, } RDI(level); - RD(" draw map4\n"); + RD(" draw map\n"); if (rendered) { diff --git a/src/lib/engines/common/Makefile.am b/src/lib/engines/common/Makefile.am index 00fbb06..c3290b9 100644 --- a/src/lib/engines/common/Makefile.am +++ b/src/lib/engines/common/Makefile.am @@ -13,7 +13,7 @@ AM_CPPFLAGS = -I. \ @FREETYPE_CFLAGS@ @VALGRIND_CFLAGS@ \ @EET_CFLAGS@ @pthread_cflags@ \ @WIN32_CFLAGS@ @EINA_CFLAGS@ \ - @FRIBIDI_CFLAGS@ + @FRIBIDI_CFLAGS@ @HARFBUZZ_CFLAGS@ noinst_LTLIBRARIES = libevas_engine_common.la libevas_engine_common_la_SOURCES = \ @@ -39,7 +39,6 @@ evas_convert_grypal_6.c \ evas_convert_yuv.c \ evas_cpu.c \ evas_draw_main.c \ -evas_encoding.c \ evas_font_draw.c \ evas_font_load.c \ evas_font_main.c \ @@ -59,7 +58,10 @@ evas_scale_span.c \ evas_tiler.c \ evas_regionbuf.c \ evas_pipe.c \ -evas_bidi_utils.c \ +language/evas_bidi_utils.c \ +language/evas_language_utils.c \ +evas_text_utils.c \ +evas_font_ot.c \ evas_map_image.c \ evas_map_image.h @@ -79,7 +81,6 @@ evas_convert_rgb_32.h \ evas_convert_rgb_8.h \ evas_convert_yuv.h \ evas_draw.h \ -evas_encoding.h \ evas_font.h \ evas_font_private.h \ evas_image.h \ @@ -98,7 +99,10 @@ evas_scale_smooth_scaler_noscale.c \ evas_scale_smooth_scaler_up.c \ evas_scale_span.h \ evas_pipe.h \ -evas_bidi_utils.h \ +language/evas_bidi_utils.h \ +language/evas_language_utils.h \ +evas_text_utils.h \ +evas_font_ot.h \ evas_map_image_internal.c \ evas_map_image_core.c \ evas_map_image_loop.c diff --git a/src/lib/engines/common/evas_encoding.c b/src/lib/engines/common/evas_encoding.c deleted file mode 100644 index 96a2690..0000000 --- a/src/lib/engines/common/evas_encoding.c +++ /dev/null @@ -1,317 +0,0 @@ -#include "evas_common.h" -#include "evas_encoding.h" - -EAPI Eina_Unicode -evas_common_encoding_utf8_get_next(const char *buf, int *iindex) -{ - /* Reads UTF8 bytes from @buf, starting at *@index and returns - * the decoded code point at iindex offset, and advances iindex - * to the next code point after this. - * - * Returns 0 to indicate there is no next char - */ -#if 1 - int index = *iindex; - Eina_Unicode r; - unsigned char d; - - /* if this char is the null terminator, exit */ - if ((d = buf[index++]) == 0) return 0; - - if ((d & 0x80) == 0) - { // 1 byte (7bit) - 0xxxxxxx - *iindex = index; - return d; - } - if ((d & 0xe0) == 0xc0) - { // 2 byte (11bit) - 110xxxxx 10xxxxxx - r = (d & 0x1f) << 6; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f); - if (!r) return 0; - *iindex = index; - return r; - } - if ((d & 0xf0) == 0xe0) - { // 3 byte (16bit) - 1110xxxx 10xxxxxx 10xxxxxx - r = (d & 0x0f) << 12; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 6; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f); - if (!r) return 0; - *iindex = index; - return r; - } - if ((d & 0xf8) == 0xf0) - { // 4 byte (21bit) - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - r = (d & 0x07) << 18; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 12; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 6; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f); - if (!r) return 0; - *iindex = index; - return r; - } - if ((d & 0xfc) == 0xf8) - { // 5 byte (26bit) - 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - r = (d & 0x03) << 24; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 18; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 12; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 6; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f); - if (!r) return 0; - *iindex = index; - return r; - } - if ((d & 0xfe) == 0xfc) - { // 6 byte (31bit) - 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - r = (d & 0x01) << 30; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 24; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 18; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 12; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f) << 6; - if ((d = buf[index++]) == 0) return 0; - r |= (d & 0x3f); - if (!r) return 0; - *iindex = index; - return r; - } - return 0; -#else - int index = *iindex, r, len; - unsigned char d, d2, d3, d4; - - /* if this char is the null terminator, exit */ - if (!buf[index]) return 0; - - d = buf[index++]; - - while (buf[index] && ((buf[index] & 0xc0) == 0x80)) - index++; - len = index - *iindex; - - if (len == 1) - r = d; - else if (len == 2) - { - /* 2 bytes */ - d2 = buf[*iindex + 1]; - if (d2 == 0) - { - *iindex = *iindex + 1; - return 0; - } - r = d & 0x1f; /* copy lower 5 */ - r <<= 6; - r |= (d2 & 0x3f); /* copy lower 6 */ - } - else if (len == 3) - { - /* 3 bytes */ - d2 = buf[*iindex + 1]; - if (d2 == 0) - { - *iindex = *iindex + 1; - return 0; - } - d3 = buf[*iindex + 2]; - if (d3 == 0) - { - *iindex = *iindex + 2; - return 0; - } - r = d & 0x0f; /* copy lower 4 */ - r <<= 6; - r |= (d2 & 0x3f); - r <<= 6; - r |= (d3 & 0x3f); - } - else - { - /* 4 bytes */ - d2 = buf[*iindex + 1]; - if (d2 == 0) - { - *iindex = *iindex + 1; - return 0; - } - d3 = buf[*iindex + 2]; - if (d3 == 0) - { - *iindex = *iindex + 2; - return 0; - } - d4 = buf[*iindex + 3]; - if (d4 == 0) - { - *iindex = *iindex + 3; - return 0; - } - r = d & 0x0f; /* copy lower 4 */ - r <<= 6; - r |= (d2 & 0x3f); - r <<= 6; - r |= (d3 & 0x3f); - r <<= 6; - r |= (d4 & 0x3f); - } - *iindex = index; - return r; -#endif -} - -EAPI Eina_Unicode -evas_common_encoding_utf8_get_prev(const char *buf, int *iindex) -{ - /* Reads UTF8 bytes from @buf, starting at *@index and returns - * the decoded code point at iindex offset, and advances iindex - * to the prev code point after this. - * - * Returns 0 to indicate there is no prev char - */ - - int r; - int index = *iindex; - /* although when index == 0 there's no previous char, we still want to get - * the current char */ - if (index < 0) - return 0; - - /* First obtain the codepoint at iindex */ - r = evas_common_encoding_utf8_get_next(buf, &index); - - /* Next advance iindex to previous codepoint */ - index = *iindex; - index--; - while ((index > 0) && ((buf[index] & 0xc0) == 0x80)) - index--; - - *iindex = index; - return r; -} - -EAPI Eina_Unicode -evas_common_encoding_utf8_get_last(const char *buf, int buflen) -{ - /* jumps to the nul byte at the buffer end and decodes backwards and - * returns the offset index byte in the buffer where the last character - * in the buffer begins. - * - * Returns -1 to indicate an error - */ - int index; - unsigned char d; - - if (buflen < 1) return 0; - index = buflen - 1; - d = buf[index]; - if (!(d & 0x80)) - return index; - else - { - while (index > 0) - { - index--; - d = buf[index]; - if ((d & 0xc0) != 0x80) - return index; - } - } - return 0; -} - -EAPI int -evas_common_encoding_utf8_get_len(const char *buf) -{ - /* returns the number of utf8 characters (not bytes) in the string */ - int i = 0, len = 0; - - while (evas_common_encoding_utf8_get_next(buf, &i)) - len++; - - return len; -} - -/* FIXME: Should optimize! */ -EAPI Eina_Unicode * -evas_common_encoding_utf8_to_unicode(const char *utf, int *_len) -{ - int len, i; - int index; - Eina_Unicode *buf, *ind; - - len = evas_common_encoding_utf8_get_len(utf); - if (_len) - *_len = len; - buf = (Eina_Unicode *) calloc(sizeof(Eina_Unicode), (len + 1)); - if (!buf) return buf; - - for (i = 0, index = 0, ind = buf ; i < len ; i++, ind++) - { - *ind = evas_common_encoding_utf8_get_next(utf, &index); - } - - return buf; -} - -EAPI char * -evas_common_encoding_unicode_to_utf8(const Eina_Unicode *uni, int *_len) -{ - char *buf; - const Eina_Unicode *uind; - char *ind; - int ulen, len; - - ulen = eina_unicode_strlen(uni); - buf = (char *) calloc(ulen + 1, EVAS_ENCODING_UTF8_BYTES_PER_CHAR); - - len = 0; - for (uind = uni, ind = buf ; *uind ; uind++) - { - if (*uind <= 0x7F) /* 1 byte char */ - { - *ind++ = *uind; - len += 1; - } - else if (*uind <= 0x7FF) /* 2 byte char */ - { - *ind++ = 0xC0 | (unsigned char) (*uind >> 6); - *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); - len += 2; - } - else if (*uind <= 0xFFFF) /* 3 byte char */ - { - *ind++ = 0xE0 | (unsigned char) (*uind >> 12); - *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F); - *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); - len += 3; - } - else /* 4 byte char */ - { - *ind++ = 0xF0 | (unsigned char) ((*uind >> 18) & 0x07); - *ind++ = 0x80 | (unsigned char) ((*uind >> 12) & 0x3F); - *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F); - *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); - len += 4; - } - } - buf = realloc(buf, len + 1); - buf[len] = '\0'; - if (_len) - *_len = len; - return buf; -} - - diff --git a/src/lib/engines/common/evas_encoding.h b/src/lib/engines/common/evas_encoding.h deleted file mode 100644 index e278727..0000000 --- a/src/lib/engines/common/evas_encoding.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef EVAS_ENCODING_H -#define EVAS_ENCODING_H -#include - -/* FIXME: An assumption that will probably break in the future */ -#define EVAS_ENCODING_UTF8_BYTES_PER_CHAR 4 - -EAPI Eina_Unicode -evas_common_encoding_utf8_get_next(const char *buf, int *iindex); - -EAPI Eina_Unicode -evas_common_encoding_utf8_get_prev(const char *buf, int *iindex); - -EAPI Eina_Unicode -evas_common_encoding_utf8_get_last(const char *buf, int buflen); - -EAPI int -evas_common_encoding_utf8_get_len(const char *buf); - -EAPI Eina_Unicode * -evas_common_encoding_utf8_to_unicode(const char *utf, int *_len) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC; - -EAPI char * -evas_common_encoding_unicode_to_utf8(const Eina_Unicode *uni, int *_len) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC; - -#endif diff --git a/src/lib/engines/common/evas_font.h b/src/lib/engines/common/evas_font.h index ddacb8e..3db4366 100644 --- a/src/lib/engines/common/evas_font.h +++ b/src/lib/engines/common/evas_font.h @@ -1,6 +1,6 @@ #ifndef _EVAS_FONT_H #define _EVAS_FONT_H -#include "evas_bidi_utils.h" +#include "evas_text_utils.h" /* main */ @@ -17,7 +17,7 @@ EAPI int evas_common_font_get_line_advance (RGBA_Font *fn); /* draw */ -EAPI void evas_common_font_draw (RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props); +EAPI void evas_common_font_draw (RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_Text_Props *intl_props); EAPI int evas_common_font_glyph_search (RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl); EAPI RGBA_Font_Glyph *evas_common_font_int_cache_glyph_get (RGBA_Font_Int *fi, FT_UInt index); EAPI void evas_common_font_draw_init (void); @@ -56,12 +56,13 @@ EAPI void evas_common_font_all_clear (void); /* query */ EAPI int evas_common_font_query_kerning (RGBA_Font_Int* fi, FT_UInt left, FT_UInt right, int* kerning); -EAPI void evas_common_font_query_size (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h); -EAPI int evas_common_font_query_inset (RGBA_Font *fn, const Eina_Unicode *text); -EAPI void evas_common_font_query_advance (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *h_adv, int *v_adv); -EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch); -EAPI int evas_common_font_query_char_at_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch); -EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y); +EAPI void evas_common_font_query_size (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int *w, int *h); +EAPI int evas_common_font_query_inset (RGBA_Font *fn __UNUSED__, const Evas_Text_Props *text_props); +EAPI void evas_common_font_query_advance (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int *h_adv, int *v_adv); +EAPI int evas_common_font_query_char_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch); +EAPI int evas_common_font_query_pen_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch); +EAPI int evas_common_font_query_char_at_coords (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch); +EAPI int evas_common_font_query_last_up_to_pos (RGBA_Font *fn, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int x, int y); #ifdef EVAS_FRAME_QUEUING EAPI void evas_common_font_draw_finish(void); diff --git a/src/lib/engines/common/evas_font_default_walk.x b/src/lib/engines/common/evas_font_default_walk.x new file mode 100644 index 0000000..704db21 --- /dev/null +++ b/src/lib/engines/common/evas_font_default_walk.x @@ -0,0 +1,196 @@ +#ifndef _EVAS_FONT_DEFAULT_WALK_X +#define _EVAS_FONT_DEFAULT_WALK_X +/* Macros for text walking */ + +/** + * @def EVAS_FONT_WALK_TEXT_INIT + * @internal + * This macro defines the variables that will later be used with the following + * macros, and by font handling functions. + * @see EVAS_FONT_WALK_TEXT_START + * @see EVAS_FONT_WALK_TEXT_WORK + * @see EVAS_FONT_WALK_TEXT_END + */ +# define EVAS_FONT_WALK_TEXT_INIT() \ + int _pen_x = 0, _pen_y = 0; \ + size_t char_index; \ + (void) _pen_y; /* Sometimes it won't be used */ + +/* Visual walk helper macros */ +#ifdef OT_SUPPORT +#define _EVAS_FONT_WALK_TEXT_VISUAL_START() \ + Evas_Font_OT_Info *_ot_itr = (text_props->info) ? \ + text_props->info->ot + text_props->start : NULL; \ + for (char_index = 0 ; char_index < text_props->len ; char_index++, _glyph_itr++, _ot_itr++) \ + { +#else +#define _EVAS_FONT_WALK_TEXT_VISUAL_START() \ + for (char_index = 0 ; char_index < text_props->len ; char_index++, _glyph_itr++) \ + { +#endif + +/** + * @def EVAS_FONT_WALK_TEXT_VISUAL_START + * @internal + * This runs through the text in visual order while updating char_index, + * which is the current index in the text. + * Does not end with a ; + * Take a look at EVAS_FONT_WALK_X_OFF and the like. + * @see EVAS_FONT_WALK_TEXT_INIT + * @see EVAS_FONT_WALK_TEXT_WORK + * @see EVAS_FONT_WALK_TEXT_END + * @see EVAS_FONT_WALK_TEXT_LOGICAL_START + */ +#define EVAS_FONT_WALK_TEXT_VISUAL_START() \ + do \ + { \ + Evas_Font_Glyph_Info *_glyph_itr = (text_props->info) ? \ + text_props->info->glyph + text_props->start : NULL; \ + _EVAS_FONT_WALK_TEXT_VISUAL_START() + +/* Logical walk helper macros */ +#ifdef OT_SUPPORT +#define _EVAS_FONT_WALK_TEXT_LOGICAL_START() \ + Evas_Font_OT_Info *_ot_itr = (text_props->info) ? \ + text_props->info->ot + text_props->start : NULL; \ + if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) \ + _ot_itr += text_props->len - 1; \ + for ( ; _i > 0 ; char_index += _char_index_d, _i--, _glyph_itr += _char_index_d, _ot_itr += _char_index_d) \ + { +#else +#define _EVAS_FONT_WALK_TEXT_LOGICAL_START() \ + for ( ; _i > 0 ; char_index += _char_index_d, _i--, _glyph_itr += _char_index_d) \ + { +#endif + +/** + * @def EVAS_FONT_WALK_TEXT_LOGICAL_START + * @internal + * This runs through the text in logical order while updating char_index, + * which is the current index in the text. + * Does not end with a ; + * Take a look at EVAS_FONT_WALK_X_OFF and the like. + * @see EVAS_FONT_WALK_TEXT_INIT + * @see EVAS_FONT_WALK_TEXT_WORK + * @see EVAS_FONT_WALK_TEXT_END + * @see EVAS_FONT_WALK_TEXT_VISUAL_START + */ +#ifdef BIDI_SUPPORT +#define EVAS_FONT_WALK_TEXT_LOGICAL_START() \ + do \ + { \ + Evas_Font_Glyph_Info *_glyph_itr = (text_props->info) ? \ + text_props->info->glyph + text_props->start : \ + NULL; \ + int _char_index_d; \ + size_t _i; \ + _i = text_props->len; \ + if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) \ + { \ + char_index = text_props->len - 1; \ + _char_index_d = -1; \ + _glyph_itr += text_props->len - 1; \ + } \ + else \ + { \ + char_index = 0; \ + _char_index_d = 1; \ + } \ + _EVAS_FONT_WALK_TEXT_LOGICAL_START() + +#else +#define EVAS_FONT_WALK_TEXT_LOGICAL_START() EVAS_FONT_WALK_TEXT_VISUAL_START() +#endif + +#define EVAS_FONT_WALK_ORIG_LEN (_len) + +/*FIXME: doc */ +#ifdef OT_SUPPORT +# define EVAS_FONT_WALK_X_OFF \ + (EVAS_FONT_ROUND_26_6_TO_INT(EVAS_FONT_OT_X_OFF_GET(*_ot_itr))) +# define EVAS_FONT_WALK_Y_OFF \ + (EVAS_FONT_ROUND_26_6_TO_INT(EVAS_FONT_OT_Y_OFF_GET(*_ot_itr))) +# define EVAS_FONT_WALK_POS \ + (EVAS_FONT_OT_POS_GET(*_ot_itr) - text_props->text_offset) +# define EVAS_FONT_WALK_POS_NEXT \ + ((!EVAS_FONT_WALK_IS_LAST) ? \ + EVAS_FONT_OT_POS_GET(*(_ot_itr + 1)) - \ + text_props->text_offset : \ + EVAS_FONT_WALK_POS \ + ) +# define EVAS_FONT_WALK_POS_PREV \ + ((char_index > 0) ? \ + EVAS_FONT_OT_POS_GET(*(_ot_itr - 1)) - \ + text_props->text_offset : \ + EVAS_FONT_WALK_POS \ + ) +#else +# define EVAS_FONT_WALK_X_OFF 0 +# define EVAS_FONT_WALK_Y_OFF 0 +# define EVAS_FONT_WALK_POS \ + ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) ? \ + (text_props->len - char_index - 1) : \ + (char_index)) +# define EVAS_FONT_WALK_POS_NEXT \ + ((!EVAS_FONT_WALK_IS_LAST) ? \ + ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) ? \ + text_props->len - char_index - 2 \ + : (char_index + 1)) : \ + EVAS_FONT_WALK_POS) +# define EVAS_FONT_WALK_POS_PREV \ + ((char_index > 0) ? \ + ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) ? \ + text_props->len - char_index \ + : (char_index - 1)) : \ + EVAS_FONT_WALK_POS) +#endif + + +#define EVAS_FONT_WALK_IS_VISIBLE (_glyph_itr->index != 0) +#define EVAS_FONT_WALK_X_BEAR (_glyph_itr->x_bear) +#define EVAS_FONT_WALK_Y_BEAR (fg->glyph_out->top) +#define _EVAS_FONT_WALK_X_ADV (_glyph_itr->advance) +#define EVAS_FONT_WALK_WIDTH (_glyph_itr->width) + +#define EVAS_FONT_WALK_INDEX (_glyph_itr->index) +#define EVAS_FONT_WALK_X_ADV \ + (EVAS_FONT_ROUND_26_6_TO_INT(_EVAS_FONT_WALK_X_ADV)) +#define EVAS_FONT_WALK_PEN_X (EVAS_FONT_ROUND_26_6_TO_INT(_pen_x)) +#define EVAS_FONT_WALK_PEN_Y (EVAS_FONT_ROUND_26_6_TO_INT(_pen_y)) +#define EVAS_FONT_WALK_Y_ADV (0) +#define EVAS_FONT_WALK_IS_LAST \ + (char_index + 1 == text_props->len) +#define EVAS_FONT_WALK_IS_FIRST \ + (char_index == 0) +#define EVAS_FONT_WALK_LEN (text_props->len) + +/** + * @def EVAS_FONT_WALK_TEXT_WORK + * @internal + * This macro actually updates the values mentioned in EVAS_FONT_WALK_TEXT_VISUAL_START + * according to the current positing in the walk. + * @see EVAS_FONT_WALK_TEXT_VISUAL_START + * @see EVAS_FONT_WALK_TEXT_INIT + * @see EVAS_FONT_WALK_TEXT_END + */ +#define EVAS_FONT_WALK_TEXT_WORK() do {} while(0) + +/** + * @def EVAS_FONT_WALK_TEXT_END + * @internal + * Closes EVAS_FONT_WALK_TEXT_VISUAL_START, needs to end with a ; + * @see EVAS_FONT_WALK_TEXT_VISUAL_START + * @see EVAS_FONT_WALK_TEXT_INIT + * @see EVAS_FONT_WALK_TEXT_WORK + */ +#define EVAS_FONT_WALK_TEXT_END() \ + if (EVAS_FONT_WALK_IS_VISIBLE) \ + { \ + _pen_x += _EVAS_FONT_WALK_X_ADV; \ + } \ + } \ + } \ + while(0) + + +#endif diff --git a/src/lib/engines/common/evas_font_draw.c b/src/lib/engines/common/evas_font_draw.c index 6067f92..195fe16 100644 --- a/src/lib/engines/common/evas_font_draw.c +++ b/src/lib/engines/common/evas_font_draw.c @@ -2,10 +2,12 @@ #include "evas_private.h" #include "evas_blend_private.h" -#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */ +#include "language/evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */ #include "evas_font_private.h" /* for Frame-Queuing support */ -#define WORD_CACHE_MAXLEN 50 +#include "evas_font_ot.h" + +#define WORD_CACHE_MAXLEN 50 /* How many to cache */ #define WORD_CACHE_NWORDS 40 static int max_cached_words = WORD_CACHE_NWORDS; @@ -28,7 +30,6 @@ struct prword struct cinfo { - int gl; FT_UInt index; struct { @@ -48,7 +49,7 @@ struct cinfo #if defined(METRIC_CACHE) || defined(WORD_CACHE) LK(lock_words); // for word cache call static Eina_Inlist *words = NULL; -static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *text, Evas_BiDi_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning); +static struct prword *evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *text, const Evas_Text_Props *text_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning); #endif EAPI void @@ -388,25 +389,21 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl) } /* - * BiDi handling: We receive the shaped string + other props from intl_props, + * BiDi handling: We receive the shaped string + other props from text_props, * we need to reorder it so we'll have the visual string (the way we draw) * and then for kerning we have to switch the order of the kerning query (as the prev * is on the right, and not on the left). */ static void evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *in_text, - const Evas_BiDi_Props *intl_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w, + const Evas_Text_Props *text_props, RGBA_Gfx_Func func, int ext_x, int ext_y, int ext_w, int ext_h, RGBA_Font_Int *fi, int im_w, int im_h __UNUSED__, int use_kerning ) { - int pen_x, pen_y; - int last_adv; const Eina_Unicode *text = in_text; - FT_Face pface = NULL; - FT_UInt prev_index; DATA32 *im; - int c; - int char_index = 0; /* the index of the current char */ + FT_Face pface = NULL; + EVAS_FONT_WALK_TEXT_INIT(); #if defined(METRIC_CACHE) || defined(WORD_CACHE) unsigned int len; @@ -414,12 +411,12 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font /* A fast strNlen would be nice (there is a wcsnlen strangely) */ len = eina_unicode_strnlen(text,WORD_CACHE_MAXLEN); - if (len > 2 && len < WORD_CACHE_MAXLEN) + if (len > 2 && (len < WORD_CACHE_MAXLEN)) { struct prword *word; - word = - evas_font_word_prerender(dc, text, (Evas_BiDi_Props *)intl_props, + word = + evas_font_word_prerender(dc, text, text_props, len, fn, fi, use_kerning); if (word) { @@ -496,64 +493,57 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font # endif } } +#else + (void) use_kerning; #endif -#ifdef BIDI_SUPPORT - Eina_Unicode *visual_text; + if (fi->src->current_size != fi->size) + { + FTLOCK(); + FT_Activate_Size(fi->ft.size); + FTUNLOCK(); + fi->src->current_size = fi->size; + } - visual_text = eina_unicode_strdup(in_text); - if (visual_text) + im = dst->image.data; + /* Load the glyph according to the first letter of the script, preety + * bad, but will have to do */ { - evas_bidi_props_reorder_line(visual_text, intl_props, NULL); - text = visual_text; + /* Skip common chars */ + const Eina_Unicode *tmp; + for (tmp = text ; + *tmp && + evas_common_language_char_script_get(*tmp) == + EVAS_SCRIPT_COMMON ; + tmp++) + ; + if (!*tmp && (tmp > text)) tmp--; + evas_common_font_glyph_search(fn, &fi, *tmp); } - else + EVAS_FONT_WALK_TEXT_VISUAL_START() { - text = in_text; - } + FT_UInt index; + RGBA_Font_Glyph *fg; + int chr_x, chr_y, chr_w; + if (!EVAS_FONT_WALK_IS_VISIBLE) continue; + +#ifdef OT_SUPPORT + index = EVAS_FONT_WALK_INDEX; #else - intl_props = NULL; + /* FIXME: Should be removed once we split according to script without + * the use of harfbuzz */ + index = + evas_common_font_glyph_search(fn, &fi, text[EVAS_FONT_WALK_POS]); #endif - - pen_x = x; - pen_y = y; - last_adv = 0; - prev_index = 0; - im = dst->image.data; - for (char_index = 0, c = 0; *text; text++, char_index++) - { - FT_UInt index; - RGBA_Font_Glyph *fg; - int chr_x, chr_y; - int gl, kern; - - gl = *text; - - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - fg = evas_common_font_int_cache_glyph_get(fi, index); - if (!fg) + LKL(fi->ft_mutex); + fg = evas_common_font_int_cache_glyph_get(fi, index); + if (!fg) { LKU(fi->ft_mutex); continue; } - /* hmmm kerning means i can't sanely do my own cached metric tables! */ - /* grrr - this means font face sharing is kinda... not an option if */ - /* you want performance */ - if ((use_kerning) && (prev_index) && (index) && - (pface == fi->src->ft.face)) - { - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - } + pface = fi->src->ft.face; LKU(fi->ft_mutex); @@ -563,15 +553,10 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg); fg->ext_dat_free = dc->font_ext.func.gl_free; } - /* If the current one is not a compositing char, do the previous advance - * and set the current advance as the next advance to do */ - if (fg->glyph->advance.x >> 16 > 0) - { - pen_x += last_adv; - last_adv = fg->glyph->advance.x >> 16; - } - chr_x = (pen_x + (fg->glyph_out->left)); - chr_y = (pen_y + (fg->glyph_out->top)); + + chr_x = x + EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + EVAS_FONT_WALK_X_BEAR; + chr_y = y + EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR; + chr_w = EVAS_FONT_WALK_WIDTH; if (chr_x < (ext_x + ext_w)) { @@ -584,10 +569,10 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font if (j < w) j = w; h = fg->glyph_out->bitmap.rows; /* - if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays) - && (fg->glyph_out->bitmap.num_grays == 256) - ) - */ + if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays) + && (fg->glyph_out->bitmap.num_grays == 256) + ) + */ { if ((j > 0) && (chr_x + w > ext_x)) { @@ -595,14 +580,14 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font { /* ext glyph draw */ dc->font_ext.func.gl_draw(dc->font_ext.data, - (void *)dst, - dc, fg, chr_x, - y - (chr_y - y)); + (void *)dst, + dc, fg, chr_x, + y - (chr_y - y)); } else { if ((fg->glyph_out->bitmap.num_grays == 256) && - (fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)) + (fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)) { for (i = 0; i < h; i++) { @@ -618,8 +603,8 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font #endif { if ((dx < (ext_x + ext_w)) && - (dy >= (ext_y)) && - (dy < (ext_y + ext_h))) + (dy >= (ext_y)) && + (dy < (ext_y + ext_h))) { if (dx + w > (ext_x + ext_w)) in_w += (dx + w) - (ext_x + ext_w); @@ -632,7 +617,7 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font if (in_w < w) { func(NULL, data + (i * j) + in_x, dc->col.col, - im + (dy * im_w) + dx, w - in_w); + im + (dy * im_w) + dx, w - in_w); } } } @@ -673,8 +658,8 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font dp++; } if ((dx < (ext_x + ext_w)) && - (dy >= (ext_y)) && - (dy < (ext_y + ext_h))) + (dy >= (ext_y)) && + (dy < (ext_y + ext_h))) { if (dx + w > (ext_x + ext_w)) in_w += (dx + w) - (ext_x + ext_w); @@ -687,31 +672,26 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font if (in_w < w) { func(NULL, tmpbuf + in_x, dc->col.col, - im + (dy * im_w) + dx, w - in_w); + im + (dy * im_w) + dx, w - in_w); } } } } } } - c++; } } } else break; - - prev_index = index; } -#ifdef BIDI_SUPPORT - if (visual_text) free(visual_text); -#endif + EVAS_FONT_WALK_TEXT_END(); evas_common_font_int_use_trim(); } EAPI void evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, - const Evas_BiDi_Props *intl_props) + const Evas_Text_Props *text_props) { int ext_x, ext_y, ext_w, ext_h; int im_w, im_h; @@ -763,7 +743,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int if (!dc->cutout.rects) { - evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props, + evas_common_font_draw_internal(dst, dc, fn, x, y, text, text_props, func, ext_x, ext_y, ext_w, ext_h, fi, im_w, im_h, use_kerning); } @@ -779,7 +759,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int { r = rects->rects + i; evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h); - evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props, + evas_common_font_draw_internal(dst, dc, fn, x, y, text, text_props, func, r->x, r->y, r->w, r->h, fi, im_w, im_h, use_kerning); } @@ -796,22 +776,19 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int /* Only used if cache is on */ #if defined(METRIC_CACHE) || defined(WORD_CACHE) struct prword * -evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Evas_BiDi_Props *intl_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning) +evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, const Evas_Text_Props *text_props, int len, RGBA_Font *fn, RGBA_Font_Int *fi,int use_kerning __UNUSED__) { - int pen_x, pen_y; struct cinfo *metrics; const Eina_Unicode *text = in_text; - int chr; - FT_Face pface = NULL; - FT_UInt prev_index; unsigned char *im; int width; int height, above, below, baseline, descent; - int c; int i,j; - int char_index = 0; /* the index of the current char */ struct prword *w; + int last_delta = 0; int gl; + struct cinfo *ci; + EVAS_FONT_WALK_TEXT_INIT(); # ifndef METRIC_CACHE gl = dc->font_ext.func.gl_new ? 1: 0; @@ -832,61 +809,54 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Eva gl = dc->font_ext.func.gl_new ? 1: 0; - pen_x = pen_y = 0; above = 0; below = 0; baseline = 0; height = 0; descent = 0; - metrics = malloc(sizeof(struct cinfo) * len); + /* Load the glyph according to the first letter of the script, preety + * bad, but will have to do */ + { + /* Skip common chars */ + const Eina_Unicode *tmp; + for (tmp = text ; + *tmp && + evas_common_language_char_script_get(*tmp) == + EVAS_SCRIPT_COMMON ; + tmp++) + ; + if (!*tmp && (tmp > text)) tmp--; + evas_common_font_glyph_search(fn, &fi, *tmp); + } - /* First pass: Work out how big */ - for (char_index = 0, c = 0, chr = 0 ; *text ; text++, char_index ++) + /* First pass: Work out how big and populate */ + /* It's a bit hackish to use index and fg here as they are internal, + * but that'll have to be good enough ATM */ + len = text_props->len; + metrics = malloc(sizeof(struct cinfo) * len); + ci = metrics; + EVAS_FONT_WALK_TEXT_VISUAL_START() { - struct cinfo *ci = metrics + char_index; - ci->gl = *text; - ci->index = evas_common_font_glyph_search(fn, &fi, ci->gl); - LKL(fi->ft_mutex); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - ci->fg = evas_common_font_int_cache_glyph_get(fi, ci->index); - if (!ci->fg) - { - LKU(fi->ft_mutex); - continue; - } - - if ((use_kerning) && (prev_index) && (ci->index) && - (pface == fi->src->ft.face)) + FT_UInt index; + RGBA_Font_Glyph *fg; +#ifdef OT_SUPPORT + index = EVAS_FONT_WALK_INDEX; +#else + /* FIXME: Should be removed once we split according to script without + * the use of harfbuzz */ + index = + evas_common_font_glyph_search(fn, &fi, text[EVAS_FONT_WALK_POS]); +#endif + LKL(fi->ft_mutex); + fg = evas_common_font_int_cache_glyph_get(fi, index); + if (!fg) { - int kern = 0; -# ifdef BIDI_SUPPORT - /* if it's rtl, the kerning matching should be reversed, i.e prev - * index is now the index and the other way around. - * There is a slight exception when there are compositing chars - * involved.*/ - if (intl_props && intl_props->props && - evas_bidi_is_rtl_char(intl_props, char_index) && - ci->fg->glyph->advance.x >> 16 > 0) - { - if (evas_common_font_query_kerning(fi, ci->index, prev_index, &kern)) - pen_x += kern; - } - else - { - if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern)) - pen_x += kern; - } -# else - if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern)) - pen_x += kern; -# endif + LKU(fi->ft_mutex); + continue; } - pface = fi->src->ft.face; - LKU(fi->ft_mutex); + EVAS_FONT_WALK_TEXT_WORK(); + /* Currently broken with invisible chars if (!EVAS_FONT_WALK_IS_VISIBLE) continue; */ + ci->index = index; + ci->fg = fg; + if (gl) { ci->fg->ext_dat =dc->font_ext.func.gl_new(dc->font_ext.data,ci->fg); @@ -901,26 +871,41 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Eva below = ci->bm.rows - ci->bm.h; if (below > descent) descent = below; if (above > baseline) baseline = above; - ci->pos.x = pen_x + ci->fg->glyph_out->left; - ci->pos.y = pen_y + ci->fg->glyph_out->top; - pen_x += ci->fg->glyph->advance.x >> 16; - prev_index = ci->index; + ci->pos.x = EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + EVAS_FONT_WALK_X_BEAR; + ci->pos.y = EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR; + last_delta = EVAS_FONT_WALK_X_ADV - + (ci->bm.w + ci->fg->glyph_out->left); + ci++; } + EVAS_FONT_WALK_TEXT_END(); /* First loop done */ - width = pen_x; + width = EVAS_FONT_WALK_PEN_X; + if (last_delta < 0) + width -= last_delta; width = (width & 0x7) ? width + (8 - (width & 0x7)) : width; height = baseline + descent; if (!gl) { im = calloc(height, width); - for (i = 0 ; i < char_index ; i ++) + for (i = 0 ; i < len ; i ++) { struct cinfo *ci = metrics + i; for (j = 0 ; j < ci->bm.rows ; j ++) - memcpy(im + ci->pos.x + (j + baseline - ci->bm.h) * width, ci->bm.data + j * ci->bm.w, ci->bm.w); + { + int correction; /* Used to remove negative inset and such */ + if (ci->pos.x < 0) + correction = -ci->pos.x; + else + correction = 0; + + memcpy(im + ci->pos.x + (j + baseline - ci->bm.h) * width + + correction, + ci->bm.data + j * ci->bm.w + correction, + ci->bm.w - correction); + } } } else @@ -938,7 +923,9 @@ evas_font_word_prerender(RGBA_Draw_Context *dc, const Eina_Unicode *in_text, Eva save->size = fi->size; save->len = len; save->im = im; - save->width = pen_x; + save->width = EVAS_FONT_WALK_PEN_X; + if (last_delta < 0) + save->width += last_delta; save->roww = width; save->height = height; save->baseline = baseline; diff --git a/src/lib/engines/common/evas_font_load.c b/src/lib/engines/common/evas_font_load.c index daa4f96..9048d53 100644 --- a/src/lib/engines/common/evas_font_load.c +++ b/src/lib/engines/common/evas_font_load.c @@ -4,6 +4,7 @@ #include #include "evas_font_private.h" /* for Frame-Queuing support */ +#include "evas_font_ot.h" extern FT_Library evas_ft_lib; @@ -44,7 +45,11 @@ _evas_common_font_source_free(RGBA_Font_Source *fs) FTLOCK(); FT_Done_Face(fs->ft.face); FTUNLOCK(); +#ifdef OT_SUPPORT + evas_common_font_ot_unload_face(fs); +#endif if (fs->name) eina_stringshare_del(fs->name); + if (fs->file) eina_stringshare_del(fs->file); free(fs); } @@ -131,6 +136,9 @@ evas_common_font_source_memory_load(const char *name, const void *data, int data free(fs); return NULL; } +#ifdef OT_SUPPORT + evas_common_font_ot_load_face(fs); +#endif FTUNLOCK(); fs->ft.orig_upem = fs->ft.face->units_per_EM; fs->references = 1; @@ -151,7 +159,7 @@ evas_common_font_source_load(const char *name) fs->current_size = 0; fs->ft.face = NULL; fs->name = eina_stringshare_add(name); - fs->file = fs->name; + fs->file = eina_stringshare_ref(fs->name); fs->ft.orig_upem = 0; fs->references = 1; eina_hash_direct_add(fonts_src, fs->name, fs); @@ -164,6 +172,9 @@ evas_common_font_source_unload(RGBA_Font_Source *fs) FTLOCK(); FT_Done_Face(fs->ft.face); fs->ft.face = NULL; +#ifdef OT_SUPPORT + evas_common_font_ot_unload_face(fs); +#endif FTUNLOCK(); } @@ -213,6 +224,9 @@ evas_common_font_source_load_complete(RGBA_Font_Source *fs) fs->ft.face = NULL; return error; } +#ifdef OT_SUPPORT + evas_common_font_ot_load_face(fs); +#endif FTUNLOCK(); fs->ft.orig_upem = fs->ft.face->units_per_EM; return error; diff --git a/src/lib/engines/common/evas_font_main.c b/src/lib/engines/common/evas_font_main.c index 8a11a10..821ab6e 100644 --- a/src/lib/engines/common/evas_font_main.c +++ b/src/lib/engines/common/evas_font_main.c @@ -1,6 +1,5 @@ #include "evas_common.h" #include "evas_private.h" -#include "evas_encoding.h" #include "evas_font_private.h" @@ -9,6 +8,7 @@ static int initialised = 0; LK(lock_font_draw); // for freetype2 API calls LK(lock_bidi); // for evas bidi internal usage. +LK(lock_ot); // for evas bidi internal usage. EAPI void evas_common_font_init(void) @@ -23,6 +23,7 @@ evas_common_font_init(void) evas_common_font_draw_init(); LKI(lock_font_draw); LKI(lock_bidi); + LKI(lock_ot); } EAPI void @@ -36,6 +37,7 @@ evas_common_font_shutdown(void) LKD(lock_font_draw); LKD(lock_bidi); + LKD(lock_ot); evas_common_font_load_shutdown(); evas_common_font_cache_set(0); diff --git a/src/lib/engines/common/evas_font_ot.c b/src/lib/engines/common/evas_font_ot.c new file mode 100644 index 0000000..62ed99a --- /dev/null +++ b/src/lib/engines/common/evas_font_ot.c @@ -0,0 +1,265 @@ +#include "evas_font_ot.h" + +#ifdef OT_SUPPORT +# include +# include +#endif + +#include "evas_common.h" + +#include +#include "evas_font_private.h" + +#ifdef OT_SUPPORT +/* FIXME: doc. returns #items */ +EAPI int +evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_index) +{ + int i; + int items; + int left_bound, right_bound; + size_t base_cluster; + char_index += props->start; + base_cluster = EVAS_FONT_OT_POS_GET(props->info->ot[char_index]); + for (i = (int) char_index ; + (i >= (int) props->start) && + (EVAS_FONT_OT_POS_GET(props->info->ot[i]) == base_cluster) ; + i--) + ; + left_bound = i; + for (i = (int) char_index + 1; + (i < (int) (props->start + props->len)) && + (EVAS_FONT_OT_POS_GET(props->info->ot[i]) == base_cluster) ; + i++) + ; + right_bound = i; + + if (right_bound == left_bound) + { + items = 1; + } + else if (props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) + { + if (left_bound < 0) + { + items = props->text_offset + props->text_len - base_cluster; + } + else + { + items = props->info->ot[left_bound].source_cluster - base_cluster; + } + } + else + { + if (right_bound >= (int) (props->text_offset + props->text_len)) + { + items = props->text_offset + props->text_len - base_cluster; + } + else + { + items = props->info->ot[right_bound].source_cluster - base_cluster; + } + } + return (items > 0) ? items : 1; +} + +EAPI void +evas_common_font_ot_load_face(void *_font) +{ + RGBA_Font_Source *font = (RGBA_Font_Source *) _font; + /* Unload the face if by any chance it's already loaded */ + evas_common_font_ot_unload_face(font); + font->hb.face = hb_ft_face_create(font->ft.face, NULL); +} + +EAPI void +evas_common_font_ot_unload_face(void *_font) +{ + RGBA_Font_Source *font = (RGBA_Font_Source *) _font; + if (!font->hb.face) return; + hb_face_destroy(font->hb.face); + font->hb.face = NULL; +} + +/* Harfbuzz font functions */ +static hb_font_funcs_t *_ft_font_funcs = NULL; + +static hb_codepoint_t +_evas_common_font_ot_hb_get_glyph(hb_font_t *font, hb_face_t *face, + const void *user_data, hb_codepoint_t unicode, + hb_codepoint_t variation_selector) +{ + RGBA_Font_Int *fi = (RGBA_Font_Int *) user_data; + return hb_font_funcs_get_glyph_func(_ft_font_funcs)(font, face, + fi->src->ft.face, unicode, variation_selector); +} + +static void +_evas_common_font_ot_hb_get_glyph_advance(hb_font_t *font, hb_face_t *face, + const void *user_data, hb_codepoint_t glyph, + hb_position_t *x_advance, hb_position_t *y_advance) +{ + /* Use our cache*/ + RGBA_Font_Int *fi = (RGBA_Font_Int *) user_data; + RGBA_Font_Glyph *fg; + (void) font; + (void) face; + fg = evas_common_font_int_cache_glyph_get(fi, glyph); + if (fg) + { + *x_advance = fg->glyph->advance.x >> 10; + *y_advance = fg->glyph->advance.y >> 10; + } +} + +static void +_evas_common_font_ot_hb_get_glyph_extents(hb_font_t *font, hb_face_t *face, + const void *user_data, hb_codepoint_t glyph, hb_glyph_extents_t *extents) +{ + RGBA_Font_Int *fi = (RGBA_Font_Int *) user_data; + hb_font_funcs_get_glyph_extents_func(_ft_font_funcs)(font, face, + fi->src->ft.face, glyph, extents); +} + +static hb_bool_t +_evas_common_font_ot_hb_get_contour_point(hb_font_t *font, hb_face_t *face, + const void *user_data, unsigned int point_index, hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) +{ + RGBA_Font_Int *fi = (RGBA_Font_Int *) user_data; + return hb_font_funcs_get_contour_point_func(_ft_font_funcs)(font, face, + fi->src->ft.face, point_index, glyph, x, y); +} + +static hb_position_t +_evas_common_font_ot_hb_get_kerning(hb_font_t *font, hb_face_t *face, + const void *user_data, hb_codepoint_t first_glyph, + hb_codepoint_t second_glyph) +{ + RGBA_Font_Int *fi = (RGBA_Font_Int *) user_data; + int kern; + (void) font; + (void) face; + if (evas_common_font_query_kerning(fi, first_glyph, second_glyph, &kern)) + return kern; + else + return 0; +} + +/* End of harfbuzz font funcs */ + +static hb_font_funcs_t * +_evas_common_font_ot_font_funcs_get(void) +{ + static hb_font_funcs_t *font_funcs = NULL; + if (!font_funcs) + { + _ft_font_funcs = hb_ft_get_font_funcs(); + font_funcs = hb_font_funcs_create(); + hb_font_funcs_set_glyph_func(font_funcs, + _evas_common_font_ot_hb_get_glyph); + hb_font_funcs_set_glyph_advance_func(font_funcs, + _evas_common_font_ot_hb_get_glyph_advance); + hb_font_funcs_set_glyph_extents_func(font_funcs, + _evas_common_font_ot_hb_get_glyph_extents); + hb_font_funcs_set_contour_point_func(font_funcs, + _evas_common_font_ot_hb_get_contour_point); + hb_font_funcs_set_kerning_func(font_funcs, + _evas_common_font_ot_hb_get_kerning); + } + + return font_funcs; +} + +static void +_evas_common_font_ot_shape(hb_buffer_t *buffer, RGBA_Font_Int *fi) +{ + hb_font_t *hb_font; + + hb_font = hb_ft_font_create(fi->src->ft.face, NULL); + hb_font_set_funcs(hb_font, _evas_common_font_ot_font_funcs_get(), NULL, fi); + + hb_shape(hb_font, fi->src->hb.face, buffer, NULL, 0); + hb_font_destroy(hb_font); +} + +EAPI Eina_Bool +evas_common_font_ot_populate_text_props(void *_fn, const Eina_Unicode *text, + Evas_Text_Props *props, int len) +{ + RGBA_Font *fn = (RGBA_Font *) _fn; + RGBA_Font_Int *fi; + hb_buffer_t *buffer; + hb_glyph_position_t *positions; + hb_glyph_info_t *infos; + int slen; + unsigned int i; + + fi = fn->fonts->data; + /* Load the font needed for this script */ + { + /* Skip common chars */ + const Eina_Unicode *tmp; + for (tmp = text ; + *tmp && + evas_common_language_char_script_get(*tmp) == EVAS_SCRIPT_COMMON ; + tmp++) + ; + if (!*tmp && (tmp > text)) tmp--; + evas_common_font_glyph_search(fn, &fi, *tmp); + } + evas_common_font_int_reload(fi); + if (fi->src->current_size != fi->size) + { + FTLOCK(); + FT_Activate_Size(fi->ft.size); + FTUNLOCK(); + fi->src->current_size = fi->size; + } + + if (len < 0) + { + slen = eina_unicode_strlen(text); + } + else + { + slen = len; + } + + buffer = hb_buffer_create(slen); + hb_buffer_set_unicode_funcs(buffer, evas_common_language_unicode_funcs_get()); + hb_buffer_set_language(buffer, hb_language_from_string( + evas_common_language_from_locale_get())); + hb_buffer_set_script(buffer, props->script); + hb_buffer_set_direction(buffer, + (props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) ? + HB_DIRECTION_RTL : HB_DIRECTION_LTR); + /* FIXME: add run-time conversions if needed, which is very unlikely */ + hb_buffer_add_utf32(buffer, (const uint32_t *) text, slen, 0, slen); + + _evas_common_font_ot_shape(buffer, fi); + + props->len = hb_buffer_get_length(buffer); + props->info->ot = calloc(props->len, + sizeof(Evas_Font_OT_Info)); + props->info->glyph = calloc(props->len, + sizeof(Evas_Font_Glyph_Info)); + positions = hb_buffer_get_glyph_positions(buffer); + infos = hb_buffer_get_glyph_infos(buffer); + for (i = 0 ; i < props->len ; i++) + { + props->info->ot[i].source_cluster = infos[i].cluster; + props->info->ot[i].x_offset = positions[i].x_offset; + props->info->ot[i].y_offset = positions[i].y_offset; + props->info->glyph[i].index = infos[i].codepoint; + props->info->glyph[i].advance = positions[i].x_advance; + } + + hb_buffer_destroy(buffer); + evas_common_font_int_use_trim(); + + return EINA_FALSE; +} + +#endif + diff --git a/src/lib/engines/common/evas_font_ot.h b/src/lib/engines/common/evas_font_ot.h new file mode 100644 index 0000000..9cf0148 --- /dev/null +++ b/src/lib/engines/common/evas_font_ot.h @@ -0,0 +1,51 @@ +#ifndef _EVAS_FONT_OT_H +# define _EVAS_FONT_OT_H + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# ifdef HAVE_HARFBUZZ +# define OT_SUPPORT +# define USE_HARFBUZZ +# endif + +# ifdef OT_SUPPORT +# include +typedef struct _Evas_Font_OT_Info Evas_Font_OT_Info; +# else +typedef void *Evas_Font_OT_Info; +# endif + +# include "Evas.h" + +# ifdef OT_SUPPORT +struct _Evas_Font_OT_Info +{ + size_t source_cluster; + Evas_Coord x_offset; + Evas_Coord y_offset; +}; +# endif + +# ifdef OT_SUPPORT +# define EVAS_FONT_OT_X_OFF_GET(a) ((a).x_offset) +# define EVAS_FONT_OT_Y_OFF_GET(a) ((a).y_offset) +# define EVAS_FONT_OT_POS_GET(a) ((a).source_cluster) +# endif + +EAPI void +evas_common_font_ot_load_face(void *_font); + +EAPI void +evas_common_font_ot_unload_face(void *_font); + +# include "evas_text_utils.h" +EAPI int +evas_common_font_ot_cluster_size_get(const Evas_Text_Props *props, size_t char_index); + +EAPI Eina_Bool +evas_common_font_ot_populate_text_props(void *fn, const Eina_Unicode *text, + Evas_Text_Props *props, int len); +#endif + diff --git a/src/lib/engines/common/evas_font_private.h b/src/lib/engines/common/evas_font_private.h index 57940ee..cc68578 100644 --- a/src/lib/engines/common/evas_font_private.h +++ b/src/lib/engines/common/evas_font_private.h @@ -1,9 +1,11 @@ #ifndef _EVAS_FONT_PRIVATE_H # define _EVAS_FONT_PRIVATE_H +#include "evas_font_ot.h" #ifdef BUILD_PTHREAD extern LK(lock_font_draw); // for freetype2 API calls extern LK(lock_bidi); // for fribidi API calls +extern LK(lock_ot); // for harfbuzz calls #endif # if defined(EVAS_FRAME_QUEUING) || defined(BUILD_PIPE_RENDER) @@ -12,13 +14,15 @@ extern LK(lock_bidi); // for fribidi API calls # define BIDILOCK() LKL(lock_bidi) # define BIDIUNLOCK() LKU(lock_bidi) + +# define OTLOCK() LKL(lock_ot) +# define OTUNLOCK() LKU(lock_ot) # else -# define FTLOCK(x) -# define FTUNLOCK(x) +# define FTLOCK(x) +# define FTUNLOCK(x) -# define BIDILOCK() -# define BIDIUNLOCK() -# endif +# define BIDILOCK() +# define BIDIUNLOCK() void evas_common_font_source_unload(RGBA_Font_Source *fs); void evas_common_font_source_reload(RGBA_Font_Source *fs); @@ -28,5 +32,20 @@ void evas_common_font_int_use_increase(int size); void evas_common_font_int_use_trim(void); void evas_common_font_int_unload(RGBA_Font_Int *fi); void evas_common_font_int_reload(RGBA_Font_Int *fi); +/* Macros for text walking */ +# define OTLOCK() +# define OTUNLOCK() +# endif + +/* 6th bit is on is the same as frac part >= 0.5 */ +# define EVAS_FONT_ROUND_26_6_TO_INT(x) \ + (((x + 0x20) & -0x40) >> 6) + +# define EVAS_FONT_CHARACTER_IS_INVISIBLE(x) ( \ + ((0x200C <= (x)) && ((x) <= 0x200D)) || /* ZWNJ..ZWH */ \ + ((0x200E <= (x)) && ((x) <= 0x200F)) || /* BIDI stuff */ \ + ((0x202A <= (x)) && ((x) <= 0x202E)) /* BIDI stuff */ \ + ) +# include "evas_font_default_walk.x" #endif /* !_EVAS_FONT_PRIVATE_H */ diff --git a/src/lib/engines/common/evas_font_query.c b/src/lib/engines/common/evas_font_query.c index e570f69..ae73e60 100644 --- a/src/lib/engines/common/evas_font_query.c +++ b/src/lib/engines/common/evas_font_query.c @@ -1,6 +1,7 @@ #include "evas_common.h" -#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */ +#include "language/evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */ #include "evas_font_private.h" /* for Frame-Queuing support */ +#include "evas_font_ot.h" EAPI int evas_common_font_query_kerning(RGBA_Font_Int* fi, @@ -36,7 +37,7 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi, int *push; FTUNLOCK(); - *kerning = delta.x >> 6; + *kerning = delta.x; push = malloc(sizeof (int) * 3); if (!push) return 1; @@ -57,267 +58,70 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi, return error; } +/* text x inset */ +EAPI int +evas_common_font_query_inset(RGBA_Font *fn __UNUSED__, const Evas_Text_Props *text_props) +{ + if (!text_props->len) return 0; + return text_props->info->glyph[text_props->start].x_bear; +} + /* size of the string (width and height) in pixels - * BiDi handling: We receive the shaped string + other props from intl_props, + * BiDi handling: We receive the shaped string + other props from text_props, * We only care about the size, and the size does not depend on the visual order. * As long as we follow the logical string and get kerning data like we should, * we are fine. */ EAPI void -evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props __UNUSED__, int *w, int *h) +evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text __UNUSED__, const Evas_Text_Props *text_props, int *w, int *h) { - int use_kerning; - int pen_x, pen_y; - int start_x, end_x; - int chr; - int char_index; - FT_UInt prev_index; - RGBA_Font_Int *fi; - FT_Face pface = NULL; - - fi = fn->fonts->data; - - start_x = 0; - end_x = 0; - - pen_x = 0; - pen_y = 0; -// evas_common_font_size_use(fn); - evas_common_font_int_reload(fi); - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - prev_index = 0; - for (chr = 0, char_index = 0; *text; text++, char_index ++) - { - FT_UInt index; - RGBA_Font_Glyph *fg = NULL; - int chr_x, chr_y, advw; - int gl, kern; - - gl = *text; - if (gl == 0) break; - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - kern = 0; - /* hmmm kerning means i can't sanely do my own cached metric tables! */ - /* grrr - this means font face sharing is kinda... not an option if */ - /* you want performance */ - if ((use_kerning) && (prev_index) && (index) && (fg) && - (pface == fi->src->ft.face)) - { -#ifdef BIDI_SUPPORT - /* if it's rtl, the kerning matching should be reversed, i.e prev - * index is now the index and the other way around. - * There is a slight exception when there are compositing chars - * involved.*/ - if (intl_props && - evas_bidi_is_rtl_char(intl_props, char_index) && - ((fg->glyph->advance.x >> 16) > 0)) - { - if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) - pen_x += kern; - } - else - { - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - } -#else - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; -#endif - } - - pface = fi->src->ft.face; - fg = evas_common_font_int_cache_glyph_get(fi, index); - LKU(fi->ft_mutex); - if (!fg || !fg->glyph) continue; - - if (kern < 0) kern = 0; - - /* We care about advancing the whole string size, and not the actual - * paint size of each string, so we only care about advancing correctly - * and not the actual glyph width */ - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - chr_x = pen_x - kern; - chr_y = pen_y; - /* If it's not a compositing char, i.e it advances, we should also add - * the left/top padding of the glyph. As we don't care about the padding - * as the drawing location remains the same. - */ - if (advw > 0) - { - chr_x += fg->glyph_out->left; - chr_y += fg->glyph_out->top; - } - - - if ((!prev_index) && (chr_x < 0)) - start_x = chr_x; - if ((chr_x + advw) > end_x) - end_x = chr_x + advw; + int keep_width = 0; + int prev_pen_x = 0; + EVAS_FONT_WALK_TEXT_INIT(); - pen_x += fg->glyph->advance.x >> 16; - prev_index = index; - } - if (w) *w = end_x - start_x; - if (h) *h = evas_common_font_max_ascent_get(fn) + evas_common_font_max_descent_get(fn); - evas_common_font_int_use_trim(); -} - -/* text x inset */ -EAPI int -evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text) -{ - FT_UInt index; - RGBA_Font_Glyph *fg; - int gl; - RGBA_Font_Int *fi; - - fi = fn->fonts->data; - - if (!*text) return 0; - gl = *text; - if (gl == 0) return 0; -// evas_common_font_size_use(fn); - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - evas_common_font_int_reload(fi); - if (fi->src->current_size != fi->size) + EVAS_FONT_WALK_TEXT_VISUAL_START() { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; + EVAS_FONT_WALK_TEXT_WORK(); + if (!EVAS_FONT_WALK_IS_VISIBLE) continue; + /* Keep the width because we'll need it for the last char */ + keep_width = EVAS_FONT_WALK_WIDTH + + EVAS_FONT_WALK_X_OFF + + EVAS_FONT_WALK_X_BEAR; + /* Keep the previous EVAS_FONT_WALK_PEN_X, before it's advanced in TEXT_END */ + prev_pen_x = EVAS_FONT_WALK_PEN_X; } - fg = evas_common_font_int_cache_glyph_get(fi, index); - LKU(fi->ft_mutex); - if (!fg) return 0; -/* - INF("fg->glyph_out->left = %i, " - "fi->src->ft.face->glyph->bitmap_left = %i, " - "fi->src->ft.face->glyph->metrics.horiBearingX = %i, " - "fi->src->ft.face->glyph->metrics.horiBearingY = %i, " - "fi->src->ft.face->glyph->metrics.horiAdvance = %i" - , - (int)fg->glyph_out->left, - (int)fi->src->ft.face->glyph->bitmap_left, - (int)fi->src->ft.face->glyph->metrics.horiBearingX >> 6, - (int)fi->src->ft.face->glyph->metrics.horiBearingY >> 6, - (int)fi->src->ft.face->glyph->metrics.horiAdvance >> 6 - ); - */ - evas_common_font_int_use_trim(); - return fg->glyph_out->left; + EVAS_FONT_WALK_TEXT_END(); + + if (w) *w = prev_pen_x + keep_width; + if (h) *h = evas_common_font_max_ascent_get(fn) + evas_common_font_max_descent_get(fn); } /* h & v advance - * BiDi handling: We receive the shaped string + other props from intl_props, + * BiDi handling: We receive the shaped string + other props from text_props, * We don't care about the order, as heights will remain the same (we already did * shaping) and as long as we go through the logical string and match the kerning * this way, we are safe. */ - EAPI void -evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *h_adv, int *v_adv) +evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text __UNUSED__, const Evas_Text_Props *text_props, int *h_adv, int *v_adv) { - int use_kerning; - int pen_x, pen_y; - int start_x; - int char_index; - FT_UInt prev_index; - RGBA_Font_Int *fi; - FT_Face pface = NULL; - - fi = fn->fonts->data; - - start_x = 0; - pen_x = 0; - pen_y = 0; -// evas_common_font_size_use(fn); - evas_common_font_int_reload(fi); - FTLOCK(); - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - FTUNLOCK(); - prev_index = 0; - for (char_index = 0 ; *text ; text++, char_index++) - { - FT_UInt index; - RGBA_Font_Glyph *fg; - int gl, kern; - - gl = *text; - if (gl == 0) break; - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - fg = evas_common_font_int_cache_glyph_get(fi, index); - if (!fg) - { - LKU(fi->ft_mutex); - continue; - } - // FIXME: Why no FT_Activate_Size here ? - kern = 0; - /* hmmm kerning means i can't sanely do my own cached metric tables! */ - /* grrr - this means font face sharing is kinda... not an option if */ - /* you want performance */ - if ((use_kerning) && (prev_index) && (index) && (fg) && - (pface == fi->src->ft.face)) - { -#ifdef BIDI_SUPPORT - /* if it's rtl, the kerning matching should be reversed, i.e prev - * index is now the index and the other way around. - * There is a slight exception when there are compositing chars - * involved.*/ - if (intl_props && - evas_bidi_is_rtl_char(intl_props, char_index) && - fg->glyph->advance.x >> 16 > 0) - { - if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) - pen_x += kern; - } - else - { - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - } -#else - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; -#endif - } - - pface = fi->src->ft.face; - LKU(fi->ft_mutex); + EVAS_FONT_WALK_TEXT_INIT(); - pen_x += fg->glyph->advance.x >> 16; - prev_index = index; + EVAS_FONT_WALK_TEXT_LOGICAL_START() + { + EVAS_FONT_WALK_TEXT_WORK(); + if (!EVAS_FONT_WALK_IS_VISIBLE) continue; } + EVAS_FONT_WALK_TEXT_END(); + if (v_adv) *v_adv = evas_common_font_get_line_advance(fn); - if (h_adv) *h_adv = pen_x - start_x; -#ifndef BIDI_SUPPORT - intl_props = NULL; -#endif - evas_common_font_int_use_trim(); + if (h_adv) *h_adv = EVAS_FONT_WALK_PEN_X; } /* x y w h for char at char pos for null it returns the position right after * the last char with 0 as width and height. - * BiDi handling: We receive the shaped string + other props from intl_props, + * BiDi handling: We receive the shaped string + other props from text_props, * We care about the actual drawing location of the string, this is why we need * the visual string. We need to know how it's printed. After that we need to calculate * the reverse kerning in case of rtl parts. "pos" passed to this function is an @@ -326,164 +130,235 @@ evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Ev */ EAPI int -evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch) +evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *text __UNUSED__, const Evas_Text_Props *text_props, int pos, int *cx, int *cy, int *cw, int *ch) { - int use_kerning; - int pen_x, pen_y; - int prev_chr_end; int asc, desc; - int char_index = 0; /* the index of the current char */ - int position = 0; - const Eina_Unicode *text = in_text; + size_t position = 0; int ret_val = 0; - int last_adv; - FT_UInt prev_index; - RGBA_Font_Int *fi; - FT_Face pface = NULL; + EVAS_FONT_WALK_TEXT_INIT(); -#ifdef BIDI_SUPPORT - int len = 0; - EvasBiDiStrIndex *visual_to_logical = NULL; - Eina_Unicode *visual_text; + asc = evas_common_font_max_ascent_get(fn); + desc = evas_common_font_max_descent_get(fn); - visual_text = eina_unicode_strdup(in_text); - if (visual_text) + position = pos; + /* If it's the null, choose location according to the direction. */ + if (position == text_props->text_len) { - evas_bidi_props_reorder_line(visual_text, intl_props, &visual_to_logical); - text = visual_text; + /* if it's rtl then the location is the left of the string, + * otherwise, the right. */ +#ifdef BIDI_SUPPORT + if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) + { + if (cx) *cx = 0; + if (ch) *ch = asc + desc; + } + else +#endif + { + evas_common_font_query_advance(fn, text, text_props, cx, ch); + } + if (cy) *cy = 0; + if (cw) *cw = 0; + ret_val = 1; + goto end; } - else + + Evas_Coord cluster_start = 0, last_end = 0; + int prev_cluster = -1; + int found = 0, items = 1, item_pos = 1; + int last_is_visible = 0; + EVAS_FONT_WALK_TEXT_VISUAL_START() { - text = in_text; - } - len = eina_unicode_strlen(text); -#endif + EVAS_FONT_WALK_TEXT_WORK(); - fi = fn->fonts->data; + if (prev_cluster != (int) EVAS_FONT_WALK_POS) + { + if (found) + { + break; + } + else + { + cluster_start = EVAS_FONT_WALK_PEN_X + + EVAS_FONT_WALK_X_OFF + + EVAS_FONT_WALK_X_BEAR; + } + } + last_is_visible = EVAS_FONT_WALK_IS_VISIBLE; + last_end = EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + + EVAS_FONT_WALK_X_BEAR + EVAS_FONT_WALK_WIDTH; + /* we need to see if the char at the visual position is the char wanted */ + if ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR) && + (EVAS_FONT_WALK_POS <= (size_t) position) && + ((((size_t) position) < EVAS_FONT_WALK_POS_NEXT) || + (EVAS_FONT_WALK_IS_LAST))) + { + found = 1; +#ifdef OT_SUPPORT + items = evas_common_font_ot_cluster_size_get(text_props, + char_index); +#endif + item_pos = position - EVAS_FONT_WALK_POS + 1; + } + else if ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) && + ((EVAS_FONT_WALK_POS_PREV > (size_t) position) || + (EVAS_FONT_WALK_IS_FIRST)) && + (((size_t) position) >= EVAS_FONT_WALK_POS)) + { + found = 1; +#ifdef OT_SUPPORT + items = evas_common_font_ot_cluster_size_get(text_props, + char_index); +#endif + item_pos = items - (position - EVAS_FONT_WALK_POS); + } - pen_x = 0; - pen_y = 0; - evas_common_font_int_reload(fi); -// evas_common_font_size_use(fn); - if (fi->src->current_size != fi->size) + prev_cluster = EVAS_FONT_WALK_POS; + } + EVAS_FONT_WALK_TEXT_END(); + if (found) { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; + Evas_Coord cluster_w; + cluster_w = last_end - cluster_start; + if (cy) *cy = -asc; + if (ch) *ch = asc + desc; + if (last_is_visible) + { + if (cx) *cx = cluster_start + + (cluster_w / items) * + (item_pos - 1); + if (cw) *cw = (cluster_w / items); + } + else + { + if (cx) *cx = cluster_start; + if (cw) *cw = 0; + } + ret_val = 1; + goto end; } - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - prev_index = 0; - prev_chr_end = 0; +end: + + return ret_val; +} + +/* x y w h for pen at char pos for null it returns the position right after + * the last char with 0 as width and height. This is the same as char_coords + * but it returns the pen_x and adv instead of x and w. + * BiDi handling: We receive the shaped string + other props from text_props, + * We care about the actual drawing location of the string, this is why we need + * the visual string. We need to know how it's printed. After that we need to calculate + * the reverse kerning in case of rtl parts. "pos" passed to this function is an + * index in bytes, that is the actual byte location of the string, we need to find + * the index in order to find it in the visual string. + */ + +EAPI int +evas_common_font_query_pen_coords(RGBA_Font *fn, const Eina_Unicode *text __UNUSED__, const Evas_Text_Props *text_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch) +{ + int asc, desc; + size_t position; + int ret_val = 0; + EVAS_FONT_WALK_TEXT_INIT(); + asc = evas_common_font_max_ascent_get(fn); desc = evas_common_font_max_descent_get(fn); -#ifdef BIDI_SUPPORT - /* Get the position in the visual string because those are the coords we care about */ - position = evas_bidi_position_logical_to_visual(visual_to_logical, len, pos); -#else position = pos; -#endif /* If it's the null, choose location according to the direction. */ - if (!text[position]) + if (position == text_props->text_len) { /* if it's rtl then the location is the left of the string, * otherwise, the right. */ #ifdef BIDI_SUPPORT - if (evas_bidi_is_rtl_char(intl_props, 0)) + if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) { - if (cx) *cx = 0; + if (cpen_x) *cpen_x = 0; if (ch) *ch = asc + desc; } else #endif { - evas_common_font_query_size(fn, text, intl_props, cx, ch); + evas_common_font_query_advance(fn, text, text_props, cpen_x, ch); } if (cy) *cy = 0; - if (cw) *cw = 0; + if (cadv) *cadv = 0; ret_val = 1; goto end; } - - last_adv = 0; - for (char_index = 0; *text ; text++, char_index++) + Evas_Coord cluster_start = 0; + int prev_cluster = -1; + int found = 0, items = 1, item_pos = 1; + int last_is_visible = 0; + EVAS_FONT_WALK_TEXT_VISUAL_START() { - FT_UInt index; - RGBA_Font_Glyph *fg; - int chr_x, chr_y, chr_w; - int gl, kern; - - gl = *text; - if (gl == 0) break; - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - fg = evas_common_font_int_cache_glyph_get(fi, index); - if (!fg) + EVAS_FONT_WALK_TEXT_WORK(); + + if (prev_cluster != (int) EVAS_FONT_WALK_POS) + { + if (found) + { + break; + } + else + { + cluster_start = EVAS_FONT_WALK_PEN_X; + } + } + last_is_visible = EVAS_FONT_WALK_IS_VISIBLE; + + if ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR) && + (EVAS_FONT_WALK_POS <= (size_t) position) && + ((((size_t) position) < EVAS_FONT_WALK_POS_NEXT) || + (EVAS_FONT_WALK_IS_LAST))) { - LKU(fi->ft_mutex); - continue; + found = 1; +#ifdef OT_SUPPORT + items = evas_common_font_ot_cluster_size_get(text_props, + char_index); +#endif + item_pos = position - EVAS_FONT_WALK_POS + 1; } - // FIXME: Why no FT_Activate_Size here ? - kern = 0; - /* hmmm kerning means i can't sanely do my own cached metric tables! */ - /* grrr - this means font face sharing is kinda... not an option if */ - /* you want performance */ - if ((use_kerning) && (prev_index) && (index) && - (pface == fi->src->ft.face)) - { - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - } - - pface = fi->src->ft.face; - LKU(fi->ft_mutex); - /* If the current one is not a compositing char, do the previous advance - * and set the current advance as the next advance to do */ - if (fg->glyph->advance.x >> 16 > 0) - { - pen_x += last_adv; - last_adv = fg->glyph->advance.x >> 16; - } - if (kern < 0) kern = 0; - chr_x = (pen_x - kern) + (fg->glyph_out->left); - chr_y = (pen_y) + (fg->glyph_out->top); - chr_w = fg->glyph_out->bitmap.width + (kern); -/* if (text[chr]) */ - { - int advw; - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - if (chr_w < advw) chr_w = advw; - } -#if 0 /* This looks like a hack, we don't want it. - leaving it here in case - * I'm wrong */ - if (chr_x > prev_chr_end) - { - chr_w += (chr_x - prev_chr_end); - chr_x = prev_chr_end; - } + else if ((text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) && + ((EVAS_FONT_WALK_POS_PREV > (size_t) position) || + (EVAS_FONT_WALK_IS_FIRST)) && + (((size_t) position) >= EVAS_FONT_WALK_POS)) + { + found = 1; +#ifdef OT_SUPPORT + items = evas_common_font_ot_cluster_size_get(text_props, + char_index); #endif - /* we need to see if the char at the visual position is the char wanted */ - if (char_index == position) - { - if (cx) *cx = chr_x; - if (cy) *cy = -asc; - if (cw) *cw = chr_w; - if (ch) *ch = asc + desc; - ret_val = 1; - goto end; - } - prev_chr_end = chr_x + chr_w; - prev_index = index; + item_pos = items - (position - EVAS_FONT_WALK_POS); + } + + prev_cluster = EVAS_FONT_WALK_POS; } -end: + EVAS_FONT_WALK_TEXT_END(); -#ifdef BIDI_SUPPORT - if (visual_to_logical) free(visual_to_logical); - if (visual_text) free(visual_text); -#endif + if (found) + { + Evas_Coord cluster_adv; + cluster_adv = EVAS_FONT_WALK_PEN_X - cluster_start; + if (cy) *cy = -asc; + if (ch) *ch = asc + desc; + if (last_is_visible) + { + if (cpen_x) *cpen_x = cluster_start + + (cluster_adv / items) * + (item_pos - 1); + if (cadv) *cadv = (cluster_adv / items); + } + else + { + if (cpen_x) *cpen_x = EVAS_FONT_WALK_PEN_X; + if (cadv) *cadv = 0; + } + ret_val = 1; + goto end; + } +end: - evas_common_font_int_use_trim(); return ret_val; } @@ -495,266 +370,114 @@ end: */ EAPI int -evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch) +evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *text __UNUSED__, const Evas_Text_Props *text_props, int x, int y, int *cx, int *cy, int *cw, int *ch) { - int use_kerning; - int pen_x, pen_y; - int prev_chr_end; int asc, desc; - int char_index = 0; /* the index of the current char */ - const Eina_Unicode *text = in_text; - int last_adv; int ret_val = -1; - FT_UInt prev_index; - RGBA_Font_Int *fi; - FT_Face pface = NULL; + EVAS_FONT_WALK_TEXT_INIT(); -#ifdef BIDI_SUPPORT - int len = 0; - EvasBiDiStrIndex *visual_to_logical = NULL; - Eina_Unicode *visual_text; + asc = evas_common_font_max_ascent_get(fn); + desc = evas_common_font_max_descent_get(fn); + Evas_Coord cluster_start = 0; + int prev_cluster = -1; + int found = 0, items = 1; + EVAS_FONT_WALK_TEXT_VISUAL_START() + { + EVAS_FONT_WALK_TEXT_WORK(); + if (prev_cluster != (int) EVAS_FONT_WALK_POS) + { + if (found) + { + break; + } + else + { + cluster_start = EVAS_FONT_WALK_PEN_X; + } + } - visual_text = eina_unicode_strdup(in_text); + if (!EVAS_FONT_WALK_IS_VISIBLE) continue; - if (visual_text) - { - evas_bidi_props_reorder_line(visual_text, intl_props, &visual_to_logical); - text = visual_text; - } - else - { - text = in_text; - } - len = eina_unicode_strlen(text); + /* we need to see if the char at the visual position is the char, + * we check that by checking if it's before the current pen + * position and the next */ + if ((x >= EVAS_FONT_WALK_PEN_X) && (x <= (EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_ADV)) && + (y >= -asc) && (y <= desc)) + { +#ifdef OT_SUPPORT + items = evas_common_font_ot_cluster_size_get(text_props, + char_index); #endif + found = 1; + } - fi = fn->fonts->data; - - pen_x = 0; - pen_y = 0; - evas_common_font_int_reload(fi); -// evas_common_font_size_use(fn); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; + prev_cluster = EVAS_FONT_WALK_POS; } - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - last_adv = 0; - prev_index = 0; - prev_chr_end = 0; - asc = evas_common_font_max_ascent_get(fn); - desc = evas_common_font_max_descent_get(fn); - - for (char_index = 0; *text; text++, char_index++) + EVAS_FONT_WALK_TEXT_END(); + if (found) { - FT_UInt index; - RGBA_Font_Glyph *fg; - int chr_x, chr_y, chr_w; - int gl, kern; - - gl = *text; - if (gl == 0) break; - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - fg = evas_common_font_int_cache_glyph_get(fi, index); - if (!fg) + int item_pos; + Evas_Coord cluster_adv; + cluster_adv = EVAS_FONT_WALK_PEN_X - cluster_start; + + if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_LTR) { - LKU(fi->ft_mutex); - continue; + double part; + part = cluster_adv / items; + item_pos = (int) ((x - cluster_start) / part); } - - // FIXME: Why not FT_Activate_Size here ? - kern = 0; - /* hmmm kerning means i can't sanely do my own cached metric tables! */ - /* grrr - this means font face sharing is kinda... not an option if */ - /* you want performance */ - if ((use_kerning) && (prev_index) && (index) && - (pface == fi->src->ft.face)) - { - if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) - pen_x += kern; - } - pface = fi->src->ft.face; - LKU(fi->ft_mutex); - /* If the current one is not a compositing char, do the previous advance - * and set the current advance as the next advance to do */ - if (fg->glyph->advance.x >> 16 > 0) - { - pen_x += last_adv; - last_adv = fg->glyph->advance.x >> 16; - } - if (kern < 0) kern = 0; - - chr_x = ((pen_x - kern) + (fg->glyph_out->left)); - chr_y = (pen_y + (fg->glyph_out->top)); - chr_w = fg->glyph_out->bitmap.width + kern; - -/* if (text[chr]) */ - { - int advw; - - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - if (chr_w < advw) chr_w = advw; - } -#if 0 /* This looks like a hack, we don't want it. - leaving it here in case - * I'm wrong */ - if (chr_x > prev_chr_end) - { - chr_w += (chr_x - prev_chr_end); - chr_x = prev_chr_end; - } -#endif - if ((x >= chr_x) && (x <= (chr_x + chr_w)) && - (y >= -asc) && (y <= desc)) - { - int position = char_index; - if (cx) *cx = chr_x; - if (cy) *cy = -asc; - if (cw) *cw = chr_w; - if (ch) *ch = asc + desc; -#ifdef BIDI_SUPPORT - /* we found the char position of the wanted char in the - * visual string, we now need to translate it to the - * position in the logical string */ - position = evas_bidi_position_visual_to_logical(visual_to_logical, position); -#endif - ret_val = position; - goto end; - } - prev_chr_end = chr_x + chr_w; - prev_index = index; + else + { + double part; + part = cluster_adv / items; + item_pos = items - ((int) ((x - cluster_start) / part)) - 1; + } + if (cx) *cx = EVAS_FONT_WALK_PEN_X + + ((cluster_adv / items) * (item_pos - 1)); + if (cy) *cy = -asc; + if (cw) *cw = (cluster_adv / items); + if (ch) *ch = asc + desc; + ret_val = prev_cluster + item_pos; + goto end; } - end: - -#ifdef BIDI_SUPPORT - if (visual_to_logical) free(visual_to_logical); - if (visual_text) free(visual_text); -#else - intl_props = NULL; -#endif - evas_common_font_int_use_trim(); return ret_val; } -/* position of the last char in thext text that will fit in xy. - * BiDi handling: We receive the shaped string + other props from intl_props, +/* position of the char after the last char in the text that will fit in xy. + * BiDi handling: We receive the shaped string + other props from text_props, * All we care about is char sizes + kerning so we only really need to get the * shaped string to utf8, and then just go through it like in english, as it's * just the logical string, nothing special about that. */ EAPI int -evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props __UNUSED__, int x, int y) +evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *text __UNUSED__, const Evas_Text_Props *text_props, int x, int y) { - int use_kerning; - int pen_x, pen_y; - int prev_chr_end; - int char_index; int asc, desc; int ret=-1; - const Eina_Unicode *text = in_text; - FT_UInt prev_index; - RGBA_Font_Int *fi; - FT_Face pface = NULL; - - fi = fn->fonts->data; + EVAS_FONT_WALK_TEXT_INIT(); - pen_x = 0; - pen_y = 0; - evas_common_font_int_reload(fi); -// evas_common_font_size_use(fn); - use_kerning = FT_HAS_KERNING(fi->src->ft.face); - prev_index = 0; - prev_chr_end = 0; asc = evas_common_font_max_ascent_get(fn); desc = evas_common_font_max_descent_get(fn); - for (char_index = 0; *text; text++, char_index++) + + EVAS_FONT_WALK_TEXT_LOGICAL_START() { - FT_UInt index; - RGBA_Font_Glyph *fg = NULL; - int chr_x, chr_y, chr_w; - int gl, kern; - - gl = *text; - if (gl == 0) break; - index = evas_common_font_glyph_search(fn, &fi, gl); - LKL(fi->ft_mutex); - if (fi->src->current_size != fi->size) - { - FTLOCK(); - FT_Activate_Size(fi->ft.size); - FTUNLOCK(); - fi->src->current_size = fi->size; - } - kern = 0; - /* hmmm kerning means i can't sanely do my own cached metric tables! */ - /* grrr - this means font face sharing is kinda... not an option if */ - /* you want performance */ - if ((use_kerning) && (prev_index) && (index) && (fg) && - (pface == fi->src->ft.face)) + EVAS_FONT_WALK_TEXT_WORK(); + if (!EVAS_FONT_WALK_IS_VISIBLE) continue; + + if ((x >= EVAS_FONT_WALK_PEN_X) && (x <= (EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_ADV)) && + (y >= -asc) && (y <= desc)) { -#ifdef BIDI_SUPPORT - /* if it's rtl, the kerning matching should be reversed, i.e prev - * index is now the index and the other way around. - * There is a slight exception when there are compositing chars - * involved.*/ - if (intl_props && - evas_bidi_is_rtl_char(intl_props, char_index) && - ((fg->glyph->advance.x >> 16) > 0)) - { - if (evas_common_font_query_kerning(fi, index, prev_index, - &kern)) - pen_x += kern; - } - else - { - if (evas_common_font_query_kerning(fi, prev_index, index, - &kern)) - pen_x += kern; - } -#else - if (evas_common_font_query_kerning(fi, prev_index, index, - &kern)) - pen_x += kern; -#endif - } - pface = fi->src->ft.face; - fg = evas_common_font_int_cache_glyph_get(fi, index); - LKU(fi->ft_mutex); - - if (kern < 0) kern = 0; - chr_x = ((pen_x - kern) + (fg->glyph_out->left)); - chr_y = (pen_y + (fg->glyph_out->top)); - chr_w = fg->glyph_out->bitmap.width + kern; -/* if (text[chr]) */ - { - int advw; - - advw = ((fg->glyph->advance.x + (kern << 16)) >> 16); - if (chr_w < advw) chr_w = advw; - } - if (chr_x > prev_chr_end) - { - chr_w += (chr_x - prev_chr_end); - chr_x = prev_chr_end; - } - if ((x >= chr_x) && (x <= (chr_x + chr_w)) && - (y >= -asc) && (y <= desc)) - { - ret = char_index; + ret = EVAS_FONT_WALK_POS; goto end; - } - prev_chr_end = chr_x + chr_w; - pen_x += fg->glyph->advance.x >> 16; - prev_index = index; + } } + EVAS_FONT_WALK_TEXT_END(); + end: - evas_common_font_int_use_trim(); - return ret; + return ret; } + diff --git a/src/lib/engines/common/evas_map_image.c b/src/lib/engines/common/evas_map_image.c index 7330910..6ac74a3 100644 --- a/src/lib/engines/common/evas_map_image.c +++ b/src/lib/engines/common/evas_map_image.c @@ -341,7 +341,7 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy EAPI void evas_common_map_rgba(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, - int npoints, RGBA_Map_Point *p, + int npoints __UNUSED__, RGBA_Map_Point *p, int smooth, int level) { #ifdef BUILD_MMX diff --git a/src/lib/engines/common/evas_op_blend/op_blend_pixel_neon.c b/src/lib/engines/common/evas_op_blend/op_blend_pixel_neon.c index cba9c66..1cb50b6 100644 --- a/src/lib/engines/common/evas_op_blend/op_blend_pixel_neon.c +++ b/src/lib/engines/common/evas_op_blend/op_blend_pixel_neon.c @@ -113,7 +113,8 @@ _op_blend_p_dp_neon(DATA32 *s, DATA8 *m, DATA32 c, DATA32 *d, int l) { //** Oct loop "vldm %[s]!, {d0,d1,d2,d3) \n\t" "vldm %[d], {d4,d5,d6,d7} \n\t" - + "pld [%[s], #64] \n\t" + // Copy s.a into q2 (>> 24) & subtract from 255 "vmvn.u8 q4, q0 \n\t" diff --git a/src/lib/engines/common/evas_op_copy/op_copy_pixel_neon.c b/src/lib/engines/common/evas_op_copy/op_copy_pixel_neon.c index e4afbbb..5b8bd60 100644 --- a/src/lib/engines/common/evas_op_copy/op_copy_pixel_neon.c +++ b/src/lib/engines/common/evas_op_copy/op_copy_pixel_neon.c @@ -3,47 +3,47 @@ #ifdef BUILD_NEON static void _op_copy_p_dp_neon(DATA32 *s, DATA8 *m __UNUSED__, DATA32 c __UNUSED__, DATA32 *d, int l) { +//#define USENEON 1 +#ifndef USENEON + memcpy(d, s, l * sizeof(DATA32)); + return; +#else DATA32 *e; -// if (((unsigned long)s & 0xf) || ((unsigned long)d & 0xf)) -// { - memcpy(d, s, l * sizeof(DATA32)); -// return; -// } -/* e = d + l - 23; if (e > d) { int dl; - asm volatile ( - ".fpu neon \n\t" - "asmloop2: \n\t" - "cmp %[e], %[d] \n\t" // compare current and end ptr - "pld [%[s], #64] \n\t" // preload 64 bytes ahead - "pld [%[s], #256] \n\t" // preload 256 bytes ahead - "pld [%[s], #320] \n\t" // preload 320 bytes ahead - "vld1.64 {d0-d3}, [%[s]]! \n\t" // load 256bits (32 bytes 8 pix) - "vld1.64 {d4-d7} , [%[s]]! \n\t" // load 256bits (32 bytes 8 pix) - "vld1.64 {d8-d11}, [%[s]]! \n\t" // load 256bits (32 bytes 8 pix) - "vst1.64 {d0-d3}, [%[d]]! \n\t" // store 256bits (32 bytes 8 pix) - "vst1.64 {d4-d7}, [%[d]]! \n\t" // store 256bits (32 bytes 8 pix) - "vst1.64 {d8-d11}, [%[d]]! \n\t" // store 256bits (32 bytes 8 pix) - "bhi asmloop2 \n\t" - : // output regs - : [s] "r" (s), [e] "r" (e), [d] "r" (d) // input - : "q0", "q1", "q2", "q3", "q4", "q5", - "d0", "d1", "d2", "d3", "d4", "d5", - "d6", "d7", "d8", "d9", "d10", "d11", - "memory" // clobbered - ); - e = d + l; - dl = l - (l % 24); - s = s + dl; - d = d + dl; + + asm volatile + (".fpu neon \n\t" + "_op_copy_p_dp_neon_asmloop: \n\t" + "pld [%[s], #192] \n\t" // preload 256 bytes ahead + "pld [%[s], #320] \n\t" // preload 320 bytes ahead + "vld1.32 {d0-d3}, [%[s]]! \n\t" // load 256bits (32 bytes 8 pix), 32bit aligned + "vld1.32 {d4-d7} , [%[s]]! \n\t" // load 256bits (32 bytes 8 pix), 32bit aligned + "vld1.32 {d8-d11}, [%[s]]! \n\t" // load 256bits (32 bytes 8 pix), 32bit aligned + "vst1.32 {d0-d3}, [%[d]]! \n\t" // store 256bits (32 bytes 8 pix), 32bit aligned + "vst1.32 {d4-d7}, [%[d]]! \n\t" // store 256bits (32 bytes 8 pix), 32bit aligned + "vst1.32 {d8-d11}, [%[d]]! \n\t" // store 256bits (32 bytes 8 pix), 32bit aligned + "cmp %[e], %[d] \n\t" // compare current and end ptr + "bgt _op_copy_p_dp_neon_asmloop \n\t" + : /*out*/ + : /*in */ [s] "r" (s), [e] "r" (e), [d] "r" (d) + : /*clobber*/ + "q0", "q1", "q2","q3", "q4", "q5", "q6", + "d0", "d1", "d2", "d3", + "d4", "d5", "d6", "d7", + "d8", "d9", "d10", "d11", + "memory" // clobbered + ); + dl = l % 24; // dl is how many pixels at end that is not a multiple of 24 + l = l - dl; // jump to there at the end of the run? + s = s + l; + d = d + l; } - for (; d < e; d++, s++) { - *d = *s; - } - */ + e += 23; + for (;d < e; d++, s++) *d = *s; +#endif } #define _op_copy_pan_dp_neon _op_copy_p_dp_neon diff --git a/src/lib/engines/common/evas_pipe.c b/src/lib/engines/common/evas_pipe.c index fbe546b..bda94ee 100644 --- a/src/lib/engines/common/evas_pipe.c +++ b/src/lib/engines/common/evas_pipe.c @@ -1177,9 +1177,7 @@ evas_common_pipe_op_text_free(RGBA_Pipe_Op *op) #else evas_common_font_free(op->op.text.font); #endif -#ifdef BIDI_SUPPORT - evas_bidi_props_clean(&(op->op.text.intl_props)); -#endif + evas_common_text_props_content_unref(&(op->op.text.intl_props)); free(op->op.text.text); evas_common_pipe_op_free(op); } @@ -1230,7 +1228,7 @@ evas_common_pipe_text_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Threa EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, - RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) + RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_Text_Props *intl_props) { RGBA_Pipe_Op *op; @@ -1240,9 +1238,8 @@ evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, op->op.text.x = x; op->op.text.y = y; op->op.text.text = eina_unicode_strdup(text); -#ifdef BIDI_SUPPORT - evas_bidi_props_copy_and_ref(intl_props, &(op->op.text.intl_props)); -#endif + evas_common_text_props_content_copy_and_ref(&(op->op.text.intl_props), + intl_props); #ifdef EVAS_FRAME_QUEUING LKL(fn->ref_fq_add); fn->ref_fq[0]++; @@ -1443,23 +1440,23 @@ evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst, } static void -evas_common_pipe_op_map4_free(RGBA_Pipe_Op *op) +evas_common_pipe_op_map_free(RGBA_Pipe_Op *op) { #ifdef EVAS_FRAME_QUEUING LKL(op->op.image.src->cache_entry.ref_fq_del); op->op.image.src->cache_entry.ref_fq[1]++; LKU(op->op.image.src->cache_entry.ref_fq_del); #else - op->op.map4.src->ref--; - if (op->op.map4.src->ref == 0) - evas_cache_image_drop(&op->op.map4.src->cache_entry); + op->op.map.src->ref--; + if (op->op.map.src->ref == 0) + evas_cache_image_drop(&op->op.map.src->cache_entry); #endif - free(op->op.map4.p); + free(op->op.map.p); evas_common_pipe_op_free(op); } static void -evas_common_pipe_map4_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info) +evas_common_pipe_map_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info) { if (info) { @@ -1472,22 +1469,22 @@ evas_common_pipe_map4_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Threa evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h); #endif - evas_common_map4_rgba(op->op.map4.src, dst, - &context, op->op.map4.p, - op->op.map4.smooth, op->op.map4.level); + evas_common_map_rgba(op->op.map.src, dst, + &context, op->op.map.npoints, op->op.map.p, + op->op.map.smooth, op->op.map.level); } else { - evas_common_map4_rgba(op->op.map4.src, dst, - &(op->context), op->op.map4.p, - op->op.map4.smooth, op->op.map4.level); + evas_common_map_rgba(op->op.map.src, dst, + &(op->context), op->op.map.npoints, op->op.map.p, + op->op.map.smooth, op->op.map.level); } } EAPI void -evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst, - RGBA_Draw_Context *dc, RGBA_Map_Point *p, - int smooth, int level) +evas_common_pipe_map_draw(RGBA_Image *src, RGBA_Image *dst, + RGBA_Draw_Context *dc, int npoints, RGBA_Map_Point *p, + int smooth, int level) { RGBA_Pipe_Op *op; RGBA_Map_Point *pts_copy; @@ -1506,8 +1503,9 @@ evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst, for (i = 0; i < 4; ++i) pts_copy[i] = p[i]; - op->op.map4.smooth = smooth; - op->op.map4.level = level; + op->op.map.npoints = npoints; + op->op.map.smooth = smooth; + op->op.map.level = level; #ifdef EVAS_FRAME_QUEUING LKL(src->cache_entry.ref_fq_add); src->cache_entry.ref_fq[0]++; @@ -1515,10 +1513,10 @@ evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst, #else src->ref++; #endif - op->op.map4.src = src; - op->op.map4.p = pts_copy; - op->op_func = evas_common_pipe_map4_draw_do; - op->free_func = evas_common_pipe_op_map4_free; + op->op.map.src = src; + op->op.map.p = pts_copy; + op->op_func = evas_common_pipe_map_draw_do; + op->free_func = evas_common_pipe_op_map_free; evas_common_pipe_draw_context_copy(dc, op); #ifdef EVAS_FRAME_QUEUING @@ -1536,7 +1534,7 @@ evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst, } static void -evas_common_pipe_map4_render(RGBA_Image *root) +evas_common_pipe_map_render(RGBA_Image *root) { RGBA_Pipe *p; int i; @@ -1546,15 +1544,15 @@ evas_common_pipe_map4_render(RGBA_Image *root) { for (i = 0; i < p->op_num; i++) { - if (p->op[i].op_func == evas_common_pipe_map4_draw_do) + if (p->op[i].op_func == evas_common_pipe_map_draw_do) { - if (p->op[i].op.map4.src->cache_entry.pipe) - evas_common_pipe_map4_render(p->op[i].op.map4.src); + if (p->op[i].op.map.src->cache_entry.pipe) + evas_common_pipe_map_render(p->op[i].op.map.src); } else if (p->op[i].op_func == evas_common_pipe_image_draw_do) { if (p->op[i].op.image.src->cache_entry.pipe) - evas_common_pipe_map4_render(p->op[i].op.image.src); + evas_common_pipe_map_render(p->op[i].op.image.src); } } } @@ -1709,7 +1707,7 @@ evas_common_pipe_image_load(RGBA_Image *im) } EAPI void -evas_common_pipe_map4_begin(RGBA_Image *root) +evas_common_pipe_map_begin(RGBA_Image *root) { if (!evas_common_pipe_init()) { @@ -1727,7 +1725,7 @@ evas_common_pipe_map4_begin(RGBA_Image *root) evas_common_pipe_image_load_do(); - evas_common_pipe_map4_render(root); + evas_common_pipe_map_render(root); } #endif diff --git a/src/lib/engines/common/evas_pipe.h b/src/lib/engines/common/evas_pipe.h index de033f0..df7f673 100644 --- a/src/lib/engines/common/evas_pipe.h +++ b/src/lib/engines/common/evas_pipe.h @@ -1,6 +1,6 @@ #ifndef _EVAS_PIPE_H #define _EVAS_PIPE_H -#include "evas_bidi_utils.h" +#include "language/evas_bidi_utils.h" #ifdef BUILD_PTHREAD typedef struct _Thinfo @@ -92,12 +92,12 @@ EAPI void evas_common_pipe_free(RGBA_Image *im); EAPI void evas_common_pipe_rectangle_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h); EAPI void evas_common_pipe_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1); EAPI void evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points, int x, int y); -EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props); +EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_Text_Props *intl_props); EAPI void evas_common_pipe_image_load(RGBA_Image *im); EAPI void evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int smooth, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h); EAPI void evas_common_pipe_map_begin(RGBA_Image *root); EAPI void evas_common_pipe_map_draw(RGBA_Image *src, RGBA_Image *dst, - RGBA_Draw_Context *dc, RGBA_Map_Point *p, + RGBA_Draw_Context *dc, int npoints, RGBA_Map_Point *p, int smooth, int level); EAPI void evas_common_pipe_flush(RGBA_Image *im); diff --git a/src/lib/engines/common/evas_scale_smooth.c b/src/lib/engines/common/evas_scale_smooth.c index 00d3243..b8f392b 100644 --- a/src/lib/engines/common/evas_scale_smooth.c +++ b/src/lib/engines/common/evas_scale_smooth.c @@ -2,24 +2,24 @@ #include "evas_scale_smooth.h" #include "evas_blend_private.h" -#define SCALE_CALC_X_POINTS(P, SW, DW) \ - P = alloca((DW + 1) * sizeof (int)); \ - scale_calc_x_points(P, SW, DW); +#define SCALE_CALC_X_POINTS(P, SW, DW, CX, CW) \ + P = alloca((CW + 1) * sizeof (int)); \ + scale_calc_x_points(P, SW, DW, CX, CW); -#define SCALE_CALC_Y_POINTS(P, SRC, SW, SH, DH) \ - P = alloca((DH + 1) * sizeof (DATA32 *)); \ - scale_calc_y_points(P, SRC, SW, SH, DH); +#define SCALE_CALC_Y_POINTS(P, SRC, SW, SH, DH, CY, CH) \ + P = alloca((CH + 1) * sizeof (DATA32 *)); \ + scale_calc_y_points(P, SRC, SW, SH, DH, CY, CH); -#define SCALE_CALC_A_POINTS(P, S, D) \ - P = alloca(D * sizeof (int)); \ - scale_calc_a_points(P, S, D); +#define SCALE_CALC_A_POINTS(P, S, D, C, CC) \ + P = alloca(CC * sizeof (int)); \ + scale_calc_a_points(P, S, D, C, CC); -static void scale_calc_y_points(DATA32** p, DATA32 *src, int sw, int sh, int dh); -static void scale_calc_x_points(int *p, int sw, int dw); -static void scale_calc_a_points(int *p, int s, int d); +static void scale_calc_y_points(DATA32 **p, DATA32 *src, int sw, int sh, int dh, int cy, int ch); +static void scale_calc_x_points(int *p, int sw, int dw, int cx, int cw); +static void scale_calc_a_points(int *p, int s, int d, int c, int cc); static void -scale_calc_y_points(DATA32** p, DATA32 *src, int sw, int sh, int dh) +scale_calc_y_points(DATA32** p, DATA32 *src, int sw, int sh, int dh, int cy, int ch) { int i, val, inc; @@ -27,14 +27,16 @@ scale_calc_y_points(DATA32** p, DATA32 *src, int sw, int sh, int dh) inc = (sh << 16) / dh; for (i = 0; i < dh; i++) { - p[i] = src + ((val >> 16) * sw); + if ((i >= cy) && (i < (cy + ch))) + p[i - cy] = src + ((val >> 16) * sw); val += inc; } - p[i] = p[i - 1]; + if ((i >= cy) && (i < (cy + ch))) + p[i - cy] = p[i - cy - 1]; } static void -scale_calc_x_points(int *p, int sw, int dw) +scale_calc_x_points(int *p, int sw, int dw, int cx, int cw) { int i, val, inc; @@ -42,14 +44,16 @@ scale_calc_x_points(int *p, int sw, int dw) inc = (sw << 16) / dw; for (i = 0; i < dw; i++) { - p[i] = val >> 16; + if ((i >= cx) && (i < (cx + cw))) + p[i - cx] = val >> 16; val += inc; } - p[i] = p[i - 1]; + if ((i >= cx) && (i < (cx + cw))) + p[i - cx] = p[i - cx - 1]; } static void -scale_calc_a_points(int *p, int s, int d) +scale_calc_a_points(int *p, int s, int d, int c, int cc) { int i, val, inc; @@ -59,8 +63,11 @@ scale_calc_a_points(int *p, int s, int d) inc = (s << 16) / d; for (i = 0; i < d; i++) { - p[i] = (val >> 8) - ((val >> 8) & 0xffffff00); - if ((val >> 16) >= (s - 1)) p[i] = 0; + if ((i >= c) && (i < (c + cc))) + { + p[i - c] = (val >> 8) - ((val >> 8) & 0xffffff00); + if ((val >> 16) >= (s - 1)) p[i - c] = 0; + } val += inc; } } @@ -74,11 +81,11 @@ scale_calc_a_points(int *p, int s, int d) for (i = 0; i < d; i++) { ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8; - p[i] = ap | (Cp << 16); + if ((i >= c) && (i < (c + cc))) + p[i - c] = ap | (Cp << 16); val += inc; } } -// sleep(1); } #ifdef BUILD_SCALE_SMOOTH diff --git a/src/lib/engines/common/evas_scale_smooth_scaler.c b/src/lib/engines/common/evas_scale_smooth_scaler.c index d119411..599bfda 100644 --- a/src/lib/engines/common/evas_scale_smooth_scaler.c +++ b/src/lib/engines/common/evas_scale_smooth_scaler.c @@ -136,6 +136,12 @@ SCALE_FUNC(RGBA_Image *src, RGBA_Image *dst, } if (dst_clip_h <= 0) return; + /* some maximum region sizes to avoid insane calc point tables */ + if (dst_clip_w > 65536) return; + if (dst_clip_h > 65536) return; + if (dst_region_w > (65536 * 1024)) return; + if (dst_region_h > (65536 * 1024)) return; + /* figure out dst jump * NB: Unused currently, so commented out */ // dst_jump = dst_w - dst_clip_w; diff --git a/src/lib/engines/common/evas_scale_smooth_scaler_down.c b/src/lib/engines/common/evas_scale_smooth_scaler_down.c index 859f2f3..357eb32 100644 --- a/src/lib/engines/common/evas_scale_smooth_scaler_down.c +++ b/src/lib/engines/common/evas_scale_smooth_scaler_down.c @@ -8,20 +8,21 @@ RGBA_Gfx_Func func; src_data = src->image.data; - - SCALE_CALC_X_POINTS(xpoints, src_region_w, dst_region_w); - SCALE_CALC_Y_POINTS(ypoints, src_data, src_w, src_region_h, dst_region_h); - SCALE_CALC_A_POINTS(xapoints, src_region_w, dst_region_w); - SCALE_CALC_A_POINTS(yapoints, src_region_h, dst_region_h); - + + /* some maximum region sizes to avoid insane calc point tables */ + SCALE_CALC_X_POINTS(xpoints, src_region_w, dst_region_w, dst_clip_x - dst_region_x, dst_clip_w); + SCALE_CALC_Y_POINTS(ypoints, src_data, src_w, src_region_h, dst_region_h, dst_clip_y - dst_region_y, dst_clip_h); + SCALE_CALC_A_POINTS(xapoints, src_region_w, dst_region_w, dst_clip_x - dst_region_x, dst_clip_w); + SCALE_CALC_A_POINTS(yapoints, src_region_h, dst_region_h, dst_clip_y - dst_region_y, dst_clip_h); + /* a scanline buffer */ buf = alloca(dst_clip_w * sizeof(DATA32)); - + if (dc->mul.use) - func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, dst_clip_w, dc->render_op); + func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, dst_clip_w, dc->render_op); else - func = evas_common_gfx_func_composite_pixel_span_get(src, dst, dst_clip_w, dc->render_op); - /* scaling down vertically */ + func = evas_common_gfx_func_composite_pixel_span_get(src, dst, dst_clip_w, dc->render_op); + /* scaling down vertically */ if ((dst_region_w >= src_region_w) && (dst_region_h < src_region_h)) { @@ -29,13 +30,13 @@ } /* scaling down horizontally */ else if ((dst_region_w < src_region_w) && - (dst_region_h >= src_region_h)) + (dst_region_h >= src_region_h)) { #include "evas_scale_smooth_scaler_downx.c" } /* scaling down both vertically & horizontally */ else if ((dst_region_w < src_region_w) && - (dst_region_h < src_region_h)) + (dst_region_h < src_region_h)) { #include "evas_scale_smooth_scaler_downx_downy.c" } diff --git a/src/lib/engines/common/evas_scale_smooth_scaler_downx.c b/src/lib/engines/common/evas_scale_smooth_scaler_downx.c index 466135f..50b2e5c 100644 --- a/src/lib/engines/common/evas_scale_smooth_scaler_downx.c +++ b/src/lib/engines/common/evas_scale_smooth_scaler_downx.c @@ -14,10 +14,10 @@ dyy = dst_clip_y - dst_region_y; dxx = dst_clip_x - dst_region_x; - xp = xpoints + dxx; - yp = ypoints + dyy; - xapp = xapoints + dxx; - yapp = yapoints + dyy; + xp = xpoints;// + dxx; + yp = ypoints;// + dyy; + xapp = xapoints;// + dxx; + yapp = yapoints;// + dyy; pbuf = buf; if (src->cache_entry.flags.alpha) @@ -97,8 +97,8 @@ pbuf = buf; dptr += dst_w; dst_clip_w = w; yp++; yapp++; - xp = xpoints + dxx; - xapp = xapoints + dxx; + xp = xpoints;// + dxx; + xapp = xapoints;// + dxx; } } else @@ -175,8 +175,8 @@ dptr += dst_w; dst_clip_w = w; yp++; yapp++; - xp = xpoints + dxx; - xapp = xapoints + dxx; + xp = xpoints;// + dxx; + xapp = xapoints;// + dxx; } } else @@ -251,8 +251,8 @@ pbuf = buf; dptr += dst_w; dst_clip_w = w; yp++; yapp++; - xp = xpoints + dxx; - xapp = xapoints + dxx; + xp = xpoints;// + dxx; + xapp = xapoints;// + dxx; } } } diff --git a/src/lib/engines/common/evas_scale_smooth_scaler_downx_downy.c b/src/lib/engines/common/evas_scale_smooth_scaler_downx_downy.c index bfe47d7..ab0c74e 100644 --- a/src/lib/engines/common/evas_scale_smooth_scaler_downx_downy.c +++ b/src/lib/engines/common/evas_scale_smooth_scaler_downx_downy.c @@ -17,10 +17,10 @@ dyy = dst_clip_y - dst_region_y; dxx = dst_clip_x - dst_region_x; - xp = xpoints + dxx; - yp = ypoints + dyy; - xapp = xapoints + dxx; - yapp = yapoints + dyy; + xp = xpoints;// + dxx; + yp = ypoints;// + dyy; + xapp = xapoints;// + dxx; + yapp = yapoints;// + dyy; pbuf = buf; /*#ifndef SCALE_USING_MMX */ /* for now there's no mmx down scaling - so C only */ @@ -145,8 +145,8 @@ #endif pbuf = buf; dptr += dst_w; dst_clip_w = w; - xp = xpoints + dxx; - xapp = xapoints + dxx; + xp = xpoints;// + dxx; + xapp = xapoints;// + dxx; yp++; yapp++; } } @@ -261,8 +261,8 @@ ysli++; #endif dptr += dst_w; dst_clip_w = w; - xp = xpoints + dxx; - xapp = xapoints + dxx; + xp = xpoints;// + dxx; + xapp = xapoints;// + dxx; yp++; yapp++; } } @@ -375,8 +375,8 @@ #endif pbuf = buf; dptr += dst_w; dst_clip_w = w; - xp = xpoints + dxx; - xapp = xapoints + dxx; + xp = xpoints;// + dxx; + xapp = xapoints;// + dxx; yp++; yapp++; } } diff --git a/src/lib/engines/common/evas_scale_smooth_scaler_downy.c b/src/lib/engines/common/evas_scale_smooth_scaler_downy.c index a6cf34c..4c5448e 100644 --- a/src/lib/engines/common/evas_scale_smooth_scaler_downy.c +++ b/src/lib/engines/common/evas_scale_smooth_scaler_downy.c @@ -14,10 +14,10 @@ dyy = dst_clip_y - dst_region_y; dxx = dst_clip_x - dst_region_x; - xp = xpoints + dxx; - yp = ypoints + dyy; - xapp = xapoints + dxx; - yapp = yapoints + dyy; + xp = xpoints;// + dxx; + yp = ypoints;// + dyy; + xapp = xapoints;// + dxx; + yapp = yapoints;// + dyy; pbuf = buf; if (src->cache_entry.flags.alpha) @@ -98,8 +98,8 @@ pbuf = buf; dptr += dst_w; dst_clip_w = w; yp++; yapp++; - xp = xpoints + dxx; - xapp = xapoints + dxx; + xp = xpoints;// + dxx; + xapp = xapoints;// + dxx; } } else @@ -176,8 +176,8 @@ #endif dptr += dst_w; dst_clip_w = w; yp++; yapp++; - xp = xpoints + dxx; - xapp = xapoints + dxx; + xp = xpoints;// + dxx; + xapp = xapoints;// + dxx; } } else @@ -252,8 +252,8 @@ pbuf = buf; dptr += dst_w; dst_clip_w = w; yp++; yapp++; - xp = xpoints + dxx; - xapp = xapoints + dxx; + xp = xpoints;// + dxx; + xapp = xapoints;// + dxx; } } } diff --git a/src/lib/engines/common/evas_text_utils.c b/src/lib/engines/common/evas_text_utils.c new file mode 100644 index 0000000..ad1fd9b --- /dev/null +++ b/src/lib/engines/common/evas_text_utils.c @@ -0,0 +1,358 @@ +#include "evas_common.h" +#include "evas_font_private.h" +#include "evas_text_utils.h" +#include "language/evas_bidi_utils.h" +#include "language/evas_language_utils.h" +#include "evas_font_ot.h" + +/* Used for showing "malformed" or missing chars */ +#define REPLACEMENT_CHAR 0xFFFD + +void +evas_common_text_props_bidi_set(Evas_Text_Props *props, + Evas_BiDi_Paragraph_Props *bidi_par_props, size_t start) +{ +#ifdef BIDI_SUPPORT + props->bidi.dir = (evas_bidi_is_rtl_char( + bidi_par_props, + 0, + start)) ? EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR; +#else + (void) start; + (void) bidi_par_props; + props->bidi.dir = EVAS_BIDI_DIRECTION_LTR; +#endif +} + +void +evas_common_text_props_script_set(Evas_Text_Props *props, + const Eina_Unicode *str) +{ + props->script = evas_common_language_script_type_get(str); +} + +void +evas_common_text_props_content_copy_and_ref(Evas_Text_Props *dst, + const Evas_Text_Props *src) +{ + memcpy(dst, src, sizeof(Evas_Text_Props)); + evas_common_text_props_content_ref(dst); +} + +void +evas_common_text_props_content_ref(Evas_Text_Props *props) +{ + /* No content in this case */ + if (!props->info) + return; + + props->info->refcount++; +} + +void +evas_common_text_props_content_unref(Evas_Text_Props *props) +{ + /* No content in this case */ + if (!props->info) + return; + + if (--(props->info->refcount) == 0) + { + if (props->info->glyph) + free(props->info->glyph); +#ifdef OT_SUPPORT + if (props->info->ot) + free(props->info->ot); +#endif + free(props->info); + props->info = NULL; + } +} + +/* Won't work in the middle of ligatures, assumes cutoff < len */ +EAPI void +evas_common_text_props_split(Evas_Text_Props *base, + Evas_Text_Props *ext, int _cutoff) +{ + size_t cutoff; + + /* Translate text cutoff pos to string object cutoff point */ +#ifdef OT_SUPPORT + cutoff = 0; + + { + Evas_Font_OT_Info *itr; + size_t i; + itr = base->info->ot + base->start; + _cutoff += base->text_offset; + /* FIXME: can I binary search? I don't think this is always sorted */ + for (i = 0 ; i < base->len ; i++, itr++) + { + if (itr->source_cluster == (size_t) _cutoff) + { + if (base->bidi.dir == EVAS_BIDI_DIRECTION_RTL) + { + /* Walk to the last one of the same cluster */ + for ( ; i < base->len ; i++, itr++) + { + if (itr->source_cluster != (size_t) _cutoff) + break; + } + cutoff = base->len - i; + } + else + { + cutoff = i; + } + break; + } + } + } + + /* If we didn't find a reasonable cut location, return. */ + if (cutoff == 0) + { + ERR("Couldn't find the cutoff position. Is it inside a cluster?"); + return; + } +#else + cutoff = (size_t) _cutoff; +#endif + + evas_common_text_props_content_copy_and_ref(ext, base); + if (base->bidi.dir == EVAS_BIDI_DIRECTION_RTL) + { + ext->start = base->start; + ext->len = base->len - cutoff; + base->start = (base->start + base->len) - cutoff; + base->len = cutoff; + +#ifdef OT_SUPPORT + ext->text_offset = + ext->info->ot[ext->start + ext->len - 1].source_cluster; +#else + ext->text_offset = base->text_offset + base->len; +#endif + } + else + { + ext->start = base->start + cutoff; + ext->len = base->len - cutoff; + base->len = cutoff; + +#ifdef OT_SUPPORT + ext->text_offset = ext->info->ot[ext->start].source_cluster; +#else + ext->text_offset = base->text_offset + base->len; +#endif + } + ext->text_len = base->text_len - (ext->text_offset - base->text_offset); + base->text_len = (ext->text_offset - base->text_offset); +} + +/* Won't work in the middle of ligatures */ +EAPI void +evas_common_text_props_merge(Evas_Text_Props *item1, + const Evas_Text_Props *item2) +{ + if (item1->info != item2->info) + { + ERR("tried merge back items that weren't together in the first place."); + return; + } + if (item1->bidi.dir == EVAS_BIDI_DIRECTION_RTL) + { + item1->start = item2->start; + } + + item1->len += item2->len; + item1->text_len += item2->text_len; +} + +EAPI Eina_Bool +evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, + Evas_Text_Props *text_props, int len) +{ + RGBA_Font *fn = (RGBA_Font *) _fn; + RGBA_Font_Int *fi; + size_t char_index; + + if (text_props->info) + { + evas_common_text_props_content_unref(text_props); + } + if (len == 0) + { + text_props->info = NULL; + text_props->start = text_props->len = text_props->text_offset = 0; + } + text_props->info = calloc(1, sizeof(Evas_Text_Props_Info)); + + fi = fn->fonts->data; + /* evas_common_font_size_use(fn); */ + evas_common_font_int_reload(fi); + if (fi->src->current_size != fi->size) + { + FTLOCK(); + FT_Activate_Size(fi->ft.size); + FTUNLOCK(); + fi->src->current_size = fi->size; + } + +#ifdef OT_SUPPORT + const Eina_Unicode *base_char; + evas_common_font_ot_populate_text_props(fn, text, text_props, len); + + /* Load the glyph according to the first letter of the script, preety + * bad, but will have to do */ + { + /* Skip common chars */ + for (base_char = text ; + *base_char && + evas_common_language_char_script_get(*base_char) == + EVAS_SCRIPT_COMMON ; + base_char++) + ; + if (!*base_char && (base_char > text)) base_char--; + evas_common_font_glyph_search(fn, &fi, *base_char); + } + + for (char_index = 0 ; char_index < text_props->len ; char_index++) + { + FT_UInt index; + RGBA_Font_Glyph *fg; + Eina_Bool is_replacement = EINA_FALSE; + /* If we got a malformed index, show the replacement char instead */ + if (text_props->info->glyph[char_index].index == 0) + { + text_props->info->glyph[char_index].index = + evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR); + is_replacement = EINA_TRUE; + } + index = text_props->info->glyph[char_index].index; + LKL(fi->ft_mutex); + fg = evas_common_font_int_cache_glyph_get(fi, index); + if (!fg) + { + LKU(fi->ft_mutex); + continue; + } + LKU(fi->ft_mutex); + if (is_replacement) + { + /* Update the advance accordingly */ + text_props->info->glyph[char_index].advance = + fg->glyph->advance.x >> 10; + /* FIXME: reload fi, a bit slow, but I have no choice. */ + evas_common_font_glyph_search(fn, &fi, *base_char); + } + text_props->info->glyph[char_index].x_bear = + fg->glyph_out->left; + text_props->info->glyph[char_index].width = + fg->glyph_out->bitmap.width; + /* text_props->info->glyph[char_index].advance = + * text_props->info->glyph[char_index].index = + * already done by the ot function */ + if (EVAS_FONT_CHARACTER_IS_INVISIBLE( + text[text_props->info->ot[char_index].source_cluster])) + text_props->info->glyph[char_index].index = 0; + + } +#else + /* We are walking the string in visual ordering */ + Eina_Bool use_kerning; + FT_UInt prev_index; + FT_Face pface = NULL; + int adv_d, i; + FTLOCK(); + use_kerning = FT_HAS_KERNING(fi->src->ft.face); + FTUNLOCK(); + prev_index = 0; + + i = len; + text_props->info->glyph = calloc(len, + sizeof(Evas_Font_Glyph_Info)); + + if (text_props->bidi.dir == EVAS_BIDI_DIRECTION_RTL) + { + text += len - 1; + adv_d = -1; + } + else + { + adv_d = 1; + } + char_index = 0; + for ( ; i > 0 ; char_index++, text += adv_d, i--) + { + FT_UInt index; + RGBA_Font_Glyph *fg; + int _gl, kern; + _gl = *text; + if (_gl == 0) break; + + index = evas_common_font_glyph_search(fn, &fi, _gl); + if (index == 0) + { + index = evas_common_font_glyph_search(fn, &fi, REPLACEMENT_CHAR); + } + LKL(fi->ft_mutex); + fg = evas_common_font_int_cache_glyph_get(fi, index); + if (!fg) + { + LKU(fi->ft_mutex); + continue; + } + kern = 0; + + if ((use_kerning) && (prev_index) && (index) && + (pface == fi->src->ft.face)) + { +# ifdef BIDI_SUPPORT + /* if it's rtl, the kerning matching should be reversed, */ + /* i.e prev index is now the index and the other way */ + /* around. There is a slight exception when there are */ + /* compositing chars involved.*/ + if (text_props && + (text_props->bidi.dir != EVAS_BIDI_DIRECTION_RTL)) + { + if (evas_common_font_query_kerning(fi, index, prev_index, &kern)) + { + text_props->info->glyph[char_index - 1].advance += + kern; + } + } + else +# endif + { + if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) + { + text_props->info->glyph[char_index - 1].advance += + kern; + } + } + } + + pface = fi->src->ft.face; + LKU(fi->ft_mutex); + + if (EVAS_FONT_CHARACTER_IS_INVISIBLE(_gl)) + text_props->info->glyph[char_index].index = 0; + + text_props->info->glyph[char_index].index = index; + text_props->info->glyph[char_index].x_bear = + fg->glyph_out->left; + text_props->info->glyph[char_index].advance = + fg->glyph->advance.x >> 10; + text_props->info->glyph[char_index].width = + fg->glyph_out->bitmap.width; + + prev_index = index; + } + text_props->len = len; +#endif + text_props->text_len = len; + text_props->info->refcount = 1; + return EINA_TRUE; +} + diff --git a/src/lib/engines/common/evas_text_utils.h b/src/lib/engines/common/evas_text_utils.h new file mode 100644 index 0000000..e4907ab --- /dev/null +++ b/src/lib/engines/common/evas_text_utils.h @@ -0,0 +1,76 @@ +#ifndef _EVAS_TEXT_UTILS_H +# define _EVAS_TEXT_UTILS_H + +typedef struct _Evas_Text_Props Evas_Text_Props; +typedef struct _Evas_Text_Props_Info Evas_Text_Props_Info; +typedef struct _Evas_Font_Glyph_Info Evas_Font_Glyph_Info; + +# include "evas_font_ot.h" +# include "language/evas_bidi_utils.h" +# include "language/evas_language_utils.h" + +struct _Evas_Text_Props +{ + /* Start and len represent the start offset and the length in the + * glyphs_info and ot_data fields, they are both internal */ + size_t start; + size_t len; + size_t text_offset; /* The text offset from the start of the info */ + size_t text_len; /* The length of the original text */ + Evas_BiDi_Props bidi; + Evas_Script_Type script; + Evas_Text_Props_Info *info; +}; + +struct _Evas_Text_Props_Info +{ + unsigned int refcount; + Evas_Font_Glyph_Info *glyph; + Evas_Font_OT_Info *ot; +}; + +/* Sorted in visual order when created */ +struct _Evas_Font_Glyph_Info +{ + unsigned int index; /* Should conform to FT */ + Evas_Coord x_bear; +#if 0 + /* This one is rarely used, only in draw, in which we already get the glyph + * so it doesn't really save time. Leaving it here just so no one will + * add it thinking it was accidentally skipped */ + Evas_Coord y_bear; +#endif + Evas_Coord width; + Evas_Coord advance; +}; + + +void +evas_common_text_props_bidi_set(Evas_Text_Props *props, + Evas_BiDi_Paragraph_Props *bidi_par_props, size_t start); + +void +evas_common_text_props_script_set(Evas_Text_Props *props, + const Eina_Unicode *str); + +EAPI Eina_Bool +evas_common_text_props_content_create(void *_fn, const Eina_Unicode *text, + Evas_Text_Props *text_props, int len); + +void +evas_common_text_props_content_copy_and_ref(Evas_Text_Props *dst, + const Evas_Text_Props *src); + +void +evas_common_text_props_content_ref(Evas_Text_Props *props); + +void +evas_common_text_props_content_unref(Evas_Text_Props *props); + + +EAPI void +evas_common_text_props_split(Evas_Text_Props *base, Evas_Text_Props *ext, + int cutoff); +EAPI void +evas_common_text_props_merge(Evas_Text_Props *item1, const Evas_Text_Props *item2); +#endif diff --git a/src/lib/engines/common/evas_bidi_utils.c b/src/lib/engines/common/language/evas_bidi_utils.c similarity index 73% rename from src/lib/engines/common/evas_bidi_utils.c rename to src/lib/engines/common/language/evas_bidi_utils.c index ed83fe5..52964a4 100644 --- a/src/lib/engines/common/evas_bidi_utils.c +++ b/src/lib/engines/common/language/evas_bidi_utils.c @@ -3,7 +3,6 @@ #include "evas_common.h" #include "evas_bidi_utils.h" -#include "evas_encoding.h" #include "evas_font_private.h" @@ -92,15 +91,16 @@ evas_bidi_is_rtl_str(const Eina_Unicode *str) * * @param str The string to shape * @param bidi_props the bidi props to shaped according. + * @param start the start of the string to shape (offset in bidi_props) * @param len the length of th string. * @return #EINA_TRUE on success, #EINA_FALSE otherwise. */ -Eina_Bool -evas_bidi_shape_string(Eina_Unicode *eina_ustr, const Evas_BiDi_Props *bidi_props, size_t len) +EAPI Eina_Bool +evas_bidi_shape_string(Eina_Unicode *eina_ustr, const Evas_BiDi_Paragraph_Props *bidi_props, size_t start, size_t len) { FriBidiChar *ustr, *base_ustr = NULL; - if (!bidi_props->props) + if (!bidi_props) return EINA_FALSE; /* The size of fribidichar is different than eina_unicode, convert */ @@ -126,12 +126,13 @@ evas_bidi_shape_string(Eina_Unicode *eina_ustr, const Evas_BiDi_Props *bidi_prop } fribidi_get_joining_types(ustr, len, join_types); - fribidi_join_arabic(bidi_props->props->char_types + bidi_props->start, len, bidi_props->props->embedding_levels + bidi_props->start, join_types); + fribidi_join_arabic(bidi_props->char_types + start, len, + bidi_props->embedding_levels + start, join_types); /* Actually modify the string */ fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC, - bidi_props->props->embedding_levels + bidi_props->start, len, join_types, ustr); + bidi_props->embedding_levels + start, len, join_types, ustr); if (join_types) free(join_types); @@ -167,6 +168,11 @@ evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr) return NULL; + if (!evas_bidi_is_rtl_str(eina_ustr)) /* No need to handle bidi */ + { + len = -1; + goto cleanup; + } len = eina_unicode_strlen(eina_ustr); /* The size of fribidichar s different than eina_unicode, convert */ @@ -181,13 +187,6 @@ evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr) ustr = (const FriBidiChar *) eina_ustr; } - - if (!evas_bidi_is_rtl_str(eina_ustr)) /* No need to handle bidi */ - { - len = -1; - goto cleanup; - } - bidi_props = evas_bidi_paragraph_props_new(); /* Prep work for reordering */ @@ -251,8 +250,7 @@ cleanup: void evas_bidi_props_copy_and_ref(const Evas_BiDi_Props *src, Evas_BiDi_Props *dst) { - dst->start = src->start; - dst->props = evas_bidi_paragraph_props_ref(src->props); + dst->dir = src->dir; } /** @@ -260,30 +258,33 @@ evas_bidi_props_copy_and_ref(const Evas_BiDi_Props *src, Evas_BiDi_Props *dst) * Reorders ustr according to the bidi props. * * @param ustr the string to reorder. - Null is ok, will just populate the map. - * @param intl_props the intl properties to rerorder according to. + * @param start the start of the line + * @param len the length of the line + * @param props the paragraph props to reorder according to * @param _v_to_l The visual to logical map to populate - if NULL it won't populate it. * @return #EINA_FALSE on success, #EINA_TRUE on error. */ Eina_Bool -evas_bidi_props_reorder_line(Eina_Unicode *eina_ustr, const Evas_BiDi_Props *intl_props, EvasBiDiStrIndex **_v_to_l) +evas_bidi_props_reorder_line(Eina_Unicode *eina_ustr, size_t start, size_t len, const Evas_BiDi_Paragraph_Props *props, EvasBiDiStrIndex **_v_to_l) { EvasBiDiStrIndex *v_to_l = NULL; - FriBidiChar *ustr, *base_ustr = NULL; - size_t len; + FriBidiChar *ustr = NULL, *base_ustr = NULL; - if (!intl_props->props) + if (!props) return EINA_FALSE; - len = eina_unicode_strlen(eina_ustr); - /* The size of fribidichar is different than eina_unicode, convert */ - if (sizeof(Eina_Unicode) != sizeof(FriBidiChar)) + if (eina_ustr) { - base_ustr = ustr = calloc(len + 1, sizeof(FriBidiChar)); - ustr = _evas_bidi_unicode_to_fribidichar(ustr, eina_ustr); - } - else - { - ustr = (FriBidiChar *) eina_ustr; + /* The size of fribidichar is different than eina_unicode, convert */ + if (sizeof(Eina_Unicode) != sizeof(FriBidiChar)) + { + base_ustr = ustr = calloc(len + 1, sizeof(FriBidiChar)); + ustr = _evas_bidi_unicode_to_fribidichar(ustr, eina_ustr); + } + else + { + ustr = (FriBidiChar *) eina_ustr; + } } @@ -303,20 +304,28 @@ evas_bidi_props_reorder_line(Eina_Unicode *eina_ustr, const Evas_BiDi_Props *int /* Shaping must be done *BEFORE* breaking to lines so there's no choice but doing it in textblock. */ - if (!fribidi_reorder_line (FRIBIDI_FLAGS_DEFAULT, - intl_props->props->char_types + intl_props->start, - len, 0, intl_props->props->direction, - intl_props->props->embedding_levels + intl_props->start, - ustr, v_to_l)) { - goto error; + /* FIXME: Hack around fribidi altering embedding_levels */ + EvasBiDiLevel *emb_lvl; + emb_lvl = malloc(len * sizeof(EvasBiDiLevel)); + memcpy(emb_lvl, props->embedding_levels, len * sizeof(EvasBiDiLevel)); + if (!fribidi_reorder_line (FRIBIDI_FLAGS_DEFAULT, + props->char_types + start, + len, 0, props->direction, + emb_lvl, + ustr, v_to_l)) + { + free(emb_lvl); + goto error; + } + free(emb_lvl); } /* The size of fribidichar is different than eina_unicode, convert */ if (sizeof(Eina_Unicode) != sizeof(FriBidiChar)) { - eina_ustr = _evas_bidi_fribidichar_to_unicode(eina_ustr, base_ustr); + _evas_bidi_fribidichar_to_unicode(eina_ustr, base_ustr); free(base_ustr); } return EINA_FALSE; @@ -327,6 +336,37 @@ error: return EINA_TRUE; } +/** + * @internal + * Returns the end of the current run of text + * + * @param bidi_props the paragraph properties + * @param start where to start looking from + * @param len the length of the string + * @return the position of the end of the run (offset from + * bidi_props->props->start), 0 when there is no end (i.e all the text) + */ +int +evas_bidi_end_of_run_get(const Evas_BiDi_Paragraph_Props *bidi_props, + size_t start, int len) +{ + EvasBiDiLevel *i; + EvasBiDiLevel base; + + if (!bidi_props || (len <= 0)) + return 0; + + i = bidi_props->embedding_levels + start; + base = *i; + for ( ; (len > 0) && (base == *i) ; len--, i++) + ; + + if (len == 0) + { + return 0; + } + return i - (bidi_props->embedding_levels + start); +} /** * @internal @@ -357,20 +397,39 @@ evas_bidi_position_logical_to_visual(EvasBiDiStrIndex *v_to_l, int len, EvasBiDi /** * @internal + * Returns the reversed pos of the index. + * + * @param dir the direction of the string + * @param len the length of the map. + * @param position the position to convert. + * @return on success the visual position, on failure the same position. + */ +EvasBiDiStrIndex +evas_bidi_position_reverse(const Evas_BiDi_Props *props, int len, EvasBiDiStrIndex position) +{ + if (!props || position >= len) + return position; + + return (props->dir == EVAS_BIDI_DIRECTION_RTL) ? (len - 1) - position : position; +} + +/** + * @internal * Checks if the char is rtl oriented. I.e even a neutral char can become rtl * if surrounded by rtl chars. * - * @param bidi_props The bidi properties - * @param index the index of the string. + * @param bidi_props The bidi paragraph properties + * @param start the base position + * @param index the offset from the base position. * @return #EINA_TRUE if true, #EINA_FALSE otherwise. */ Eina_Bool -evas_bidi_is_rtl_char(const Evas_BiDi_Props *bidi_props, EvasBiDiStrIndex index) +evas_bidi_is_rtl_char(const Evas_BiDi_Paragraph_Props *bidi_props, size_t start, EvasBiDiStrIndex index) { - if(!bidi_props || !bidi_props->props || index < 0) + if(!bidi_props || index < 0) return EINA_FALSE; return (FRIBIDI_IS_RTL( - bidi_props->props->embedding_levels[index + bidi_props->start])) + bidi_props->embedding_levels[index + start])) ? EINA_TRUE : EINA_FALSE; } @@ -446,8 +505,7 @@ void evas_bidi_props_clean(Evas_BiDi_Props *bidi_props) { if (!bidi_props) return; - evas_bidi_paragraph_props_unref(bidi_props->props); - bidi_props->props = NULL; + bidi_props->dir = EVAS_BIDI_DIRECTION_NATURAL; } /** * @} diff --git a/src/lib/engines/common/evas_bidi_utils.h b/src/lib/engines/common/language/evas_bidi_utils.h similarity index 83% rename from src/lib/engines/common/evas_bidi_utils.h rename to src/lib/engines/common/language/evas_bidi_utils.h index 86a83f1..971c2c4 100644 --- a/src/lib/engines/common/evas_bidi_utils.h +++ b/src/lib/engines/common/language/evas_bidi_utils.h @@ -26,7 +26,6 @@ #endif #include -#include "evas_common.h" #ifdef USE_FRIBIDI # include @@ -39,6 +38,8 @@ * these types in function declarations. Defining as void should help ensuring that. */ +/* Evas_BiDi_Direction is defined in evas.h */ + #ifdef USE_FRIBIDI # define _EVAS_BIDI_TYPEDEF(type) \ typedef FriBidi ## type EvasBiDi ## type @@ -73,9 +74,10 @@ struct _Evas_BiDi_Paragraph_Props { #endif }; -struct _Evas_BiDi_Props { - Evas_BiDi_Paragraph_Props *props; - size_t start; +#include "Evas.h" +struct _Evas_BiDi_Props +{ + Evas_BiDi_Direction dir; }; @@ -102,14 +104,20 @@ struct _Evas_BiDi_Props { EvasBiDiStrIndex evas_bidi_position_logical_to_visual(EvasBiDiStrIndex *v_to_l, int len, EvasBiDiStrIndex position); +EvasBiDiStrIndex +evas_bidi_position_reverse(const Evas_BiDi_Props *props, int len, EvasBiDiStrIndex position); + Eina_Bool evas_bidi_is_rtl_str(const Eina_Unicode *str); Eina_Bool -evas_bidi_is_rtl_char(const Evas_BiDi_Props *bidi_props, EvasBiDiStrIndex index); +evas_bidi_is_rtl_char(const Evas_BiDi_Paragraph_Props *bidi_props, size_t start, EvasBiDiStrIndex index); + +int +evas_bidi_end_of_run_get(const Evas_BiDi_Paragraph_Props *bidi_props, size_t start, int len); Eina_Bool -evas_bidi_props_reorder_line(Eina_Unicode *text, const Evas_BiDi_Props *intl_props, EvasBiDiStrIndex **_v_to_l); +evas_bidi_props_reorder_line(Eina_Unicode *eina_ustr, size_t start, size_t len, const Evas_BiDi_Paragraph_Props *props, EvasBiDiStrIndex **_v_to_l); Evas_BiDi_Paragraph_Props * evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr) EINA_ARG_NONNULL(1) EINA_MALLOC EINA_WARN_UNUSED_RESULT; @@ -117,8 +125,8 @@ evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr) EINA_ARG_NONNULL(1) void evas_bidi_props_copy_and_ref(const Evas_BiDi_Props *src, Evas_BiDi_Props *dst); -Eina_Bool -evas_bidi_shape_string(Eina_Unicode *ustr, const Evas_BiDi_Props *intl_props, size_t len); +EAPI Eina_Bool +evas_bidi_shape_string(Eina_Unicode *eina_ustr, const Evas_BiDi_Paragraph_Props *bidi_props, size_t start, size_t len); void evas_bidi_props_clean(Evas_BiDi_Props *intl_props) EINA_ARG_NONNULL(1); diff --git a/src/lib/engines/common/language/evas_language_utils.c b/src/lib/engines/common/language/evas_language_utils.c new file mode 100644 index 0000000..2bdd53e --- /dev/null +++ b/src/lib/engines/common/language/evas_language_utils.c @@ -0,0 +1,147 @@ +/** + * @internal + * @addtogroup Evas_Utils + * + * @{ + */ +/** + * @internal + * @defgroup Evas_Script Evas Script (language) utility functions + * + * This set of functions and types helps evas handle scripts correctly. + * @todo Document types, structures and macros. + * + * @{ + */ +#include + +#include "evas_language_utils.h" +#include "evas_bidi_utils.h" /* Used for fallback. */ +#include "../evas_font_ot.h" /* Used for harfbuzz info */ + +#ifdef USE_HARFBUZZ +# include +# ifdef HAVE_HARFBUZZ_GLIB +# include +# endif +#endif + +/* FIXME: rename and move */ +void * +evas_common_language_unicode_funcs_get(void) +{ +#if defined(USE_HARFBUZZ) && defined(HAVE_HARFBUZZ_GLIB) + return hb_glib_get_unicode_funcs(); +#endif + return NULL; +} + +Evas_Script_Type +evas_common_language_char_script_get(Eina_Unicode unicode) +{ +#ifdef USE_HARFBUZZ + static hb_unicode_funcs_t *funcs; + if (!funcs) + funcs = evas_common_language_unicode_funcs_get(); + return hb_unicode_get_script(funcs, unicode); +#else + (void) unicode; +#endif + return EVAS_SCRIPT_COMMON; +} + +int +evas_common_language_script_end_of_run_get(const Eina_Unicode *str, + const Evas_BiDi_Paragraph_Props *bidi_props, size_t start, int len) +{ + /* FIXME: Use the standard segmentation instead */ +#ifdef OT_SUPPORT + Evas_Script_Type first = EVAS_SCRIPT_UNKNOWN; + int i; + for (i = 0 ; i < len ; i++, str++) + { + Evas_Script_Type tmp; + tmp = evas_common_language_char_script_get(*str); + /* Arabic is the first script in the array that's not + * common/inherited. */ + if ((first == EVAS_SCRIPT_UNKNOWN) && (tmp >= EVAS_SCRIPT_ARABIC)) + { + first = tmp; + continue; + } + if ((first != tmp) && (tmp >= EVAS_SCRIPT_ARABIC)) + { + break; + } + } +# ifdef BIDI_SUPPORT + { + int bidi_end; + bidi_end = evas_bidi_end_of_run_get(bidi_props, start, len); + if (bidi_end > 0) + { + i = (i < bidi_end) ? i : bidi_end; + } + } +# else + (void) bidi_props; + (void) start; +# endif + return (i < len) ? i : 0; +#elif defined(BIDI_SUPPORT) + (void) str; + return evas_bidi_end_of_run_get(bidi_props, start, len); +#else + (void) bidi_props; + (void) start; + (void) str; + (void) len; + return 0; +#endif +} + +Evas_Script_Type +evas_common_language_script_type_get(const Eina_Unicode *str) +{ + Evas_Script_Type script = EVAS_SCRIPT_COMMON; + /* Arabic is the first script in the array that's not a common/inherited */ + for ( ; *str && ((script = evas_common_language_char_script_get(*str)) < EVAS_SCRIPT_ARABIC) ; str++) + ; + return script; +} + +const char * +evas_common_language_from_locale_get(void) +{ + static char lang[6]; /* FIXME: Maximum length I know about */ + if (*lang) return lang; + + const char *locale; + locale = getenv("LANG"); + if (locale && *locale) + { + char *itr; + strncpy(lang, locale, 5); + lang[5] = '\0'; + itr = lang; + while (*itr) + { + if (*itr == '_') + { + *itr = '\0'; + } + itr++; + } + return lang; + } + + return ""; +} + +/* + * @} + */ +/* + * @} + */ + diff --git a/src/lib/engines/common/language/evas_language_utils.h b/src/lib/engines/common/language/evas_language_utils.h new file mode 100644 index 0000000..0993fd6 --- /dev/null +++ b/src/lib/engines/common/language/evas_language_utils.h @@ -0,0 +1,131 @@ +#ifndef _EVAS_LANGUAGE_UTILS +#define _EVAS_LANGUAGE_UTILS + +#include +#include "evas_bidi_utils.h" + +/* Unicode Script property - conforming to HARFBUZZ's */ +typedef enum +{ + EVAS_SCRIPT_INVALID_CODE = -1, + EVAS_SCRIPT_COMMON = 0, /* Zyyy */ + EVAS_SCRIPT_INHERITED, /* Qaai */ + EVAS_SCRIPT_ARABIC, /* Arab */ + EVAS_SCRIPT_ARMENIAN, /* Armn */ + EVAS_SCRIPT_BENGALI, /* Beng */ + EVAS_SCRIPT_BOPOMOFO, /* Bopo */ + EVAS_SCRIPT_CHEROKEE, /* Cher */ + EVAS_SCRIPT_COPTIC, /* Qaac */ + EVAS_SCRIPT_CYRILLIC, /* Cyrl (Cyrs) */ + EVAS_SCRIPT_DESERET, /* Dsrt */ + EVAS_SCRIPT_DEVANAGARI, /* Deva */ + EVAS_SCRIPT_ETHIOPIC, /* Ethi */ + EVAS_SCRIPT_GEORGIAN, /* Geor (Geon, Geoa) */ + EVAS_SCRIPT_GOTHIC, /* Goth */ + EVAS_SCRIPT_GREEK, /* Grek */ + EVAS_SCRIPT_GUJARATI, /* Gujr */ + EVAS_SCRIPT_GURMUKHI, /* Guru */ + EVAS_SCRIPT_HAN, /* Hani */ + EVAS_SCRIPT_HANGUL, /* Hang */ + EVAS_SCRIPT_HEBREW, /* Hebr */ + EVAS_SCRIPT_HIRAGANA, /* Hira */ + EVAS_SCRIPT_KANNADA, /* Knda */ + EVAS_SCRIPT_KATAKANA, /* Kana */ + EVAS_SCRIPT_KHMER, /* Khmr */ + EVAS_SCRIPT_LAO, /* Laoo */ + EVAS_SCRIPT_LATIN, /* Latn (Latf, Latg) */ + EVAS_SCRIPT_MALAYALAM, /* Mlym */ + EVAS_SCRIPT_MONGOLIAN, /* Mong */ + EVAS_SCRIPT_MYANMAR, /* Mymr */ + EVAS_SCRIPT_OGHAM, /* Ogam */ + EVAS_SCRIPT_OLD_ITALIC, /* Ital */ + EVAS_SCRIPT_ORIYA, /* Orya */ + EVAS_SCRIPT_RUNIC, /* Runr */ + EVAS_SCRIPT_SINHALA, /* Sinh */ + EVAS_SCRIPT_SYRIAC, /* Syrc (Syrj, Syrn, Syre) */ + EVAS_SCRIPT_TAMIL, /* Taml */ + EVAS_SCRIPT_TELUGU, /* Telu */ + EVAS_SCRIPT_THAANA, /* Thaa */ + EVAS_SCRIPT_THAI, /* Thai */ + EVAS_SCRIPT_TIBETAN, /* Tibt */ + EVAS_SCRIPT_CANADIAN_ABORIGINAL, /* Cans */ + EVAS_SCRIPT_YI, /* Yiii */ + EVAS_SCRIPT_TAGALOG, /* Tglg */ + EVAS_SCRIPT_HANUNOO, /* Hano */ + EVAS_SCRIPT_BUHID, /* Buhd */ + EVAS_SCRIPT_TAGBANWA, /* Tagb */ + + /* Unicode-4.0 additions */ + EVAS_SCRIPT_BRAILLE, /* Brai */ + EVAS_SCRIPT_CYPRIOT, /* Cprt */ + EVAS_SCRIPT_LIMBU, /* Limb */ + EVAS_SCRIPT_OSMANYA, /* Osma */ + EVAS_SCRIPT_SHAVIAN, /* Shaw */ + EVAS_SCRIPT_LINEAR_B, /* Linb */ + EVAS_SCRIPT_TAI_LE, /* Tale */ + EVAS_SCRIPT_UGARITIC, /* Ugar */ + + /* Unicode-4.1 additions */ + EVAS_SCRIPT_NEW_TAI_LUE, /* Talu */ + EVAS_SCRIPT_BUGINESE, /* Bugi */ + EVAS_SCRIPT_GLAGOLITIC, /* Glag */ + EVAS_SCRIPT_TIFINAGH, /* Tfng */ + EVAS_SCRIPT_SYLOTI_NAGRI, /* Sylo */ + EVAS_SCRIPT_OLD_PERSIAN, /* Xpeo */ + EVAS_SCRIPT_KHAROSHTHI, /* Khar */ + + /* Unicode-5.0 additions */ + EVAS_SCRIPT_UNKNOWN, /* Zzzz */ + EVAS_SCRIPT_BALINESE, /* Bali */ + EVAS_SCRIPT_CUNEIFORM, /* Xsux */ + EVAS_SCRIPT_PHOENICIAN, /* Phnx */ + EVAS_SCRIPT_PHAGS_PA, /* Phag */ + EVAS_SCRIPT_NKO, /* Nkoo */ + + /* Unicode-5.1 additions */ + EVAS_SCRIPT_KAYAH_LI, /* Kali */ + EVAS_SCRIPT_LEPCHA, /* Lepc */ + EVAS_SCRIPT_REJANG, /* Rjng */ + EVAS_SCRIPT_SUNDANESE, /* Sund */ + EVAS_SCRIPT_SAURASHTRA, /* Saur */ + EVAS_SCRIPT_CHAM, /* Cham */ + EVAS_SCRIPT_OL_CHIKI, /* Olck */ + EVAS_SCRIPT_VAI, /* Vaii */ + EVAS_SCRIPT_CARIAN, /* Cari */ + EVAS_SCRIPT_LYCIAN, /* Lyci */ + EVAS_SCRIPT_LYDIAN, /* Lydi */ + + /* Unicode-5.2 additions */ + EVAS_SCRIPT_AVESTAN, /* Avst */ + EVAS_SCRIPT_BAMUM, /* Bamu */ + EVAS_SCRIPT_EGYPTIAN_HIEROGLYPHS, /* Egyp */ + EVAS_SCRIPT_IMPERIAL_ARAMAIC, /* Armi */ + EVAS_SCRIPT_INSCRIPTIONAL_PAHLAVI, /* Phli */ + EVAS_SCRIPT_INSCRIPTIONAL_PARTHIAN, /* Prti */ + EVAS_SCRIPT_JAVANESE, /* Java */ + EVAS_SCRIPT_KAITHI, /* Kthi */ + EVAS_SCRIPT_LISU, /* Lisu */ + EVAS_SCRIPT_MEITEI_MAYEK, /* Mtei */ + EVAS_SCRIPT_OLD_SOUTH_ARABIAN, /* Sarb */ + EVAS_SCRIPT_OLD_TURKIC, /* Orkh */ + EVAS_SCRIPT_SAMARITAN, /* Samr */ + EVAS_SCRIPT_TAI_THAM, /* Lana */ + EVAS_SCRIPT_TAI_VIET /* Tavt */ +} Evas_Script_Type; + +int +evas_common_language_script_end_of_run_get(const Eina_Unicode *str, const Evas_BiDi_Paragraph_Props *bidi_props, size_t start, int len); + +Evas_Script_Type +evas_common_language_script_type_get(const Eina_Unicode *str); + +Evas_Script_Type +evas_common_language_char_script_get(Eina_Unicode unicode); + +const char * +evas_common_language_from_locale_get(void); + +void * +evas_common_language_unicode_funcs_get(void); +#endif + diff --git a/src/lib/file/evas_module.c b/src/lib/file/evas_module.c index a70ea64..4e37f1a 100644 --- a/src/lib/file/evas_module.c +++ b/src/lib/file/evas_module.c @@ -246,7 +246,7 @@ static const struct { #ifdef EVAS_STATIC_BUILD_EET EVAS_EINA_STATIC_MODULE_USE(image_saver, eet), #endif -#ifdef EVAS_STATIC_BUILD_JPEG +#if defined (EVAS_BUILD_SAVER_JPEG) && defined (EVAS_STATIC_BUILD_JPEG) EVAS_EINA_STATIC_MODULE_USE(image_saver, jpeg), #endif #ifdef EVAS_STATIC_BUILD_PNG diff --git a/src/lib/include/evas_common.h b/src/lib/include/evas_common.h index b975cbf..6e9cb6d 100644 --- a/src/lib/include/evas_common.h +++ b/src/lib/include/evas_common.h @@ -49,10 +49,6 @@ extern EAPI int _evas_log_dom_global; #endif #define CRIT(...) EINA_LOG_DOM_CRIT(_EVAS_DEFAULT_LOG_DOM, __VA_ARGS__) -/************************ Unicode stuff **************************/ -#include "../engines/common/evas_encoding.h" -/*****************************************************************/ - #include "evas_options.h" #if defined(__ARM_ARCH_3M__) @@ -664,6 +660,7 @@ struct _RGBA_Draw_Context DATA32 col; } col; struct RGBA_Draw_Context_clip { + DATA8 *mask; int x, y, w, h; Eina_Bool use : 1; } clip; @@ -692,7 +689,7 @@ struct _RGBA_Draw_Context #ifdef BUILD_PIPE_RENDER #include "../engines/common/evas_map_image.h" -#include "../engines/common/evas_bidi_utils.h" +#include "../engines/common/evas_text_utils.h" struct _RGBA_Pipe_Op { @@ -714,7 +711,7 @@ struct _RGBA_Pipe_Op RGBA_Font *font; int x, y; Eina_Unicode *text; - Evas_BiDi_Props intl_props; + Evas_Text_Props intl_props; } text; struct { RGBA_Image *src; @@ -725,9 +722,10 @@ struct _RGBA_Pipe_Op struct { RGBA_Image *src; RGBA_Map_Point *p; + int npoints; int smooth; int level; - } map4; + } map; } op; }; @@ -893,6 +891,8 @@ struct _RGBA_Font_Int unsigned char inuse : 1; }; +#include "../engines/common/evas_font_ot.h" + struct _RGBA_Font_Source { const char *name; @@ -905,6 +905,11 @@ struct _RGBA_Font_Source int orig_upem; FT_Face face; } ft; +#ifdef OT_SUPPORT + struct { + void *face; + } hb; +#endif }; struct _RGBA_Font_Glyph diff --git a/src/lib/include/evas_inline.x b/src/lib/include/evas_inline.x index 653125f..73f3f42 100644 --- a/src/lib/include/evas_inline.x +++ b/src/lib/include/evas_inline.x @@ -90,8 +90,8 @@ evas_event_passes_through(Evas_Object *obj) static inline int evas_object_is_visible(Evas_Object *obj) -{ - if ((obj->cur.visible) && +{ /* post 1.0 -> enable? */ + if ((obj->cur.visible)/* && (obj->cur.color.a > 0)*/ && ((obj->cur.cache.clip.visible) || (obj->smart.smart)) && ((obj->cur.cache.clip.a > 0 && obj->cur.render_op == EVAS_RENDER_BLEND) || obj->cur.render_op != EVAS_RENDER_BLEND)) diff --git a/src/lib/include/evas_private.h b/src/lib/include/evas_private.h index 9745bc4..6103bfd 100644 --- a/src/lib/include/evas_private.h +++ b/src/lib/include/evas_private.h @@ -11,7 +11,9 @@ #include "../file/evas_module.h" #include "../file/evas_path.h" -#include "../engines/common/evas_bidi_utils.h" +#include "../engines/common/evas_text_utils.h" +#include "../engines/common/language/evas_bidi_utils.h" +#include "../engines/common/language/evas_language_utils.h" #ifdef EVAS_MAGIC_DEBUG /* complain when peole pass in wrong object types etc. */ @@ -53,6 +55,7 @@ typedef struct _Evas_Post_Callback Evas_Post_Callback; #define MAGIC_OBJ_TEXT 0x71777776 #define MAGIC_OBJ_SMART 0x71777777 #define MAGIC_OBJ_TEXTBLOCK 0x71777778 +#define MAGIC_OBJ_PROXY 0x71777779 #define MAGIC_SMART 0x72777770 #define MAGIC_OBJ_SHAPE 0x72777773 #define MAGIC_OBJ_CONTAINER 0x72777774 @@ -650,13 +653,13 @@ struct _Evas_Func int (*font_descent_get) (void *data, void *font); int (*font_max_ascent_get) (void *data, void *font); int (*font_max_descent_get) (void *data, void *font); - void (*font_string_size_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h); - int (*font_inset_get) (void *data, void *font, const Eina_Unicode *text); - int (*font_h_advance_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props); - int (*font_v_advance_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props); - int (*font_char_coords_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch); - int (*font_char_at_coords_get) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch); - void (*font_draw) (void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props); + void (*font_string_size_get) (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int *w, int *h); + int (*font_inset_get) (void *data, void *font, const Evas_Text_Props *text_props); + int (*font_h_advance_get) (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props); + int (*font_v_advance_get) (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props); + int (*font_char_coords_get) (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch); + int (*font_char_at_coords_get) (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch); + void (*font_draw) (void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_Text_Props *intl_props); void (*font_cache_flush) (void *data); void (*font_cache_set) (void *data, int bytes); @@ -671,7 +674,7 @@ struct _Evas_Func void (*image_scale_hint_set) (void *data, void *image, int hint); int (*image_scale_hint_get) (void *data, void *image); - int (*font_last_up_to_pos) (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y); + int (*font_last_up_to_pos) (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int x, int y); void (*image_map_draw) (void *data, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level); void *(*image_map_surface_new) (void *data, int w, int h, int alpha); @@ -679,6 +682,8 @@ struct _Evas_Func void (*image_content_hint_set) (void *data, void *surface, int hint); int (*image_content_hint_get) (void *data, void *surface); + int (*font_pen_coords_get) (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch); + Eina_Bool (*font_text_props_info_create) (void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *intl_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len); }; struct _Evas_Image_Load_Func @@ -838,7 +843,7 @@ Eina_Bool evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y, Eva /****************************************************************************/ /*****************************************/ /********************/ -//#define MPOOL 1 +#define MPOOL 1 #ifdef MPOOL typedef struct _Evas_Mempool Evas_Mempool; diff --git a/src/modules/engines/buffer/evas_engine.c b/src/modules/engines/buffer/evas_engine.c index 851d905..0277db4 100644 --- a/src/modules/engines/buffer/evas_engine.c +++ b/src/modules/engines/buffer/evas_engine.c @@ -306,7 +306,7 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int re = (Render_Engine *)data; #ifdef BUILD_PIPE_RENDER - evas_common_pipe_map4_begin(surface); + evas_common_pipe_map_begin(surface); #endif evas_buffer_outbuf_buf_push_updated_region(re->ob, surface, x, y, w, h); evas_buffer_outbuf_buf_free_region_for_update(re->ob, surface); diff --git a/src/modules/engines/cairo_x11/evas_engine.c b/src/modules/engines/cairo_x11/evas_engine.c index 528a273..0f9ea14 100644 --- a/src/modules/engines/cairo_x11/evas_engine.c +++ b/src/modules/engines/cairo_x11/evas_engine.c @@ -89,10 +89,12 @@ static int eng_font_descent_get(void *data, void *font); static int eng_font_max_ascent_get(void *data, void *font); static int eng_font_max_descent_get(void *data, void *font); static void eng_font_string_size_get(void *data, void *font, char *text, int *w, int *h); -static int eng_font_inset_get(void *data, void *font, char *text); +static int eng_font_inset_get(void *data, void *font, const Evas_Text_Props *intl_props); static int eng_font_h_advance_get(void *data, void *font, char *text); static int eng_font_v_advance_get(void *data, void *font, char *text); static int eng_font_char_coords_get(void *data, void *font, char *text, int pos, int *cx, int *cy, int *cw, int *ch); +static int eng_font_pen_coords_get(void *data, void *font, char *text, int pos, int *cpen_x, int *cy, int *cadv, int *ch); +static Eina_Bool eng_font_text_props_info_create(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len); static int eng_font_char_at_coords_get(void *data, void *font, char *text, int x, int y, int *cx, int *cy, int *cw, int *ch); static void eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, char *text); static void eng_font_cache_flush(void *data); @@ -211,9 +213,14 @@ static Evas_Func eng_func = eng_image_scale_hint_get, /* more font draw functions */ eng_font_last_up_to_pos, - NULL, // image_map4_draw - NULL, // image_map_surface_new - NULL // image_map_surface_free + NULL, // ORD(image_map_draw); + NULL, // ORD(image_map_surface_new); + NULL, // ORD(image_map_surface_free); + NULL, // eng_image_content_hint_set - software doesn't use it + NULL, // eng_image_content_hint_get - software doesn't use it + eng_font_pen_coords_get, + eng_font_text_props_info_create + /* FUTURE software generic calls go here */ }; static void * @@ -1231,7 +1238,7 @@ eng_font_string_size_get(void *data, void *font, char *text, int *w, int *h) } static int -eng_font_inset_get(void *data, void *font, char *text) +eng_font_inset_get(void *data, void *font, const Evas_Text_Props *intl_props) { Render_Engine *re; @@ -1273,6 +1280,27 @@ eng_font_char_coords_get(void *data, void *font, char *text, int pos, int *cx, i } static int +eng_font_pen_coords_get(void *data, void *font, char *text, int pos, int *cpen_x, int *cy, int *cadv, int *ch) +{ + Render_Engine *re; + + /* FIXME, use cairo font subsystem */ + re = (Render_Engine *)data; + return 0; +} + + +static Eina_Bool +eng_font_text_props_info_create(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len) +{ + Render_Engine *re; + + /* FIXME, use cairo font subsystem */ + re = (Render_Engine *)data; + return EINA_TRUE; +} + +static int eng_font_char_at_coords_get(void *data, void *font, char *text, int x, int y, int *cx, int *cy, int *cw, int *ch) { Render_Engine *re; diff --git a/src/modules/engines/direct3d/evas_engine.c b/src/modules/engines/direct3d/evas_engine.c index be5938b..2ed59bc 100644 --- a/src/modules/engines/direct3d/evas_engine.c +++ b/src/modules/engines/direct3d/evas_engine.c @@ -388,7 +388,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_Text_Props *intl_props) { Render_Engine *re = (Render_Engine *)data; RGBA_Image im; @@ -469,7 +469,7 @@ module_open(Evas_Module *em) ORD(image_scale_hint_set); ORD(image_scale_hint_get); -// ORD(image_map4_draw); +// ORD(image_map_draw); // ORD(image_map_surface_new); // ORD(image_map_surface_free); diff --git a/src/modules/engines/directfb/evas_engine.c b/src/modules/engines/directfb/evas_engine.c index cecc69c..4f960cd 100644 --- a/src/modules/engines/directfb/evas_engine.c +++ b/src/modules/engines/directfb/evas_engine.c @@ -1037,7 +1037,7 @@ evas_engine_dfb_output_idle_flush(void *data) * memory. */ static void -evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_Text_Props *intl_props) { DirectFB_Engine_Image_Entry *eim = surface; IDirectFBSurface *screen; @@ -1551,7 +1551,7 @@ evas_engine_dfb_image_draw(void *data, void *context, void *surface, void *image #endif static void -evas_engine_dfb_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level) +evas_engine_dfb_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level) { Render_Engine *re = (Render_Engine*) data; DirectFB_Engine_Image_Entry *deie = image; @@ -1570,7 +1570,7 @@ evas_engine_dfb_image_map4_draw(void *data __UNUSED__, void *context, void *surf if (!_dfb_lock_and_sync_image(deie->surface, src, DSLF_READ)) goto error_src; - evas_common_map4_rgba(src, dst, context, p, smooth, level); + evas_common_map_rgba(src, dst, context, 4, p, smooth, level); evas_common_cpu_end_opt(); screen->Unlock(screen); @@ -1718,7 +1718,7 @@ module_open(Evas_Module *em) ORD(image_scale_hint_set); ORD(image_scale_hint_get); - ORD(image_map4_draw); + ORD(image_map_draw); ORD(image_map_surface_new); ORD(image_map_surface_free); diff --git a/src/modules/engines/fb/evas_engine.c b/src/modules/engines/fb/evas_engine.c index b2b8b58..7681b00 100644 --- a/src/modules/engines/fb/evas_engine.c +++ b/src/modules/engines/fb/evas_engine.c @@ -223,7 +223,7 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int re = (Render_Engine *)data; #ifdef BUILD_PIPE_RENDER - evas_common_pipe_map4_begin(surface); + evas_common_pipe_map_begin(surface); #endif evas_fb_outbuf_fb_push_updated_region(re->ob, surface, x, y, w, h); evas_fb_outbuf_fb_free_region_for_update(re->ob, surface); diff --git a/src/modules/engines/gl_common/evas_gl_common.h b/src/modules/engines/gl_common/evas_gl_common.h index defaa1a..d83bdd1 100644 --- a/src/modules/engines/gl_common/evas_gl_common.h +++ b/src/modules/engines/gl_common/evas_gl_common.h @@ -126,6 +126,8 @@ struct _Evas_GL_Shared { Eina_List *images; + int images_size; + struct { GLint max_texture_units; GLint max_texture_size; @@ -356,6 +358,7 @@ struct _Evas_GL_Image } native; int scale_hint, content_hint; + int csize; unsigned char dirty : 1; unsigned char cached : 1; @@ -448,14 +451,15 @@ void evas_gl_common_context_yuv_push(Evas_GL_Context *gc, int x, int y, int w, int h, int r, int g, int b, int a, Eina_Bool smooth); -void evas_gl_common_context_image_map4_push(Evas_GL_Context *gc, - Evas_GL_Texture *tex, - RGBA_Map_Point *p, - int clip, int cx, int cy, int cw, int ch, - int r, int g, int b, int a, - Eina_Bool smooth, - Eina_Bool tex_only, - Eina_Bool yuv); +void evas_gl_common_context_image_map_push(Evas_GL_Context *gc, + Evas_GL_Texture *tex, + int npoints, + RGBA_Map_Point *p, + int clip, int cx, int cy, int cw, int ch, + int r, int g, int b, int a, + Eina_Bool smooth, + Eina_Bool tex_only, + Eina_Bool yuv); void evas_gl_common_context_flush(Evas_GL_Context *gc); int evas_gl_common_shader_program_init(Evas_GL_Program *p, @@ -480,6 +484,8 @@ void evas_gl_common_texture_yuv_update(Evas_GL_Texture *tex, DATA8 void evas_gl_common_image_all_unload(Evas_GL_Context *gc); +void evas_gl_common_image_ref(Evas_GL_Image *im); +void evas_gl_common_image_unref(Evas_GL_Image *im); Evas_GL_Image *evas_gl_common_image_load(Evas_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error); Evas_GL_Image *evas_gl_common_image_new_from_data(Evas_GL_Context *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, int cspace); Evas_GL_Image *evas_gl_common_image_new_from_copied_data(Evas_GL_Context *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, int cspace); @@ -489,10 +495,11 @@ void evas_gl_common_image_native_enable(Evas_GL_Image *im); void evas_gl_common_image_native_disable(Evas_GL_Image *im); void evas_gl_common_image_scale_hint_set(Evas_GL_Image *im, int hint); void evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint); +void evas_gl_common_image_cache_flush(Evas_GL_Context *gc); void evas_gl_common_image_free(Evas_GL_Image *im); Evas_GL_Image *evas_gl_common_image_surface_new(Evas_GL_Context *gc, unsigned int w, unsigned int h, int alpha); void evas_gl_common_image_dirty(Evas_GL_Image *im, unsigned int x, unsigned int y, unsigned int w, unsigned int h); -void evas_gl_common_image_map4_draw(Evas_GL_Context *gc, Evas_GL_Image *im, RGBA_Map_Point *p, int smooth, int level); +void evas_gl_common_image_map_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int npoints, RGBA_Map_Point *p, int smooth, int level); void evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth); void *evas_gl_font_texture_new(void *gc, RGBA_Font_Glyph *fg); diff --git a/src/modules/engines/gl_common/evas_gl_context.c b/src/modules/engines/gl_common/evas_gl_context.c index d7ad88a..5eceb64 100644 --- a/src/modules/engines/gl_common/evas_gl_context.c +++ b/src/modules/engines/gl_common/evas_gl_context.c @@ -2185,13 +2185,14 @@ again: } void -evas_gl_common_context_image_map4_push(Evas_GL_Context *gc, - Evas_GL_Texture *tex, - RGBA_Map_Point *p, - int clip, int cx, int cy, int cw, int ch, - int r, int g, int b, int a, - Eina_Bool smooth, Eina_Bool tex_only, - Eina_Bool yuv) +evas_gl_common_context_image_map_push(Evas_GL_Context *gc, + Evas_GL_Texture *tex, + int npoints, + RGBA_Map_Point *p, + int clip, int cx, int cy, int cw, int ch, + int r, int g, int b, int a, + Eina_Bool smooth, Eina_Bool tex_only, + Eina_Bool yuv) { int pnum, nv, nc, nu, nu2, nu3, nt, i; const int points[6] = { 0, 1, 2, 0, 2, 3 }; @@ -2205,6 +2206,11 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc, if (!tex->alpha) blend = 0; if (a < 255) blend = 1; + if (npoints != 4) + { + // FIXME: nash - you didnt fix this for n points. its still all 4 point stuff!!! grrrr. + abort(); + } if ((A_VAL(&(p[0].col)) < 0xff) || (A_VAL(&(p[1].col)) < 0xff) || (A_VAL(&(p[2].col)) < 0xff) || (A_VAL(&(p[3].col)) < 0xff)) blend = 1; @@ -2520,7 +2526,7 @@ again: if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert)) { // FIXME: handle yinvert - ERR("not handling inverted y case for map4"); + ERR("not handling inverted y case for map"); } cmul = ARGB_JOIN(a, r, g, b); diff --git a/src/modules/engines/gl_common/evas_gl_image.c b/src/modules/engines/gl_common/evas_gl_image.c index afed2a7..e119df9 100644 --- a/src/modules/engines/gl_common/evas_gl_image.c +++ b/src/modules/engines/gl_common/evas_gl_image.c @@ -20,6 +20,82 @@ evas_gl_common_image_all_unload(Evas_GL_Context *gc) } } +static void +_evas_gl_image_cache_trim(Evas_GL_Context *gc) +{ + int size = evas_common_image_get_cache(); + + while (gc->shared->images_size > size) + { + Evas_GL_Image *im2; + Eina_List *l = NULL; + + EINA_LIST_REVERSE_FOREACH(gc->shared->images, l, im2) + { + if (im2->references == 0) + { + im2->cached = 0; + im2->gc->shared->images = + eina_list_remove_list(im2->gc->shared->images, l); + im2->gc->shared->images_size -= (im2->csize); + evas_gl_common_image_free(im2); + l = NULL; + break; + } + } + if ((gc->shared->images_size > size) && (l)) + { + printf("EEK %i > %i, no 0 ref imgs\n", + gc->shared->images_size, size); + break; + } + if (!gc->shared->images) + { + printf("EEK %i > %i, no imgs\n", + gc->shared->images_size, size); + break; + } + } +} + +static Eina_Bool +_evas_gl_image_cache_add(Evas_GL_Image *im) +{ + if (im->references == 0) + { + im->csize = im->w * im->h * 4; + im->gc->shared->images_size += im->csize; + _evas_gl_image_cache_trim(im->gc); + return EINA_TRUE; + } + else + { + im->gc->shared->images = eina_list_remove(im->gc->shared->images, im); + im->cached = 0; + } + return EINA_FALSE; +} + +void +evas_gl_common_image_ref(Evas_GL_Image *im) +{ + if (im->references == 0) + { + im->gc->shared->images_size -= (im->csize); + } + im->references++; +} + +void +evas_gl_common_image_unref(Evas_GL_Image *im) +{ + im->references--; + if (im->references == 0) + { + _evas_gl_image_cache_add(im); + } +} + Evas_GL_Image * evas_gl_common_image_load(Evas_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error) { @@ -30,14 +106,17 @@ evas_gl_common_image_load(Evas_GL_Context *gc, const char *file, const char *key im_im = evas_common_load_image_from_file(file, key, lo, error); if (!im_im) return NULL; + // FIXME: keep unreffed shared images around EINA_LIST_FOREACH(gc->shared->images, l, im) { if (im->im == im_im) { - evas_cache_image_drop(&im_im->cache_entry); +// why did i put this here? i think to free the rgba pixel data once a texture +// exists. +// evas_cache_image_drop(&im_im->cache_entry); gc->shared->images = eina_list_remove_list(gc->shared->images, l); gc->shared->images = eina_list_prepend(gc->shared->images, im); - im->references++; + evas_gl_common_image_ref(im); *error = EVAS_LOAD_ERROR_NONE; return im; } @@ -52,7 +131,6 @@ evas_gl_common_image_load(Evas_GL_Context *gc, const char *file, const char *key im->references = 1; im->im = im_im; im->gc = gc; - im->references = 1; im->cached = 1; im->cs.space = EVAS_COLORSPACE_ARGB8888; im->alpha = im->im->cache_entry.flags.alpha; @@ -79,7 +157,7 @@ evas_gl_common_image_new_from_data(Evas_GL_Context *gc, unsigned int w, unsigned { gc->shared->images = eina_list_remove_list(gc->shared->images, l); gc->shared->images = eina_list_prepend(gc->shared->images, im); - im->references++; + evas_gl_common_image_ref(im); return im; } } @@ -230,6 +308,8 @@ evas_gl_common_image_native_enable(Evas_GL_Image *im) im->cs.no_free = 0; if (im->cached) { + if (im->references == 0) + im->gc->shared->images_size -= (im->csize); im->gc->shared->images = eina_list_remove(im->gc->shared->images, im); im->cached = 0; } @@ -302,6 +382,8 @@ evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint) im->cs.no_free = 0; if (im->cached) { + if (im->references == 0) + im->gc->shared->images_size -= im->csize; im->gc->shared->images = eina_list_remove(im->gc->shared->images, im); im->cached = 0; } @@ -343,6 +425,12 @@ evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint) } void +evas_gl_common_image_cache_flush(Evas_GL_Context *gc) +{ + _evas_gl_image_cache_trim(gc); +} + +void evas_gl_common_image_free(Evas_GL_Image *im) { im->references--; @@ -355,7 +443,10 @@ evas_gl_common_image_free(Evas_GL_Image *im) { if (!im->cs.no_free) free(im->cs.data); } - if (im->cached) im->gc->shared->images = eina_list_remove(im->gc->shared->images, im); + if (im->cached) + { + if (_evas_gl_image_cache_add(im)) return; + } if (im->im) evas_cache_image_drop(&im->im->cache_entry); if (im->tex) evas_gl_common_texture_free(im->tex); free(im); @@ -462,8 +553,8 @@ _evas_gl_common_image_update(Evas_GL_Context *gc, Evas_GL_Image *im) } void -evas_gl_common_image_map4_draw(Evas_GL_Context *gc, Evas_GL_Image *im, - RGBA_Map_Point *p, int smooth, int level __UNUSED__) +evas_gl_common_image_map_draw(Evas_GL_Context *gc, Evas_GL_Image *im, + int npoints, RGBA_Map_Point *p, int smooth, int level __UNUSED__) { RGBA_Draw_Context *dc; int r, g, b, a; @@ -492,10 +583,10 @@ evas_gl_common_image_map4_draw(Evas_GL_Context *gc, Evas_GL_Image *im, if ((im->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) || (im->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL)) yuv = 1; - evas_gl_common_context_image_map4_push(gc, im->tex, p, - c, cx, cy, cw, ch, - r, g, b, a, smooth, im->tex_only, - yuv); + evas_gl_common_context_image_map_push(gc, im->tex, npoints, p, + c, cx, cy, cw, ch, + r, g, b, a, smooth, im->tex_only, + yuv); } void diff --git a/src/modules/engines/gl_common/evas_gl_texture.c b/src/modules/engines/gl_common/evas_gl_texture.c index e03b2d9..0810472 100644 --- a/src/modules/engines/gl_common/evas_gl_texture.c +++ b/src/modules/engines/gl_common/evas_gl_texture.c @@ -847,6 +847,7 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im) glPixelStorei(GL_UNPACK_ALIGNMENT, 4); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); +// printf("tex upload %ix%i\n", im->cache_entry.w, im->cache_entry.h); // +-+ // +-+ // diff --git a/src/modules/engines/gl_common/shader/.gitignore b/src/modules/engines/gl_common/shader/.gitignore new file mode 100644 index 0000000..a01ee28 --- /dev/null +++ b/src/modules/engines/gl_common/shader/.gitignore @@ -0,0 +1 @@ +.*.swp diff --git a/src/modules/engines/gl_glew/evas_engine.c b/src/modules/engines/gl_glew/evas_engine.c index 5f40812..43e349d 100644 --- a/src/modules/engines/gl_glew/evas_engine.c +++ b/src/modules/engines/gl_glew/evas_engine.c @@ -729,7 +729,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image __UNUSED__) } static void -eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level) +eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level) { // XXX } @@ -748,7 +748,7 @@ eng_image_map_surface_free(void *data __UNUSED__, void *surface) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const Eina_Unicode *text, const Evas_Text_Props *intl_props) { Render_Engine *re; @@ -853,7 +853,7 @@ module_open(Evas_Module *em) ORD(image_scale_hint_set); ORD(image_scale_hint_get); - ORD(image_map4_draw); + ORD(image_map_draw); ORD(image_map_surface_new); ORD(image_map_surface_free); diff --git a/src/modules/engines/gl_sdl/evas_engine.c b/src/modules/engines/gl_sdl/evas_engine.c index ec8edbf..fd4f817 100644 --- a/src/modules/engines/gl_sdl/evas_engine.c +++ b/src/modules/engines/gl_sdl/evas_engine.c @@ -785,14 +785,14 @@ eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint) } static void -eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level) +eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level) { Render_Engine *re; re = (Render_Engine *)data; evas_gl_common_context_target_surface_set(re->gl_context, surface); re->gl_context->dc = context; - evas_gl_common_image_map4_draw(re->gl_context, image, p, smooth, level); + evas_gl_common_image_map_draw(re->gl_context, image, npoints, p, smooth, level); } static void * @@ -817,7 +817,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_Text_Props *intl_props) { Render_Engine *re; @@ -922,7 +922,7 @@ module_open(Evas_Module *em) ORD(image_scale_hint_set); ORD(image_scale_hint_get); - ORD(image_map4_draw); + ORD(image_map_draw); ORD(image_map_surface_new); ORD(image_map_surface_free); diff --git a/src/modules/engines/gl_x11/evas_engine.c b/src/modules/engines/gl_x11/evas_engine.c index 6ea8256..8523df4 100644 --- a/src/modules/engines/gl_x11/evas_engine.c +++ b/src/modules/engines/gl_x11/evas_engine.c @@ -1225,13 +1225,13 @@ eng_image_native_set(void *data, void *image, void *native) if (im2 == im) return im; if (im2) { - n = im2->native.data; - if (n) - { - im2->references++; - evas_gl_common_image_free(im); - return im2; - } + n = im2->native.data; + if (n) + { + evas_gl_common_image_ref(im2); + evas_gl_common_image_free(im); + return im2; + } } } else if (ns->type == EVAS_NATIVE_SURFACE_OPENGL) @@ -1762,6 +1762,11 @@ eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *im eng_window_use(re->win); evas_gl_common_context_target_surface_set(re->win->gl_context, surface); re->win->gl_context->dc = context; + if (npoints != 4) + { + // FIXME: nash - you didnt fix this + abort(); + } if ((p[0].x == p[3].x) && (p[1].x == p[2].x) && (p[0].y == p[1].y) && @@ -1787,15 +1792,13 @@ eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *im dy = p[0].y >> FP; dw = (p[2].x >> FP) - dx; dh = (p[2].y >> FP) - dy; - eng_image_draw - (data, context, surface, image, - 0, 0, gim->w, gim->h, - dx, dy, dw, dh, smooth); + eng_image_draw(data, context, surface, image, + 0, 0, gim->w, gim->h, dx, dy, dw, dh, smooth); } else { - evas_gl_common_image_map4_draw(re->win->gl_context, image, p, - smooth, level); + evas_gl_common_image_map_draw(re->win->gl_context, image, npoints, p, + smooth, level); } } @@ -1829,6 +1832,42 @@ eng_image_content_hint_get(void *data __UNUSED__, void *image) } static void +eng_image_cache_flush(void *data __UNUSED__) +{ + Render_Engine *re; + int tmp_size; + + re = (Render_Engine *)data; + + tmp_size = evas_common_image_get_cache(); + evas_common_image_set_cache(0); + evas_common_rgba_image_scalecache_flush(); + evas_gl_common_image_cache_flush(re->win->gl_context); + evas_common_image_set_cache(tmp_size); +} + +static void +eng_image_cache_set(void *data __UNUSED__, int bytes) +{ + Render_Engine *re; + + re = (Render_Engine *)data; + evas_common_image_set_cache(bytes); + evas_common_rgba_image_scalecache_size_set(bytes); + evas_gl_common_image_cache_flush(re->win->gl_context); +} + +static int +eng_image_cache_get(void *data __UNUSED__) +{ + Render_Engine *re; + + re = (Render_Engine *)data; + return evas_common_image_get_cache(); +} + + +static void eng_image_stride_get(void *data __UNUSED__, void *image, int *stride) { Evas_GL_Image *im = image; @@ -1841,7 +1880,7 @@ eng_image_stride_get(void *data __UNUSED__, void *image, int *stride) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_Text_Props *intl_props) { Render_Engine *re; @@ -1963,6 +2002,10 @@ module_open(Evas_Module *em) ORD(image_content_hint_set); ORD(image_content_hint_get); + + ORD(image_cache_flush); + ORD(image_cache_set); + ORD(image_cache_get); /* now advertise out own api */ em->functions = (void *)(&func); diff --git a/src/modules/engines/quartz/evas_engine.c b/src/modules/engines/quartz/evas_engine.c index 28508ff..6ed0c25 100644 --- a/src/modules/engines/quartz/evas_engine.c +++ b/src/modules/engines/quartz/evas_engine.c @@ -1026,7 +1026,7 @@ eng_font_max_descent_get(void *data, void *font) } static void -eng_font_string_size_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int *w, int *h) +eng_font_string_size_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props, int *w, int *h) { Render_Engine *re = (Render_Engine *)data; Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font; @@ -1050,34 +1050,34 @@ eng_font_string_size_get(void *data, void *font, const char *text, const Evas_Bi } static int -eng_font_inset_get(void *data, void *font, const char *text) +eng_font_inset_get(void *data, void *font, const Evas_Text_Props *intl_props) { return 0; } static int -eng_font_h_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props) +eng_font_h_advance_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props) { int w; - eng_font_string_size_get(data, font, text, intl_props, &w, NULL); + eng_font_string_size_get(data, font, text, text_props, &w, NULL); return w + 2; // FIXME: shouldn't need a constant here. from where do we get word spacing? // it seems we lose the space between differently-styled text in a text block. Why? } static int -eng_font_v_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props) +eng_font_v_advance_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props) { int h; - eng_font_string_size_get(data, font, text, intl_props, NULL, &h); + eng_font_string_size_get(data, font, text, text_props, NULL, &h); return h; } static int -eng_font_char_coords_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch) +eng_font_char_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props, int pos, int *cx, int *cy, int *cw, int *ch) { Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font; @@ -1096,8 +1096,32 @@ eng_font_char_coords_get(void *data, void *font, const char *text, const Evas_Bi return 1; } +/*FIXME: this is *NOT* implemennted correctly, look at the other engines to + * see what needed to be done */ static int -eng_font_char_at_coords_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch) +eng_font_pen_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch) +{ + return eng_font_char_coords_get(data, font, text, text_props, pos, cpen_x, + cy, cadv, ch); +} + +static Eina_Bool +eng_font_text_props_info_create(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len) +{ + (void) font; + (void) text; + (void) text_props; + (void) par_props; + (void) pos; + (void) len; +#if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT) + evas_bidi_shape_string(text, par_props, pos, len); +#endif + return evas_common_text_props_content_create(font, text, text_props, len); +} + +static int +eng_font_char_at_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *text_props, int x, int y, int *cx, int *cy, int *cw, int *ch) { // Return the index of the character at the given point, also lookup it's origin x, y, w, and h. Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font; @@ -1109,8 +1133,8 @@ eng_font_char_at_coords_get(void *data, void *font, const char *text, const Evas int stringIndex = (int) CTLineGetStringIndexForPosition(line, CGPointMake(x, y)); // In order to get the character's size and position, look up the position of this character and the next one - eng_font_char_coords_get(data, font, text, intl_props, stringIndex, cx, cy, NULL, NULL); - eng_font_char_coords_get(data, font, text, intl_props, stringIndex + 1, cw, NULL, NULL, NULL); + eng_font_char_coords_get(data, font, text, text_props, stringIndex, cx, cy, NULL, NULL); + eng_font_char_coords_get(data, font, text, text_props, stringIndex + 1, cw, NULL, NULL, NULL); if (cw && cx) *cw -= *cx; if (ch) *ch = loaded_font->size; @@ -1136,7 +1160,7 @@ eng_font_hinting_can_hint(void *data, int hinting) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text, const Evas_BiDi_Props *intl_props) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text, const Evas_Text_Props *text_props) { Render_Engine *re = (Render_Engine *)data; Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context; @@ -1297,7 +1321,7 @@ module_open(Evas_Module *em) ORD(image_scale_hint_set); ORD(image_scale_hint_get); -// ORD(image_map4_draw); +// ORD(image_map_draw); // ORD(image_map_surface_new); // ORD(image_map_surface_free); /* now advertise out our api */ diff --git a/src/modules/engines/quartz/evas_quartz_private.h b/src/modules/engines/quartz/evas_quartz_private.h index 3254f75..c1a1123 100644 --- a/src/modules/engines/quartz/evas_quartz_private.h +++ b/src/modules/engines/quartz/evas_quartz_private.h @@ -75,13 +75,15 @@ static int eng_font_ascent_get(void *data, void *font); static int eng_font_descent_get(void *data, void *font); static int eng_font_max_ascent_get(void *data, void *font); static int eng_font_max_descent_get(void *data, void *font); -static void eng_font_string_size_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int *w, int *h); -static int eng_font_inset_get(void *data, void *font, const char *text); -static int eng_font_h_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props); -static int eng_font_v_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props); -static int eng_font_char_coords_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch); -static int eng_font_char_at_coords_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch); -static void eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text, const Evas_BiDi_Props *intl_props); +static void eng_font_string_size_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props, int *w, int *h); +static int eng_font_inset_get(void *data, void *font, const Evas_Text_Props *intl_props); +static int eng_font_h_advance_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props); +static int eng_font_v_advance_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props); +static int eng_font_char_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch); +static int eng_font_pen_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch); +static Eina_Bool eng_font_text_props_info_create(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *intl_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len); +static int eng_font_char_at_coords_get(void *data, void *font, const char *text, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch); +static void eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text, const Evas_Text_Props *intl_props); static void eng_font_hinting_set(void *data, void *font, int hinting); static int eng_font_hinting_can_hint(void *data, int hinting); diff --git a/src/modules/engines/software_16/evas_engine.c b/src/modules/engines/software_16/evas_engine.c index 86855ab..fd657d9 100644 --- a/src/modules/engines/software_16/evas_engine.c +++ b/src/modules/engines/software_16/evas_engine.c @@ -505,55 +505,76 @@ eng_font_max_descent_get(void *data __UNUSED__, void *font) } static void -eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h) +eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int *w, int *h) { - evas_common_font_query_size(font, text, intl_props, w, h); + evas_common_font_query_size(font, text, text_props, w, h); } static int -eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text) +eng_font_inset_get(void *data __UNUSED__, void *font, const Evas_Text_Props *text_props) { - return evas_common_font_query_inset(font, text); + return evas_common_font_query_inset(font, text_props); } static int -eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props) { int h, v; - evas_common_font_query_advance(font, text, intl_props, &h, &v); + evas_common_font_query_advance(font, text, text_props, &h, &v); return h; } static int -eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props) { int h, v; - evas_common_font_query_advance(font, text, intl_props, &h, &v); + evas_common_font_query_advance(font, text, text_props, &h, &v); return v; } static int -eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch) +eng_font_pen_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch) { - return evas_common_font_query_char_coords(font, text, intl_props, pos, cx, cy, cw, ch); + return evas_common_font_query_pen_coords(font, text, text_props, pos, cpen_x, cy, cadv, ch); +} + +static Eina_Bool +eng_font_text_props_info_create(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len) +{ + (void) font; + (void) text; + (void) text_props; + (void) par_props; + (void) pos; + (void) len; +#if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT) + evas_bidi_shape_string(text, par_props, pos, len); +#endif + return evas_common_text_props_content_create(font, text, text_props, len); +} + +static int +eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int pos, int *cx, int *cy, int *cw, int *ch) +{ + return evas_common_font_query_char_coords(font, text, text_props, pos, cx, cy, cw, ch); } static int -eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch) +eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int x, int y, int *cx, int *cy, int *cw, int *ch) { - return evas_common_font_query_char_at_coords(font, text, intl_props, x, y, cx, cy, cw, ch); + return evas_common_font_query_char_at_coords(font, text, text_props, x, y, cx, cy, cw, ch); } static int -eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y) +eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int x, int y) { - return evas_common_font_query_last_up_to_pos(font, text, intl_props, x, y); + return evas_common_font_query_last_up_to_pos(font, text, text_props, x, y); } static void -eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_Text_Props *text_props) { static RGBA_Image *im = NULL; Soft16_Image *dst = surface; @@ -566,7 +587,7 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, i evas_common_soft16_font_glyph_new, evas_common_soft16_font_glyph_free, evas_common_soft16_font_glyph_draw); - evas_common_font_draw(im, context, font, x, y, text, intl_props); + evas_common_font_draw(im, context, font, x, y, text, text_props); evas_common_draw_context_font_ext_set(context, NULL, NULL, @@ -719,11 +740,13 @@ static Evas_Func func = eng_image_scale_hint_get, /* more font draw functions */ eng_font_last_up_to_pos, - NULL, // ORD(image_map4_draw); + NULL, // ORD(image_map_draw); NULL, // ORD(image_map_surface_new); NULL, // ORD(image_map_surface_free); NULL, // eng_image_content_hint_set - software doesn't use it - NULL // eng_image_content_hint_get - software doesn't use it + NULL, // eng_image_content_hint_get - software doesn't use it + eng_font_pen_coords_get, + eng_font_text_props_info_create /* FUTURE software generic calls go here */ }; diff --git a/src/modules/engines/software_16_sdl/evas_engine.c b/src/modules/engines/software_16_sdl/evas_engine.c index 3166107..e4cf501 100644 --- a/src/modules/engines/software_16_sdl/evas_engine.c +++ b/src/modules/engines/software_16_sdl/evas_engine.c @@ -816,7 +816,7 @@ evas_engine_sdl16_image_draw(void *data __UNUSED__, void *context, void *surface } static void -evas_engine_sdl16_image_map4_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *image __UNUSED__, RGBA_Map_Point *p __UNUSED__, int smooth __UNUSED__, int level __UNUSED__) +evas_engine_sdl16_image_map_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *image __UNUSED__, int npoints __UNUSED__, RGBA_Map_Point *p __UNUSED__, int smooth __UNUSED__, int level __UNUSED__) { } @@ -873,7 +873,7 @@ evas_engine_sdl16_image_format_get(void *data __UNUSED__, void *image __UNUSED__ } static void -evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_Text_Props *intl_props) { static RGBA_Image *im = NULL; SDL_Engine_Image_Entry *eim = surface; @@ -1074,7 +1074,7 @@ module_open(Evas_Module *em) ORD(image_border_set); ORD(image_border_get); ORD(image_draw); - ORD(image_map4_draw); + ORD(image_map_draw); ORD(image_cache_flush); ORD(image_cache_set); ORD(image_cache_get); diff --git a/src/modules/engines/software_8/evas_engine.c b/src/modules/engines/software_8/evas_engine.c index a9462d2..bc8b933 100644 --- a/src/modules/engines/software_8/evas_engine.c +++ b/src/modules/engines/software_8/evas_engine.c @@ -561,62 +561,84 @@ eng_font_max_descent_get(void *data __UNUSED__, void *font) } static void -eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, +eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int *w, int *h) { - evas_common_font_query_size(font, text, intl_props, w, h); + evas_common_font_query_size(font, text, text_props, w, h); } static int -eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text) +eng_font_inset_get(void *data __UNUSED__, void *font, const Evas_Text_Props *text_props) { - return evas_common_font_query_inset(font, text); + return evas_common_font_query_inset(font, text_props); } static int -eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props) { int h, v; - evas_common_font_query_advance(font, text, intl_props, &h, &v); + evas_common_font_query_advance(font, text, text_props, &h, &v); return h; } static int -eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props) { int h, v; - evas_common_font_query_advance(font, text, intl_props, &h, &v); + evas_common_font_query_advance(font, text, text_props, &h, &v); return v; } static int -eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, +eng_font_pen_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, + int pos, int *cpen, int *cy, int *cadv, int *ch) +{ + return evas_common_font_query_pen_coords(font, text, text_props, pos, cpen, cy, cadv, ch); +} + +static Eina_Bool +eng_font_text_props_info_create(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len) +{ + (void) font; + (void) text; + (void) text_props; + (void) par_props; + (void) pos; + (void) len; +#if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT) + evas_bidi_shape_string(text, par_props, pos, len); +#endif + return evas_common_text_props_content_create(font, text, text_props, len); +} + +static int +eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int pos, int *cx, int *cy, int *cw, int *ch) { - return evas_common_font_query_char_coords(font, text, intl_props, pos, cx, cy, cw, ch); + return evas_common_font_query_char_coords(font, text, text_props, pos, cx, cy, cw, ch); } static int -eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, +eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int x, int y, int *cx, int *cy, int *cw, int *ch) { - return evas_common_font_query_char_at_coords(font, text, intl_props, x, y, cx, cy, cw, ch); + return evas_common_font_query_char_at_coords(font, text, text_props, x, y, cx, cy, cw, ch); } static int -eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, +eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int x, int y) { - return evas_common_font_query_last_up_to_pos(font, text, intl_props, x, y); + return evas_common_font_query_last_up_to_pos(font, text, text_props, x, y); } static void eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, - int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) + int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_Text_Props *text_props) { - evas_common_font_draw(surface, context, font, x, y, text, intl_props); + evas_common_font_draw(surface, context, font, x, y, text, text_props); evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL); } @@ -764,11 +786,13 @@ static Evas_Func func = { eng_image_scale_hint_get, /* more font draw functions */ eng_font_last_up_to_pos, - NULL, // ORD(image_map4_draw); + NULL, // ORD(image_map_draw); NULL, // ORD(image_map_surface_new); NULL, // ORD(image_map_surface_free); NULL, // eng_image_content_hint_set - software doesn't use it - NULL // eng_image_content_hint_get - software doesn't use it + NULL, // eng_image_content_hint_get - software doesn't use it + eng_font_pen_coords_get, + eng_font_text_props_info_create /* FUTURE software generic calls go here */ }; diff --git a/src/modules/engines/software_ddraw/evas_engine.c b/src/modules/engines/software_ddraw/evas_engine.c index 7bcfdf9..5bfc87f 100644 --- a/src/modules/engines/software_ddraw/evas_engine.c +++ b/src/modules/engines/software_ddraw/evas_engine.c @@ -287,7 +287,7 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int re = (Render_Engine *)data; #ifdef BUILD_PIPE_RENDER - evas_common_pipe_map4_begin(surface); + evas_common_pipe_map_begin(surface); #endif evas_software_ddraw_outbuf_push_updated_region(re->ob, surface, x, y, w, h); evas_software_ddraw_outbuf_free_region_for_update(re->ob, surface); diff --git a/src/modules/engines/software_gdi/evas_engine.c b/src/modules/engines/software_gdi/evas_engine.c index ba80eb5..414e880 100644 --- a/src/modules/engines/software_gdi/evas_engine.c +++ b/src/modules/engines/software_gdi/evas_engine.c @@ -293,7 +293,7 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int re = (Render_Engine *)data; #ifdef BUILD_PIPE_RENDER - evas_common_pipe_map4_begin(surface); + evas_common_pipe_map_begin(surface); #endif evas_software_gdi_outbuf_push_updated_region(re->ob, surface, x, y, w, h); evas_software_gdi_outbuf_free_region_for_update(re->ob, surface); diff --git a/src/modules/engines/software_generic/evas_engine.c b/src/modules/engines/software_generic/evas_engine.c index f2bd395..2ff188e 100644 --- a/src/modules/engines/software_generic/evas_engine.c +++ b/src/modules/engines/software_generic/evas_engine.c @@ -604,7 +604,7 @@ eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *im if (npoints > 4) { eng_image_map_draw(data, context, surface, image, npoints - 2, p + 2, - smooth, level); + smooth, level); } } @@ -725,55 +725,76 @@ eng_font_max_descent_get(void *data __UNUSED__, void *font) } static void -eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h) +eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int *w, int *h) { - evas_common_font_query_size(font, text, intl_props, w, h); + evas_common_font_query_size(font, text, text_props, w, h); } static int -eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text) +eng_font_inset_get(void *data __UNUSED__, void *font, const Evas_Text_Props *text_props) { - return evas_common_font_query_inset(font, text); + return evas_common_font_query_inset(font, text_props); } static int -eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props) { int h, v; - evas_common_font_query_advance(font, text, intl_props, &h, &v); + evas_common_font_query_advance(font, text, text_props, &h, &v); return h; } static int -eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props) { int h, v; - evas_common_font_query_advance(font, text, intl_props, &h, &v); + evas_common_font_query_advance(font, text, text_props, &h, &v); return v; } static int -eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch) +eng_font_pen_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int pos, int *cpen_x, int *cy, int *cadv, int *ch) { - return evas_common_font_query_char_coords(font, text, intl_props, pos, cx, cy, cw, ch); + return evas_common_font_query_pen_coords(font, text, text_props, pos, cpen_x, cy, cadv, ch); +} + +static Eina_Bool +eng_font_text_props_info_create(void *data __UNUSED__, void *font, Eina_Unicode *text, Evas_Text_Props *text_props, const Evas_BiDi_Paragraph_Props *par_props, size_t pos, size_t len) +{ + (void) font; + (void) text; + (void) text_props; + (void) par_props; + (void) pos; + (void) len; +#if !defined(OT_SUPPORT) && defined(BIDI_SUPPORT) + evas_bidi_shape_string(text, par_props, pos, len); +#endif + return evas_common_text_props_content_create(font, text, text_props, len); +} + +static int +eng_font_char_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int pos, int *cx, int *cy, int *cw, int *ch) +{ + return evas_common_font_query_char_coords(font, text, text_props, pos, cx, cy, cw, ch); } static int -eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch) +eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int x, int y, int *cx, int *cy, int *cw, int *ch) { - return evas_common_font_query_char_at_coords(font, text, intl_props, x, y, cx, cy, cw, ch); + return evas_common_font_query_char_at_coords(font, text, text_props, x, y, cx, cy, cw, ch); } static int -eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y) +eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_Text_Props *text_props, int x, int y) { - return evas_common_font_query_last_up_to_pos(font, text, intl_props, x, y); + return evas_common_font_query_last_up_to_pos(font, text, text_props, x, y); } static void -eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_Text_Props *text_props) { #ifdef BUILD_PIPE_RENDER if ((cpunum > 1) @@ -781,11 +802,11 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, i && evas_common_frameq_enabled() #endif ) - evas_common_pipe_text_draw(surface, context, font, x, y, text, intl_props); + evas_common_pipe_text_draw(surface, context, font, x, y, text, text_props); else #endif { - evas_common_font_draw(surface, context, font, x, y, text, intl_props); + evas_common_font_draw(surface, context, font, x, y, text, text_props); evas_common_cpu_end_opt(); } } @@ -793,7 +814,12 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, i static void eng_font_cache_flush(void *data __UNUSED__) { + int tmp_size; + + tmp_size = evas_common_font_cache_get(); + evas_common_font_cache_set(0); evas_common_font_flush(); + evas_common_font_cache_set(tmp_size); } static void @@ -943,7 +969,9 @@ static Evas_Func func = eng_image_map_surface_new, eng_image_map_surface_free, NULL, // eng_image_content_hint_set - software doesn't use it - NULL // eng_image_content_hint_get - software doesn't use it + NULL, // eng_image_content_hint_get - software doesn't use it + eng_font_pen_coords_get, + eng_font_text_props_info_create /* FUTURE software generic calls go here */ }; diff --git a/src/modules/engines/software_qtopia/evas_engine.c b/src/modules/engines/software_qtopia/evas_engine.c index a291adc..1d84d57 100644 --- a/src/modules/engines/software_qtopia/evas_engine.c +++ b/src/modules/engines/software_qtopia/evas_engine.c @@ -237,7 +237,7 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int re = (Render_Engine *)data; #ifdef BUILD_PIPE_RENDER - evas_common_pipe_map4_begin(surface); + evas_common_pipe_map_begin(surface); #endif evas_qtopia_outbuf_software_qtopia_push_updated_region(re->ob, surface, x, y, w, h); evas_qtopia_outbuf_software_qtopia_free_region_for_update(re->ob, surface); diff --git a/src/modules/engines/software_sdl/evas_engine.c b/src/modules/engines/software_sdl/evas_engine.c index d7d9e22..7c6f2b5 100644 --- a/src/modules/engines/software_sdl/evas_engine.c +++ b/src/modules/engines/software_sdl/evas_engine.c @@ -618,7 +618,7 @@ evas_engine_sdl_image_draw(void *data, void *context, void *surface, void *image } static void -evas_engine_sdl_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level) +evas_engine_sdl_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level) { SDL_Engine_Image_Entry *eim = image; SDL_Engine_Image_Entry *dst = surface; @@ -641,8 +641,8 @@ evas_engine_sdl_image_map4_draw(void *data __UNUSED__, void *context, void *surf _SDL_UPDATE_PIXELS(eim); } - evas_common_map4_rgba((RGBA_Image*) eim->cache_entry.src, - (RGBA_Image*) dst->cache_entry.src, context, p, smooth, level); + evas_common_map_rgba((RGBA_Image*) eim->cache_entry.src, + (RGBA_Image*) dst->cache_entry.src, context, npoints, p, smooth, level); evas_common_cpu_end_opt(); if (mustlock_im) @@ -738,7 +738,7 @@ evas_engine_sdl_image_format_get(void *data __UNUSED__, void *image __UNUSED__) } static void -evas_engine_sdl_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +evas_engine_sdl_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_Text_Props *intl_props) { SDL_Engine_Image_Entry *eim = surface; int mustlock_im = 0; @@ -903,7 +903,7 @@ static int module_open(Evas_Module *em) ORD(image_border_set); ORD(image_border_get); ORD(image_draw); - ORD(image_map4_draw); + ORD(image_map_draw); ORD(image_map_surface_new); ORD(image_map_surface_free); ORD(image_comment_get); diff --git a/src/modules/engines/software_x11/evas_engine.c b/src/modules/engines/software_x11/evas_engine.c index 722f5f3..aff3469 100644 --- a/src/modules/engines/software_x11/evas_engine.c +++ b/src/modules/engines/software_x11/evas_engine.c @@ -736,7 +736,7 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int re = (Render_Engine *)data; #if defined(BUILD_PIPE_RENDER) && !defined(EVAS_FRAME_QUEUING) - evas_common_pipe_map4_begin(surface); + evas_common_pipe_map_begin(surface); #endif /* BUILD_PIPE_RENDER && !EVAS_FRAME_QUEUING*/ #ifdef EVAS_FRAME_QUEUING diff --git a/src/modules/engines/xrender_x11/evas_engine.c b/src/modules/engines/xrender_x11/evas_engine.c index b16ebdd..b7efa97 100644 --- a/src/modules/engines/xrender_x11/evas_engine.c +++ b/src/modules/engines/xrender_x11/evas_engine.c @@ -1172,7 +1172,7 @@ eng_image_cache_get(void *data) } static void -eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props) +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_Text_Props *intl_props) { Render_Engine *re; RGBA_Image *im; @@ -1286,7 +1286,7 @@ module_open(Evas_Module *em) ORD(image_scale_hint_set); ORD(image_scale_hint_get); -// ORD(image_map4_draw); +// ORD(image_map_draw); // ORD(image_map_surface_new); // ORD(image_map_surface_free); diff --git a/src/modules/loaders/wbmp/evas_image_load_wbmp.c b/src/modules/loaders/wbmp/evas_image_load_wbmp.c index 1c7ce4e..393d6da 100644 --- a/src/modules/loaders/wbmp/evas_image_load_wbmp.c +++ b/src/modules/loaders/wbmp/evas_image_load_wbmp.c @@ -16,119 +16,126 @@ static Eina_Bool evas_image_load_file_data_wbmp(Image_Entry *ie, const char *fil static Evas_Image_Load_Func evas_image_load_wbmp_func = { - EINA_TRUE, - evas_image_load_file_head_wbmp, - evas_image_load_file_data_wbmp + EINA_TRUE, + evas_image_load_file_head_wbmp, + evas_image_load_file_data_wbmp }; static int -read_mb(unsigned int *data, FILE * f) +read_mb(unsigned int *data, FILE *f) { - int ac = 0, ct; - unsigned char buf; - - for (ct = 0;;) - { - if ((ct++) == 5) return -1; - if ((fread(&buf, 1, 1, f)) < 1) - return -1; - ac = (ac << 7) | (buf & 0x7f); - if ((buf & 0x80) == 0) break; - } - *data = ac; - return 0; + int ac = 0, ct; + unsigned char buf; + + for (ct = 0;;) + { + if ((ct++) == 5) return -1; + if ((fread(&buf, 1, 1, f)) < 1) + return -1; + ac = (ac << 7) | (buf & 0x7f); + if ((buf & 0x80) == 0) break; + } + *data = ac; + return 0; } static Eina_Bool evas_image_load_file_head_wbmp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error) { - FILE *f; - unsigned int type, w, h; - unsigned char fixed_header; - struct stat statbuf; - - *error = EVAS_LOAD_ERROR_GENERIC; - f = fopen(file, "rb"); - if (!f) - { - *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; - return EINA_FALSE; - } - - if (stat(file, &statbuf) == -1) goto bail; - if (read_mb(&type, f) < 0) goto bail; - - if (type != 0) - { - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - goto bail; - } - - if (fread(&fixed_header, 1, 1, f) != 1) goto bail; - if (read_mb(&w, f) < 0) goto bail; - if (read_mb(&h, f) < 0) goto bail; - fclose(f); - ie->w = w; - ie->h = h; - - *error = EVAS_LOAD_ERROR_NONE; - return EINA_TRUE; + FILE *f; + unsigned int type, w, h; + unsigned char fixed_header; + struct stat statbuf; + + *error = EVAS_LOAD_ERROR_GENERIC; + f = fopen(file, "rb"); + if (!f) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + + if (stat(file, &statbuf) == -1) goto bail; + if (read_mb(&type, f) < 0) goto bail; + + if (type != 0) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto bail; + } + + if (fread(&fixed_header, 1, 1, f) != 1) goto bail; + if (read_mb(&w, f) < 0) goto bail; + if (read_mb(&h, f) < 0) goto bail; + if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) || + IMG_TOO_BIG(w, h)) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto bail; + } + + fclose(f); + ie->w = w; + ie->h = h; + + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE; bail: - fclose(f); - return EINA_FALSE; + fclose(f); + return EINA_FALSE; } static Eina_Bool evas_image_load_file_data_wbmp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error) { - FILE *f; - unsigned int dummy, line_length; - unsigned char *line = NULL; - int cur = 0, x, y; - DATA32 *dst_data; - - *error = EVAS_LOAD_ERROR_GENERIC; - f = fopen(file, "rb"); - if (!f) - { - *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; - return EINA_FALSE; - } - if (read_mb(&dummy, f) < 0) goto bail; - if (fread(&dummy, 1, 1, f) != 1) goto bail; - if (read_mb(&dummy, f) < 0) goto bail; - if (read_mb(&dummy, f) < 0) goto bail; - - evas_cache_image_surface_alloc(ie, ie->w, ie->h); - dst_data = evas_cache_image_pixels(ie); - if (!dst_data) - { - *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - goto bail; - } - - line_length = (ie->w + 7) >> 3; - line = alloca(line_length); - - for (y = 0; y < (int)ie->h; y++) - { - if (fread(line, 1, line_length, f) != line_length) goto bail; - for (x = 0; x < (int)ie->w; x++) - { - int idx = x >> 3; - int offset = 1 << (0x07 - (x & 0x07)); - if (line[idx] & offset) dst_data[cur] = 0xffffffff; - else dst_data[cur] = 0xff000000; - cur++; - } - } - fclose(f); - *error = EVAS_LOAD_ERROR_NONE; - return EINA_TRUE; + FILE *f; + unsigned int dummy, line_length; + unsigned char *line = NULL; + int cur = 0, x, y; + DATA32 *dst_data; + + *error = EVAS_LOAD_ERROR_GENERIC; + f = fopen(file, "rb"); + if (!f) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + if (read_mb(&dummy, f) < 0) goto bail; + if (fread(&dummy, 1, 1, f) != 1) goto bail; + if (read_mb(&dummy, f) < 0) goto bail; + if (read_mb(&dummy, f) < 0) goto bail; + + evas_cache_image_surface_alloc(ie, ie->w, ie->h); + dst_data = evas_cache_image_pixels(ie); + if (!dst_data) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto bail; + } + + line_length = (ie->w + 7) >> 3; + line = alloca(line_length); + + for (y = 0; y < (int)ie->h; y++) + { + if (fread(line, 1, line_length, f) != line_length) goto bail; + for (x = 0; x < (int)ie->w; x++) + { + int idx = x >> 3; + int offset = 1 << (0x07 - (x & 0x07)); + if (line[idx] & offset) dst_data[cur] = 0xffffffff; + else dst_data[cur] = 0xff000000; + cur++; + } + } + fclose(f); + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE; bail: - fclose(f); - return EINA_FALSE; + fclose(f); + return EINA_FALSE; } static int diff --git a/src/modules/savers/jpeg/Makefile.am b/src/modules/savers/jpeg/Makefile.am index 63c8fd9..7d86faa 100644 --- a/src/modules/savers/jpeg/Makefile.am +++ b/src/modules/savers/jpeg/Makefile.am @@ -11,7 +11,7 @@ AM_CPPFLAGS= \ AM_CFLAGS = @WIN32_CFLAGS@ -if BUILD_LOADER_JPEG +if BUILD_SAVER_JPEG if !EVAS_STATIC_BUILD_JPEG pkgdir = $(libdir)/evas/modules/savers/jpeg/$(MODULE_ARCH) diff --git a/src/modules/savers/jpeg/evas_image_save_jpeg.c b/src/modules/savers/jpeg/evas_image_save_jpeg.c index 1ddb0bb..27d48e2 100644 --- a/src/modules/savers/jpeg/evas_image_save_jpeg.c +++ b/src/modules/savers/jpeg/evas_image_save_jpeg.c @@ -24,7 +24,7 @@ static void _JPEGFatalErrorHandler(j_common_ptr cinfo) { emptr errmgr; - + errmgr = (emptr) cinfo->err; longjmp(errmgr->setjmp_buffer, 1); return; @@ -34,7 +34,7 @@ static void _JPEGErrorHandler(j_common_ptr cinfo __UNUSED__) { /* emptr errmgr; */ - + /* errmgr = (emptr) cinfo->err; */ return; } @@ -43,7 +43,7 @@ static void _JPEGErrorHandler2(j_common_ptr cinfo __UNUSED__, int msg_level __UNUSED__) { /* emptr errmgr; */ - + /* errmgr = (emptr) cinfo->err; */ return; } @@ -61,7 +61,7 @@ save_image_jpeg(RGBA_Image *im, const char *file, int quality) if (!im || !im->image.data || !file) return 0; - + buf = alloca(im->cache_entry.w * 3 * sizeof(DATA8)); f = fopen(file, "wb"); if (!f) @@ -90,7 +90,7 @@ save_image_jpeg(RGBA_Image *im, const char *file, int quality) ptr = im->image.data; while (cinfo.next_scanline < cinfo.image_height) { - unsigned int i, j; + unsigned int i, j; for (j = 0, i = 0; i < im->cache_entry.w; i++) { buf[j++] = ((*ptr) >> 16) & 0xff; @@ -142,4 +142,3 @@ EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_SAVER, image_saver, jpeg); #ifndef EVAS_STATIC_BUILD_JPEG EVAS_EINA_MODULE_DEFINE(image_saver, jpeg); #endif - diff --git a/src/modules/savers/png/evas_image_save_png.c b/src/modules/savers/png/evas_image_save_png.c index f6dcb4b..decc14d 100644 --- a/src/modules/savers/png/evas_image_save_png.c +++ b/src/modules/savers/png/evas_image_save_png.c @@ -66,10 +66,13 @@ save_image_png(RGBA_Image *im, const char *file, int compress, int interlace) if (interlace) { #ifdef PNG_WRITE_INTERLACING_SUPPORTED - png_ptr->interlaced = PNG_INTERLACE_ADAM7; - num_passes = png_set_interlace_handling(png_ptr); + interlace = PNG_INTERLACE_ADAM7; +#else + interlace = PNG_INTERLACE_NONE; #endif } + else + interlace = PNG_INTERLACE_NONE; if (im->cache_entry.flags.alpha) { @@ -84,7 +87,7 @@ save_image_png(RGBA_Image *im, const char *file, int compress, int interlace) evas_common_convert_argb_unpremul(data, im->cache_entry.w * im->cache_entry.h); png_init_io(png_ptr, f); png_set_IHDR(png_ptr, info_ptr, im->cache_entry.w, im->cache_entry.h, 8, - PNG_COLOR_TYPE_RGB_ALPHA, png_ptr->interlaced, + PNG_COLOR_TYPE_RGB_ALPHA, interlace, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); #ifdef WORDS_BIGENDIAN png_set_swap_alpha(png_ptr); @@ -97,7 +100,7 @@ save_image_png(RGBA_Image *im, const char *file, int compress, int interlace) data = im->image.data; png_init_io(png_ptr, f); png_set_IHDR(png_ptr, info_ptr, im->cache_entry.w, im->cache_entry.h, 8, - PNG_COLOR_TYPE_RGB, png_ptr->interlaced, + PNG_COLOR_TYPE_RGB, interlace, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_data = alloca(im->cache_entry.w * 3 * sizeof(char)); } @@ -112,6 +115,10 @@ save_image_png(RGBA_Image *im, const char *file, int compress, int interlace) png_set_shift(png_ptr, &sig_bit); png_set_packing(png_ptr); +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + num_passes = png_set_interlace_handling(png_ptr); +#endif + for (pass = 0; pass < num_passes; pass++) { ptr = data; diff --git a/win32/common/config.h b/win32/common/config.h deleted file mode 100644 index 5a94303..0000000 --- a/win32/common/config.h +++ /dev/null @@ -1,328 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Build Altivec Code */ -/* #undef BUILD_ALTIVEC */ - -/* Build plain C code */ -#define BUILD_C 1 - -/* 16bpp BGR 565 Converter Support */ -#define BUILD_CONVERT_16_BGR_565 1 - -/* 16bpp RGB 444 Converter Support */ -#define BUILD_CONVERT_16_RGB_444 1 - -/* 16bpp 565 (444 ipaq) Converter Support */ -#define BUILD_CONVERT_16_RGB_454645 1 - -/* 16bpp RGB 555 Converter Support */ -#define BUILD_CONVERT_16_RGB_555 1 - -/* 16bpp RGB 565 Converter Support */ -#define BUILD_CONVERT_16_RGB_565 1 - -/* 16bpp RGB Rotation 0 Converter Support */ -#define BUILD_CONVERT_16_RGB_ROT0 1 - -/* 16bpp RGB Rotation 180 Converter Support */ -#define BUILD_CONVERT_16_RGB_ROT180 1 - -/* 16bpp RGB Rotation 270 Converter Support */ -#define BUILD_CONVERT_16_RGB_ROT270 1 - -/* 16bpp RGB Rotation 90 Converter Support */ -#define BUILD_CONVERT_16_RGB_ROT90 1 - -/* 24bpp BGR 888 Converter Support */ -#define BUILD_CONVERT_24_BGR_888 1 - -/* 24bpp RGB 888 Converter Support */ -#define BUILD_CONVERT_24_RGB_888 1 - -/* 32bpp BGRX 8888 Converter Support */ -#define BUILD_CONVERT_32_BGRX_8888 1 - -/* 32bpp BGR 8888 Converter Support */ -#define BUILD_CONVERT_32_BGR_8888 1 - -/* 32bpp RGBX 8888 Converter Support */ -#define BUILD_CONVERT_32_RGBX_8888 1 - -/* 32bpp RGB 8888 Converter Support */ -#define BUILD_CONVERT_32_RGB_8888 1 - -/* 32bpp RGB Rotation 0 Converter Support */ -#define BUILD_CONVERT_32_RGB_ROT0 1 - -/* 32bpp RGB Rotation 180 Converter Support */ -#define BUILD_CONVERT_32_RGB_ROT180 1 - -/* 32bpp RGB Rotation 270 Converter Support */ -#define BUILD_CONVERT_32_RGB_ROT270 1 - -/* 32bpp RGB Rotation 90 Converter Support */ -#define BUILD_CONVERT_32_RGB_ROT90 1 - -/* 8bpp RGB 111 Converter Support */ -#define BUILD_CONVERT_8_RGB_111 1 - -/* 8bpp RGB 121 Converter Support */ -#define BUILD_CONVERT_8_RGB_121 1 - -/* 8bpp RGB 221 Converter Support */ -#define BUILD_CONVERT_8_RGB_221 1 - -/* 8bpp RGB 222 Converter Support */ -#define BUILD_CONVERT_8_RGB_222 1 - -/* 8bpp RGB 232 Converter Support */ -#define BUILD_CONVERT_8_RGB_232 1 - -/* 8bpp RGB 332 Converter Support */ -#define BUILD_CONVERT_8_RGB_332 1 - -/* 8bpp RGB 666 Converter Support */ -#define BUILD_CONVERT_8_RGB_666 1 - -/* YUV Converter Support */ -#define BUILD_CONVERT_YUV 1 - -/* Buffer Rendering Backend */ -#define BUILD_ENGINE_BUFFER 1 - -/* Generic Cairo Rendering Support */ -/* #undef BUILD_ENGINE_CAIRO_COMMON */ - -/* Cairo X11 Rendering Backend */ -/* #undef BUILD_ENGINE_CAIRO_X11 */ - -/* Direct3D Rendering Backend */ -#define BUILD_ENGINE_DIRECT3D 1 - -/* DirectFB Rendering Backend */ -/* #undef BUILD_ENGINE_DIRECTFB */ - -/* Linux FB Rendering Backend */ -/* #undef BUILD_ENGINE_FB */ - -/* Glitz X11 Rendering Backend */ -/* #undef BUILD_ENGINE_GLITZ_X11 */ - -/* Generic OpenGL Rendering Support */ -#define BUILD_ENGINE_GL_COMMON 1 - -/* OpenGL Glew Rendering Backend */ -#define BUILD_ENGINE_GL_GLEW 1 - -/* OpenGL X11 Rendering Backend */ -/* #undef BUILD_ENGINE_GL_X11 */ - -/* SDL Rendering Backend */ -#define BUILD_ENGINE_SDL 1 - -/* 16bit Software DirectDraw Rendering Backend */ -/* #undef BUILD_ENGINE_SOFTWARE_16_DDRAW */ - -/* Software 16bit X11 Rendering Backend */ -/* #undef BUILD_ENGINE_SOFTWARE_16_X11 */ - -/* Software DirectDraw Rendering Backend */ -/* #undef BUILD_ENGINE_SOFTWARE_DDRAW */ - -/* Qtopia Rendering Backend */ -/* #undef BUILD_ENGINE_SOFTWARE_QTOPIA */ - -/* Software X11 Rendering Backend */ -/* #undef BUILD_ENGINE_SOFTWARE_X11 */ - -/* Software XCB Rendering Backend */ -/* #undef BUILD_ENGINE_SOFTWARE_XCB */ - -/* XRender X11 Rendering Backend */ -/* #undef BUILD_ENGINE_XRENDER_X11 */ - -/* Xrender XCB Rendering Backend */ -/* #undef BUILD_ENGINE_XRENDER_XCB */ - -/* EET Font Loader Support */ -#define BUILD_FONT_LOADER_EET 1 - -/* EDB Image Loader Support */ -/* #undef BUILD_LOADER_EDB */ - -/* EET Image Loader Support */ -#define BUILD_LOADER_EET 1 - -/* GIF Image Loader Support */ -#define BUILD_LOADER_GIF 1 - -/* JPEG Image Loader Support */ -#define BUILD_LOADER_JPEG 1 - -/* TIFF Image Loader Support */ -#define BUILD_LOADER_TIFF 1 - -/* Build MMX Code */ -/* #define BUILD_MMX 1 */ - -/* No Dither Mask Support */ -/* #undef BUILD_NO_DITHER_MASK */ - -/* Build Threaded Rendering */ -/* #undef BUILD_PTHREAD */ - -/* Sampling Scaler Support */ -#define BUILD_SCALE_SAMPLE 1 - -/* Smooth Scaler Support */ -#define BUILD_SCALE_SMOOTH 1 - -/* Small Dither Mask Support */ -/* #undef BUILD_SMALL_DITHER_MASK */ - -/* Build SSE Code */ -/* #define BUILD_SSE 1 */ - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Define to mention that evas is built */ -#define EFL_EVAS_BUILD 1 - -/* Define to 1 if you have `alloca', as a function or macro. */ -#define HAVE_ALLOCA 1 - -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -/* #undef HAVE_ALLOCA_H */ - -/* Have altivec.h header file */ -/* #undef HAVE_ALTIVEC_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_D3D9_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_D3DX9_H */ - -/* Define to 1 if you have the `dladdr' function. */ -#define HAVE_DLADDR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the `dlopen' function. */ -/* #undef HAVE_DLOPEN */ - -/* Set to 1 if evil package is installed */ -#define HAVE_EVIL 1 - -/* Define to 1 if you have the `fnmatch' function. */ -/* #undef HAVE_FNMATCH */ - -/* have fontconfig searching capabilities */ -#define HAVE_FONTCONFIG 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_GL_GLEW_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_GL_GLU_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_GL_GL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PTHREAD_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SCHED_H */ - -/* Define to 1 if you have the header file. */ -/* #define HAVE_STDINT_H 1 */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #define HAVE_UNISTD_H 1 */ - -/* Valgrind support */ -/* #undef HAVE_VALGRIND */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_X11_EXTENSIONS_XRENDER_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_X11_X_H */ - -/* Name of package */ -#define PACKAGE "evas" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "enlightenment-devel@lists.sourceforge.net" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "evas" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "evas 1.0.0" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "evas" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.0.0" - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "1.0.0" - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Define to 1 if the X Window System is missing or not being used. */ -#define X_DISPLAY_MISSING 1 - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -#define VMAJ 1 -#define VMIN 0 -#define VMIC 0 -#define VREV 0 diff --git a/win32/patch/evas.diff b/win32/patch/evas.diff deleted file mode 100644 index e827ce3..0000000 --- a/win32/patch/evas.diff +++ /dev/null @@ -1,70 +0,0 @@ ---- ../../src/lib/include/evas_common.h 2010-04-15 17:50:07 +0000 -+++ ../../src/lib/include/evas_common_new.h 2010-04-15 17:49:51 +0000 -@@ -312,10 +312,10 @@ - - /*****************************************************************************/ - --#define UNROLL2(op...) op op --#define UNROLL4(op...) UNROLL2(op) UNROLL2(op) --#define UNROLL8(op...) UNROLL4(op) UNROLL4(op) --#define UNROLL16(op...) UNROLL8(op) UNROLL8(op) -+#define UNROLL2(op) op op -+#define UNROLL4(op) UNROLL2(op) UNROLL2(op) -+#define UNROLL8(op) UNROLL4(op) UNROLL4(op) -+#define UNROLL16(op) UNROLL8(op) UNROLL8(op) - - #define UNROLL8_PLD_WHILE(start, size, end, op) \ - pld(start, 0); \ -@@ -726,7 +726,9 @@ - } image; - - struct { -+#ifdef BUILD_PTHREAD - LK(lock); -+#endif - Eina_List *list; - unsigned long long orig_usage; - unsigned long long usage_count; -@@ -921,7 +923,9 @@ - int references; - Fash_Int *fash; - unsigned char sizeok : 1; -+#ifdef BUILD_PTHREAD - LK(lock); -+#endif - }; - - struct _RGBA_Font_Int -@@ -938,7 +942,9 @@ - - // Eina_Hash *glyphs; - -+#ifdef BUILD_PTHREAD - LK(ft_mutex); -+#endif - - Eina_Hash *kerning; - // Eina_Hash *indexes; ---- ../../src/lib/file/evas_module.h 2010-04-15 17:40:42 +0000 -+++ ../../src/lib/file/evas_module_new.h 2010-04-15 17:40:21 +0000 -@@ -47,7 +47,9 @@ - int ref; /* how many refs */ - int last_used; /* the cycle count when it was last used */ - -+#ifdef BUILD_PTHREAD - LK(lock); -+#endif - - unsigned char loaded : 1; - }; ---- ../../src/lib/canvas/evas_render.c 2010-04-15 17:42:18 +0000 -+++ ../../src/lib/canvas/evas_render_new.c 2010-04-15 17:41:46 +0000 -@@ -34,7 +34,7 @@ - rend_dbg(__tmpbuf); \ - } - #else --#define RD(args...) -+#define RD(args,...) - #define RDI(x) - #endif - diff --git a/win32/start.bat b/win32/start.bat deleted file mode 100644 index 4e716ed..0000000 --- a/win32/start.bat +++ /dev/null @@ -1,99 +0,0 @@ -@echo off - -rem Set external libraries directory. -set EXT_DIR=%cd%\..\..\..\extern - -if not exist %EXT_DIR% ( - set EXT_DIR= - echo ERROR: External libs dir is not set. - pause - goto END -) - -if "%DXSDK_DIR%" == "" ( - echo ERROR: Microsoft DirectX SDK is not installed. - pause - goto END -) - -rem Check for basic requirements for Visual Studio 2008 -if "%VS90COMNTOOLS%" == "" ( - echo ERROR: Microsoft Visual Studio 2008 is not installed. - echo ERROR: Try to launch Microsoft Visual Studio 2005. - pause - goto NOVS9 -) - -set PROJECT_TYPE=vs9 -set VSCOMMONTOOLS=%VS90COMNTOOLS%vsvars32.bat - -goto STARTVS - -:NOVS9 - -rem Check for basic requirements for Visual Studio 2005 -if "%VS80COMNTOOLS%" == "" ( - echo ERROR: Microsoft Visual Studio 2005 is not installed. - pause - goto END -) - -set PROJECT_TYPE=vs8 -set VSCOMMONTOOLS=%VS80COMNTOOLS%vsvars32.bat - -rem Patching Eina -patch.exe --binary -p1 < %cd%\patch\eina.diff -echo INFO: Eina patched. - -pause - -:STARTVS - -rem Setup common Win32 environment variables - -rem Add DirectX includes and libraries dirs. -set INCLUDE=%DXSDK_DIR%Include;%INCLUDE% -set LIB=%DXSDK_DIR%Lib\x86;%LIB% - -rem Add Evil lib path -set EvilInclude=%cd%\..\..\evil\src\lib -set EvilCommon=%cd%\..\..\evil\win32\common -set EvilOut=%cd%\..\..\evil\win32\%PROJECT_TYPE%\out - -set INCLUDE=%EvilCommon%;%EvilInclude%;%EvilInclude%\dlfcn;%INCLUDE% -set LIB=%EvilOut%;%LIB% - -rem Add Eina lib path -set EinaInclude=%cd%\..\..\eina\src\include -set EinaCommon=%cd%\..\..\eina\win32\common -set EinaOut=%cd%\..\..\eina\win32\%PROJECT_TYPE%\out - -set INCLUDE=%EinaInclude%;%EinaCommon%;%INCLUDE% -set LIB=%EinaOut%;%LIB% - -rem Add Eet lib path -set EetInclude=%cd%\..\..\eet\src\lib -set EetOut=%cd%\..\..\eet\win32\%PROJECT_TYPE%\out - -set INCLUDE=%EetInclude%;%INCLUDE% -set LIB=%EetOut%;%LIB% - -rem Add installation directory pathes. -set INCLUDE=%EXT_DIR%\include;%EXT_DIR%\include\freetype2;%INCLUDE% -set LIB=%EXT_DIR%\lib;%LIB% - -set INCLUDE=%cd%\common;%cd%\..\src\lib;%cd%\..\src\lib\include;%cd%\..\src\lib\file;%cd%\..\src\lib\cserve;%INCLUDE% - -set SolutionDirectory=%cd%\%PROJECT_TYPE% -set DebugOutputDirectory=%SolutionDirectory%\out -set ReleaseOutputDirectory=%SolutionDirectory%\out -set DebugLibraryDirectory=%SolutionDirectory%\out -set ReleaseLibraryDirectory=%SolutionDirectory%\out -set TemporaryDirectory=%SolutionDirectory%\temp - -rem Setting environment for using Microsoft Visual Studio x86 tools. -call "%VSCOMMONTOOLS%" - -%PROJECT_TYPE%\evas.sln - -:END diff --git a/win32/vs8/engine_buffer.vcproj b/win32/vs8/engine_buffer.vcproj deleted file mode 100644 index b0acbaf..0000000 --- a/win32/vs8/engine_buffer.vcproj +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/engine_direct3d.vcproj b/win32/vs8/engine_direct3d.vcproj deleted file mode 100644 index 48556bb..0000000 --- a/win32/vs8/engine_direct3d.vcproj +++ /dev/null @@ -1,323 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/engine_gl_glew.vcproj b/win32/vs8/engine_gl_glew.vcproj deleted file mode 100644 index 690393b..0000000 --- a/win32/vs8/engine_gl_glew.vcproj +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/engine_software_ddraw.vcproj b/win32/vs8/engine_software_ddraw.vcproj deleted file mode 100644 index 29e43a0..0000000 --- a/win32/vs8/engine_software_ddraw.vcproj +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/engine_software_gdi.vcproj b/win32/vs8/engine_software_gdi.vcproj deleted file mode 100644 index 1fae64f..0000000 --- a/win32/vs8/engine_software_gdi.vcproj +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/engine_software_generic.vcproj b/win32/vs8/engine_software_generic.vcproj deleted file mode 100644 index f6bd243..0000000 --- a/win32/vs8/engine_software_generic.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/evas.sln b/win32/vs8/evas.sln deleted file mode 100644 index 90a1801..0000000 --- a/win32/vs8/evas.sln +++ /dev/null @@ -1,47 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libevas", "libevas.vcproj", "{689B4F2B-666D-439F-9BF3-1203D813DE3F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_buffer", "engine_buffer.vcproj", "{FF8981EF-618E-45B9-9F03-738D7E2914AF}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_software_gdi", "engine_software_gdi.vcproj", "{3367A64F-A08E-4F27-8303-54A3BBB01D5A}" - ProjectSection(ProjectDependencies) = postProject - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36} = {1E24C1AF-62F2-4EC0-AD94-7363C0534E36} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_software_generic", "engine_software_generic.vcproj", "{1E24C1AF-62F2-4EC0-AD94-7363C0534E36}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Debug|Win32.ActiveCfg = Debug|Win32 - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Debug|Win32.Build.0 = Debug|Win32 - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Release|Win32.ActiveCfg = Release|Win32 - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Release|Win32.Build.0 = Release|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Debug|Win32.ActiveCfg = Debug|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Debug|Win32.Build.0 = Debug|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Release|Win32.ActiveCfg = Release|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Release|Win32.Build.0 = Release|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Debug|Win32.ActiveCfg = Debug|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Debug|Win32.Build.0 = Debug|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Release|Win32.ActiveCfg = Release|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Release|Win32.Build.0 = Release|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Debug|Win32.ActiveCfg = Debug|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Debug|Win32.Build.0 = Debug|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Release|Win32.ActiveCfg = Release|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/win32/vs8/libevas.vcproj b/win32/vs8/libevas.vcproj deleted file mode 100644 index ddc2e27..0000000 --- a/win32/vs8/libevas.vcproj +++ /dev/null @@ -1,949 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/loader_eet.vcproj b/win32/vs8/loader_eet.vcproj deleted file mode 100644 index 686bcca..0000000 --- a/win32/vs8/loader_eet.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/loader_gif.vcproj b/win32/vs8/loader_gif.vcproj deleted file mode 100644 index 7be2861..0000000 --- a/win32/vs8/loader_gif.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/loader_jpeg.vcproj b/win32/vs8/loader_jpeg.vcproj deleted file mode 100644 index 581e2ce..0000000 --- a/win32/vs8/loader_jpeg.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/loader_pmaps.vcproj b/win32/vs8/loader_pmaps.vcproj deleted file mode 100644 index c18f46d..0000000 --- a/win32/vs8/loader_pmaps.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/loader_png.vcproj b/win32/vs8/loader_png.vcproj deleted file mode 100644 index 389a005..0000000 --- a/win32/vs8/loader_png.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/loader_tiff.vcproj b/win32/vs8/loader_tiff.vcproj deleted file mode 100644 index 0dd15a2..0000000 --- a/win32/vs8/loader_tiff.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/loader_xpm.vcproj b/win32/vs8/loader_xpm.vcproj deleted file mode 100644 index 26b881f..0000000 --- a/win32/vs8/loader_xpm.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/modules.sln b/win32/vs8/modules.sln deleted file mode 100644 index e4fabf2..0000000 --- a/win32/vs8/modules.sln +++ /dev/null @@ -1,110 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_direct3d", "engine_direct3d.vcproj", "{689B4F2B-666D-439F-9BF3-1203D813DE3F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_buffer", "engine_buffer.vcproj", "{FF8981EF-618E-45B9-9F03-738D7E2914AF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_software_win32_gdi", "engine_software_win32_gdi.vcproj", "{3367A64F-A08E-4F27-8303-54A3BBB01D5A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_software_generic", "engine_software_generic.vcproj", "{1E24C1AF-62F2-4EC0-AD94-7363C0534E36}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_gl_glew", "engine_gl_glew.vcproj", "{38C9AD78-8461-4A33-A31B-7DA62AB3BBE9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_software_ddraw", "engine_software_ddraw.vcproj", "{C71D20DF-3BAB-4BFF-80D4-508E7548358B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_eet", "loader_eet.vcproj", "{EB7D2089-3FDB-40F4-B90C-716752FFF786}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_gif", "loader_gif.vcproj", "{C3534833-592F-4450-911E-9C35E205D488}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_jpeg", "loader_jpeg.vcproj", "{EAC1F90F-87EC-4E3F-8924-0F67FA2302CC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_pmaps", "loader_pmaps.vcproj", "{73EB3790-3A72-436C-87CD-FE8747198F06}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_png", "loader_png.vcproj", "{866F2513-EEE6-4BD7-9C3E-1FF83682424A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_tiff", "loader_tiff.vcproj", "{94C11E2D-6DA2-4CB9-AC08-4068A660C8C9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_xpm", "loader_xpm.vcproj", "{9063A709-C228-4CA1-822B-75A51F38817F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "saver_eet", "saver_eet.vcproj", "{9BF0AB1E-3B95-45BC-BDFB-5C2879577A1E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "saver_png", "saver_png.vcproj", "{455EB58B-C65C-4793-841A-22C62D58ADD5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "saver_tiff", "saver_tiff.vcproj", "{9BC8E8CC-955C-4D41-91D4-BADBB87830AF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Debug|Win32.ActiveCfg = Debug|Win32 - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Debug|Win32.Build.0 = Debug|Win32 - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Release|Win32.ActiveCfg = Release|Win32 - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Release|Win32.Build.0 = Release|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Debug|Win32.ActiveCfg = Debug|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Debug|Win32.Build.0 = Debug|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Release|Win32.ActiveCfg = Release|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Release|Win32.Build.0 = Release|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Debug|Win32.ActiveCfg = Debug|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Debug|Win32.Build.0 = Debug|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Release|Win32.ActiveCfg = Release|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Release|Win32.Build.0 = Release|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Debug|Win32.ActiveCfg = Debug|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Debug|Win32.Build.0 = Debug|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Release|Win32.ActiveCfg = Release|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Release|Win32.Build.0 = Release|Win32 - {38C9AD78-8461-4A33-A31B-7DA62AB3BBE9}.Debug|Win32.ActiveCfg = Debug|Win32 - {38C9AD78-8461-4A33-A31B-7DA62AB3BBE9}.Debug|Win32.Build.0 = Debug|Win32 - {38C9AD78-8461-4A33-A31B-7DA62AB3BBE9}.Release|Win32.ActiveCfg = Release|Win32 - {38C9AD78-8461-4A33-A31B-7DA62AB3BBE9}.Release|Win32.Build.0 = Release|Win32 - {C71D20DF-3BAB-4BFF-80D4-508E7548358B}.Debug|Win32.ActiveCfg = Debug|Win32 - {C71D20DF-3BAB-4BFF-80D4-508E7548358B}.Debug|Win32.Build.0 = Debug|Win32 - {C71D20DF-3BAB-4BFF-80D4-508E7548358B}.Release|Win32.ActiveCfg = Release|Win32 - {C71D20DF-3BAB-4BFF-80D4-508E7548358B}.Release|Win32.Build.0 = Release|Win32 - {EB7D2089-3FDB-40F4-B90C-716752FFF786}.Debug|Win32.ActiveCfg = Debug|Win32 - {EB7D2089-3FDB-40F4-B90C-716752FFF786}.Debug|Win32.Build.0 = Debug|Win32 - {EB7D2089-3FDB-40F4-B90C-716752FFF786}.Release|Win32.ActiveCfg = Release|Win32 - {EB7D2089-3FDB-40F4-B90C-716752FFF786}.Release|Win32.Build.0 = Release|Win32 - {C3534833-592F-4450-911E-9C35E205D488}.Debug|Win32.ActiveCfg = Debug|Win32 - {C3534833-592F-4450-911E-9C35E205D488}.Debug|Win32.Build.0 = Debug|Win32 - {C3534833-592F-4450-911E-9C35E205D488}.Release|Win32.ActiveCfg = Release|Win32 - {C3534833-592F-4450-911E-9C35E205D488}.Release|Win32.Build.0 = Release|Win32 - {EAC1F90F-87EC-4E3F-8924-0F67FA2302CC}.Debug|Win32.ActiveCfg = Debug|Win32 - {EAC1F90F-87EC-4E3F-8924-0F67FA2302CC}.Debug|Win32.Build.0 = Debug|Win32 - {EAC1F90F-87EC-4E3F-8924-0F67FA2302CC}.Release|Win32.ActiveCfg = Release|Win32 - {EAC1F90F-87EC-4E3F-8924-0F67FA2302CC}.Release|Win32.Build.0 = Release|Win32 - {73EB3790-3A72-436C-87CD-FE8747198F06}.Debug|Win32.ActiveCfg = Debug|Win32 - {73EB3790-3A72-436C-87CD-FE8747198F06}.Debug|Win32.Build.0 = Debug|Win32 - {73EB3790-3A72-436C-87CD-FE8747198F06}.Release|Win32.ActiveCfg = Release|Win32 - {73EB3790-3A72-436C-87CD-FE8747198F06}.Release|Win32.Build.0 = Release|Win32 - {866F2513-EEE6-4BD7-9C3E-1FF83682424A}.Debug|Win32.ActiveCfg = Debug|Win32 - {866F2513-EEE6-4BD7-9C3E-1FF83682424A}.Debug|Win32.Build.0 = Debug|Win32 - {866F2513-EEE6-4BD7-9C3E-1FF83682424A}.Release|Win32.ActiveCfg = Release|Win32 - {866F2513-EEE6-4BD7-9C3E-1FF83682424A}.Release|Win32.Build.0 = Release|Win32 - {94C11E2D-6DA2-4CB9-AC08-4068A660C8C9}.Debug|Win32.ActiveCfg = Debug|Win32 - {94C11E2D-6DA2-4CB9-AC08-4068A660C8C9}.Debug|Win32.Build.0 = Debug|Win32 - {94C11E2D-6DA2-4CB9-AC08-4068A660C8C9}.Release|Win32.ActiveCfg = Release|Win32 - {94C11E2D-6DA2-4CB9-AC08-4068A660C8C9}.Release|Win32.Build.0 = Release|Win32 - {9063A709-C228-4CA1-822B-75A51F38817F}.Debug|Win32.ActiveCfg = Debug|Win32 - {9063A709-C228-4CA1-822B-75A51F38817F}.Debug|Win32.Build.0 = Debug|Win32 - {9063A709-C228-4CA1-822B-75A51F38817F}.Release|Win32.ActiveCfg = Release|Win32 - {9063A709-C228-4CA1-822B-75A51F38817F}.Release|Win32.Build.0 = Release|Win32 - {9BF0AB1E-3B95-45BC-BDFB-5C2879577A1E}.Debug|Win32.ActiveCfg = Debug|Win32 - {9BF0AB1E-3B95-45BC-BDFB-5C2879577A1E}.Debug|Win32.Build.0 = Debug|Win32 - {9BF0AB1E-3B95-45BC-BDFB-5C2879577A1E}.Release|Win32.ActiveCfg = Release|Win32 - {9BF0AB1E-3B95-45BC-BDFB-5C2879577A1E}.Release|Win32.Build.0 = Release|Win32 - {455EB58B-C65C-4793-841A-22C62D58ADD5}.Debug|Win32.ActiveCfg = Debug|Win32 - {455EB58B-C65C-4793-841A-22C62D58ADD5}.Debug|Win32.Build.0 = Debug|Win32 - {455EB58B-C65C-4793-841A-22C62D58ADD5}.Release|Win32.ActiveCfg = Release|Win32 - {455EB58B-C65C-4793-841A-22C62D58ADD5}.Release|Win32.Build.0 = Release|Win32 - {9BC8E8CC-955C-4D41-91D4-BADBB87830AF}.Debug|Win32.ActiveCfg = Debug|Win32 - {9BC8E8CC-955C-4D41-91D4-BADBB87830AF}.Debug|Win32.Build.0 = Debug|Win32 - {9BC8E8CC-955C-4D41-91D4-BADBB87830AF}.Release|Win32.ActiveCfg = Release|Win32 - {9BC8E8CC-955C-4D41-91D4-BADBB87830AF}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/win32/vs8/saver_eet.vcproj b/win32/vs8/saver_eet.vcproj deleted file mode 100644 index aaa46b8..0000000 --- a/win32/vs8/saver_eet.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/saver_png.vcproj b/win32/vs8/saver_png.vcproj deleted file mode 100644 index a2e866a..0000000 --- a/win32/vs8/saver_png.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/saver_tiff.vcproj b/win32/vs8/saver_tiff.vcproj deleted file mode 100644 index 531ec2c..0000000 --- a/win32/vs8/saver_tiff.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs8/start.bat b/win32/vs8/start.bat deleted file mode 100644 index 5f6b049..0000000 --- a/win32/vs8/start.bat +++ /dev/null @@ -1,35 +0,0 @@ -@echo off -rem Warning: environment is set for Win32 platform. - -set PROJECT_TYPE=vs8 - -pushd .. -call set_env.bat -popd - -if "%EXT_DIR%" == "" goto END - -rem Setup common Win32 environment variables - -set SolutionDirectory=%cd% -set DebugOutputDirectory=%SolutionDirectory%\out -set ReleaseOutputDirectory=%SolutionDirectory%\out -set DebugLibraryDirectory=%SolutionDirectory%\out -set ReleaseLibraryDirectory=%SolutionDirectory%\out -set TemporaryDirectory=%SolutionDirectory%\temp - -set LIB=%DebugLibraryDirectory%;%ReleaseLibraryDirectory%;%LIB% - -rem Check for basic requirements -if "%VS80COMNTOOLS%" == "" ( - echo ERROR: Microsoft Visual Studio 2005 is not installed. - pause - goto END -) - -rem Setting environment for using Microsoft Visual Studio 2005 x86 tools. -call "%VS80COMNTOOLS%vsvars32.bat" - -evas.sln - -:END \ No newline at end of file diff --git a/win32/vs8/start_modules.bat b/win32/vs8/start_modules.bat deleted file mode 100644 index 067d810..0000000 --- a/win32/vs8/start_modules.bat +++ /dev/null @@ -1,35 +0,0 @@ -@echo off -rem Warning: environment is set for Win32 platform. - -set PROJECT_TYPE=vs8 - -pushd .. -call set_env.bat -popd - -if "%EXT_DIR%" == "" goto END - -rem Setup common Win32 environment variables - -set SolutionDirectory=%cd% -set DebugOutputDirectory=%SolutionDirectory%\out\modules -set ReleaseOutputDirectory=%SolutionDirectory%\out\modules -set DebugLibraryDirectory=%SolutionDirectory%\out\modules -set ReleaseLibraryDirectory=%SolutionDirectory%\out\modules -set TemporaryDirectory=%SolutionDirectory%\temp - -set LIB=%DebugLibraryDirectory%\..;%DebugLibraryDirectory%;%ReleaseLibraryDirectory%;%LIB% - -rem Check for basic requirements -if "%VS80COMNTOOLS%" == "" ( - echo ERROR: Microsoft Visual Studio 2005 is not installed. - pause - goto END -) - -rem Setting environment for using Microsoft Visual Studio 2005 x86 tools. -call "%VS80COMNTOOLS%vsvars32.bat" - -modules.sln - -:END \ No newline at end of file diff --git a/win32/vs9/engine_buffer.vcproj b/win32/vs9/engine_buffer.vcproj deleted file mode 100644 index 44512e5..0000000 --- a/win32/vs9/engine_buffer.vcproj +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/engine_software_gdi.vcproj b/win32/vs9/engine_software_gdi.vcproj deleted file mode 100644 index 7a61467..0000000 --- a/win32/vs9/engine_software_gdi.vcproj +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/engine_software_generic.vcproj b/win32/vs9/engine_software_generic.vcproj deleted file mode 100644 index 1c5766a..0000000 --- a/win32/vs9/engine_software_generic.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/evas.sln b/win32/vs9/evas.sln deleted file mode 100644 index 24020bc..0000000 --- a/win32/vs9/evas.sln +++ /dev/null @@ -1,132 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libevas", "libevas.vcproj", "{689B4F2B-666D-439F-9BF3-1203D813DE3F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_buffer", "engine_buffer.vcproj", "{FF8981EF-618E-45B9-9F03-738D7E2914AF}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_software_generic", "engine_software_generic.vcproj", "{1E24C1AF-62F2-4EC0-AD94-7363C0534E36}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_software_gdi", "engine_software_gdi.vcproj", "{3367A64F-A08E-4F27-8303-54A3BBB01D5A}" - ProjectSection(ProjectDependencies) = postProject - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36} = {1E24C1AF-62F2-4EC0-AD94-7363C0534E36} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_software_ddraw", "engine_software_ddraw.vcproj", "{C71D20DF-3BAB-4BFF-80D4-508E7548358B}" - ProjectSection(ProjectDependencies) = postProject - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36} = {1E24C1AF-62F2-4EC0-AD94-7363C0534E36} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_eet", "loader_eet.vcproj", "{EB7D2089-3FDB-40F4-B90C-716752FFF786}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_gif", "loader_gif.vcproj", "{C3534833-592F-4450-911E-9C35E205D488}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_jpeg", "loader_jpeg.vcproj", "{EAC1F90F-87EC-4E3F-8924-0F67FA2302CC}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_pmaps", "loader_pmaps.vcproj", "{73EB3790-3A72-436C-87CD-FE8747198F06}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_png", "loader_png.vcproj", "{866F2513-EEE6-4BD7-9C3E-1FF83682424A}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_tiff", "loader_tiff.vcproj", "{94C11E2D-6DA2-4CB9-AC08-4068A660C8C9}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader_xpm", "loader_xpm.vcproj", "{9063A709-C228-4CA1-822B-75A51F38817F}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "saver_eet", "saver_eet.vcproj", "{9BF0AB1E-3B95-45BC-BDFB-5C2879577A1E}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "saver_png", "saver_png.vcproj", "{455EB58B-C65C-4793-841A-22C62D58ADD5}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "saver_tiff", "saver_tiff.vcproj", "{9BC8E8CC-955C-4D41-91D4-BADBB87830AF}" - ProjectSection(ProjectDependencies) = postProject - {689B4F2B-666D-439F-9BF3-1203D813DE3F} = {689B4F2B-666D-439F-9BF3-1203D813DE3F} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Debug|Win32.ActiveCfg = Debug|Win32 - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Debug|Win32.Build.0 = Debug|Win32 - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Release|Win32.ActiveCfg = Release|Win32 - {689B4F2B-666D-439F-9BF3-1203D813DE3F}.Release|Win32.Build.0 = Release|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Debug|Win32.ActiveCfg = Debug|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Debug|Win32.Build.0 = Debug|Win32 - {FF8981EF-618E-45B9-9F03-738D7E2914AF}.Release|Win32.ActiveCfg = Release|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Debug|Win32.ActiveCfg = Debug|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Debug|Win32.Build.0 = Debug|Win32 - {1E24C1AF-62F2-4EC0-AD94-7363C0534E36}.Release|Win32.ActiveCfg = Release|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Debug|Win32.ActiveCfg = Debug|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Debug|Win32.Build.0 = Debug|Win32 - {3367A64F-A08E-4F27-8303-54A3BBB01D5A}.Release|Win32.ActiveCfg = Release|Win32 - {C71D20DF-3BAB-4BFF-80D4-508E7548358B}.Debug|Win32.ActiveCfg = Debug|Win32 - {C71D20DF-3BAB-4BFF-80D4-508E7548358B}.Debug|Win32.Build.0 = Debug|Win32 - {C71D20DF-3BAB-4BFF-80D4-508E7548358B}.Release|Win32.ActiveCfg = Release|Win32 - {EB7D2089-3FDB-40F4-B90C-716752FFF786}.Debug|Win32.ActiveCfg = Debug|Win32 - {EB7D2089-3FDB-40F4-B90C-716752FFF786}.Debug|Win32.Build.0 = Debug|Win32 - {EB7D2089-3FDB-40F4-B90C-716752FFF786}.Release|Win32.ActiveCfg = Release|Win32 - {C3534833-592F-4450-911E-9C35E205D488}.Debug|Win32.ActiveCfg = Debug|Win32 - {C3534833-592F-4450-911E-9C35E205D488}.Debug|Win32.Build.0 = Debug|Win32 - {C3534833-592F-4450-911E-9C35E205D488}.Release|Win32.ActiveCfg = Release|Win32 - {EAC1F90F-87EC-4E3F-8924-0F67FA2302CC}.Debug|Win32.ActiveCfg = Debug|Win32 - {EAC1F90F-87EC-4E3F-8924-0F67FA2302CC}.Debug|Win32.Build.0 = Debug|Win32 - {EAC1F90F-87EC-4E3F-8924-0F67FA2302CC}.Release|Win32.ActiveCfg = Release|Win32 - {73EB3790-3A72-436C-87CD-FE8747198F06}.Debug|Win32.ActiveCfg = Debug|Win32 - {73EB3790-3A72-436C-87CD-FE8747198F06}.Debug|Win32.Build.0 = Debug|Win32 - {73EB3790-3A72-436C-87CD-FE8747198F06}.Release|Win32.ActiveCfg = Release|Win32 - {866F2513-EEE6-4BD7-9C3E-1FF83682424A}.Debug|Win32.ActiveCfg = Debug|Win32 - {866F2513-EEE6-4BD7-9C3E-1FF83682424A}.Debug|Win32.Build.0 = Debug|Win32 - {866F2513-EEE6-4BD7-9C3E-1FF83682424A}.Release|Win32.ActiveCfg = Release|Win32 - {94C11E2D-6DA2-4CB9-AC08-4068A660C8C9}.Debug|Win32.ActiveCfg = Debug|Win32 - {94C11E2D-6DA2-4CB9-AC08-4068A660C8C9}.Debug|Win32.Build.0 = Debug|Win32 - {94C11E2D-6DA2-4CB9-AC08-4068A660C8C9}.Release|Win32.ActiveCfg = Release|Win32 - {9063A709-C228-4CA1-822B-75A51F38817F}.Debug|Win32.ActiveCfg = Debug|Win32 - {9063A709-C228-4CA1-822B-75A51F38817F}.Debug|Win32.Build.0 = Debug|Win32 - {9063A709-C228-4CA1-822B-75A51F38817F}.Release|Win32.ActiveCfg = Release|Win32 - {9BF0AB1E-3B95-45BC-BDFB-5C2879577A1E}.Debug|Win32.ActiveCfg = Debug|Win32 - {9BF0AB1E-3B95-45BC-BDFB-5C2879577A1E}.Debug|Win32.Build.0 = Debug|Win32 - {9BF0AB1E-3B95-45BC-BDFB-5C2879577A1E}.Release|Win32.ActiveCfg = Release|Win32 - {455EB58B-C65C-4793-841A-22C62D58ADD5}.Debug|Win32.ActiveCfg = Debug|Win32 - {455EB58B-C65C-4793-841A-22C62D58ADD5}.Debug|Win32.Build.0 = Debug|Win32 - {455EB58B-C65C-4793-841A-22C62D58ADD5}.Release|Win32.ActiveCfg = Release|Win32 - {9BC8E8CC-955C-4D41-91D4-BADBB87830AF}.Debug|Win32.ActiveCfg = Debug|Win32 - {9BC8E8CC-955C-4D41-91D4-BADBB87830AF}.Debug|Win32.Build.0 = Debug|Win32 - {9BC8E8CC-955C-4D41-91D4-BADBB87830AF}.Release|Win32.ActiveCfg = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/win32/vs9/libevas.vcproj b/win32/vs9/libevas.vcproj deleted file mode 100644 index 918d830..0000000 --- a/win32/vs9/libevas.vcproj +++ /dev/null @@ -1,936 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/loader_eet.vcproj b/win32/vs9/loader_eet.vcproj deleted file mode 100644 index d132d04..0000000 --- a/win32/vs9/loader_eet.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/loader_gif.vcproj b/win32/vs9/loader_gif.vcproj deleted file mode 100644 index 299c7d5..0000000 --- a/win32/vs9/loader_gif.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/loader_jpeg.vcproj b/win32/vs9/loader_jpeg.vcproj deleted file mode 100644 index 21bfbe6..0000000 --- a/win32/vs9/loader_jpeg.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/loader_pmaps.vcproj b/win32/vs9/loader_pmaps.vcproj deleted file mode 100644 index 9ed557a..0000000 --- a/win32/vs9/loader_pmaps.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/loader_png.vcproj b/win32/vs9/loader_png.vcproj deleted file mode 100644 index f1223e7..0000000 --- a/win32/vs9/loader_png.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/loader_tiff.vcproj b/win32/vs9/loader_tiff.vcproj deleted file mode 100644 index db188ff..0000000 --- a/win32/vs9/loader_tiff.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/loader_xpm.vcproj b/win32/vs9/loader_xpm.vcproj deleted file mode 100644 index 4e02946..0000000 --- a/win32/vs9/loader_xpm.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/saver_eet.vcproj b/win32/vs9/saver_eet.vcproj deleted file mode 100644 index 6b84c97..0000000 --- a/win32/vs9/saver_eet.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/saver_png.vcproj b/win32/vs9/saver_png.vcproj deleted file mode 100644 index 55cf49e..0000000 --- a/win32/vs9/saver_png.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/win32/vs9/saver_tiff.vcproj b/win32/vs9/saver_tiff.vcproj deleted file mode 100644 index de0d8b6..0000000 --- a/win32/vs9/saver_tiff.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -