svn update: 51458 (latest:51480)
authorJeahwan Kim <jae.hwan.kim@samsung.com>
Tue, 7 Sep 2010 23:57:19 +0000 (08:57 +0900)
committerJeahwan Kim <jae.hwan.kim@samsung.com>
Tue, 7 Sep 2010 23:57:19 +0000 (08:57 +0900)
261 files changed:
COPYING
ChangeLog
INSTALL
Makefile.am
README.in
configure.ac
debian/SVN_REV
doc/img/edoxy.css [new file with mode: 0644]
evas-software-8-x11.pc.in [new file with mode: 0644]
evas.pc.in
m4/efl_pthread.m4
m4/evas_check_engine.m4
m4/evas_check_loader.m4
src/bin/Makefile.am
src/bin/evas_cserve_main.c
src/lib/Evas.h
src/lib/Makefile.am
src/lib/cache/evas_cache_engine_image.c
src/lib/cache/evas_cache_image.c
src/lib/cache/evas_preload.c
src/lib/canvas/Makefile.am
src/lib/canvas/evas_callbacks.c
src/lib/canvas/evas_main.c
src/lib/canvas/evas_object_box.c
src/lib/canvas/evas_object_image.c
src/lib/canvas/evas_object_line.c
src/lib/canvas/evas_object_main.c
src/lib/canvas/evas_object_polygon.c
src/lib/canvas/evas_object_text.c
src/lib/canvas/evas_object_textblock.c
src/lib/canvas/evas_render.c
src/lib/canvas/evas_transform.c
src/lib/cserve/evas_cs_server.c
src/lib/engines/Makefile.am
src/lib/engines/common/Makefile.am
src/lib/engines/common/evas_bidi_utils.c [new file with mode: 0644]
src/lib/engines/common/evas_bidi_utils.h [new file with mode: 0644]
src/lib/engines/common/evas_blend.h
src/lib/engines/common/evas_blend_main.c
src/lib/engines/common/evas_blend_private.h
src/lib/engines/common/evas_blit_main.c
src/lib/engines/common/evas_convert_color.c
src/lib/engines/common/evas_convert_color.h
src/lib/engines/common/evas_convert_colorspace.c
src/lib/engines/common/evas_convert_colorspace.h
src/lib/engines/common/evas_convert_gry_1.c
src/lib/engines/common/evas_convert_gry_1.h
src/lib/engines/common/evas_convert_gry_4.c
src/lib/engines/common/evas_convert_gry_4.h
src/lib/engines/common/evas_convert_gry_8.c
src/lib/engines/common/evas_convert_gry_8.h
src/lib/engines/common/evas_convert_grypal_6.c
src/lib/engines/common/evas_convert_grypal_6.h
src/lib/engines/common/evas_convert_main.c
src/lib/engines/common/evas_convert_main.h
src/lib/engines/common/evas_convert_rgb_16.c
src/lib/engines/common/evas_convert_rgb_16.h
src/lib/engines/common/evas_convert_rgb_24.c
src/lib/engines/common/evas_convert_rgb_24.h
src/lib/engines/common/evas_convert_rgb_32.c
src/lib/engines/common/evas_convert_rgb_32.h
src/lib/engines/common/evas_convert_rgb_8.c
src/lib/engines/common/evas_convert_rgb_8.h
src/lib/engines/common/evas_convert_yuv.c
src/lib/engines/common/evas_convert_yuv.h
src/lib/engines/common/evas_cpu.c
src/lib/engines/common/evas_draw.h
src/lib/engines/common/evas_draw_main.c
src/lib/engines/common/evas_encoding.c [new file with mode: 0644]
src/lib/engines/common/evas_encoding.h [new file with mode: 0644]
src/lib/engines/common/evas_font.h
src/lib/engines/common/evas_font_draw.c
src/lib/engines/common/evas_font_load.c
src/lib/engines/common/evas_font_main.c
src/lib/engines/common/evas_font_private.h
src/lib/engines/common/evas_font_query.c
src/lib/engines/common/evas_image_data.c
src/lib/engines/common/evas_image_load.c
src/lib/engines/common/evas_image_main.c
src/lib/engines/common/evas_image_save.c
src/lib/engines/common/evas_image_scalecache.c
src/lib/engines/common/evas_line_main.c
src/lib/engines/common/evas_map_image.c
src/lib/engines/common/evas_map_image.h
src/lib/engines/common/evas_map_image_core.c
src/lib/engines/common/evas_map_image_internal.c
src/lib/engines/common/evas_map_image_loop.c
src/lib/engines/common/evas_op_add/op_add_color_.c
src/lib/engines/common/evas_op_add/op_add_color_i386.c
src/lib/engines/common/evas_op_add/op_add_mask_color_.c
src/lib/engines/common/evas_op_add/op_add_mask_color_i386.c
src/lib/engines/common/evas_op_add/op_add_pixel_.c
src/lib/engines/common/evas_op_add/op_add_pixel_color_.c
src/lib/engines/common/evas_op_add/op_add_pixel_color_i386.c
src/lib/engines/common/evas_op_add/op_add_pixel_i386.c
src/lib/engines/common/evas_op_add/op_add_pixel_mask_.c
src/lib/engines/common/evas_op_add/op_add_pixel_mask_i386.c
src/lib/engines/common/evas_op_add_main_.c
src/lib/engines/common/evas_op_blend/op_blend_color_.c
src/lib/engines/common/evas_op_blend/op_blend_color_i386.c
src/lib/engines/common/evas_op_blend/op_blend_color_neon.c
src/lib/engines/common/evas_op_blend/op_blend_mask_color_.c
src/lib/engines/common/evas_op_blend/op_blend_mask_color_i386.c
src/lib/engines/common/evas_op_blend/op_blend_mask_color_neon.c
src/lib/engines/common/evas_op_blend/op_blend_pixel_.c
src/lib/engines/common/evas_op_blend/op_blend_pixel_color_.c
src/lib/engines/common/evas_op_blend/op_blend_pixel_color_i386.c
src/lib/engines/common/evas_op_blend/op_blend_pixel_color_neon.c
src/lib/engines/common/evas_op_blend/op_blend_pixel_i386.c
src/lib/engines/common/evas_op_blend/op_blend_pixel_mask_.c
src/lib/engines/common/evas_op_blend/op_blend_pixel_mask_i386.c
src/lib/engines/common/evas_op_blend/op_blend_pixel_mask_neon.c
src/lib/engines/common/evas_op_blend/op_blend_pixel_neon.c
src/lib/engines/common/evas_op_copy/op_copy_color_.c
src/lib/engines/common/evas_op_copy/op_copy_color_i386.c
src/lib/engines/common/evas_op_copy/op_copy_color_neon.c
src/lib/engines/common/evas_op_copy/op_copy_mask_color_.c
src/lib/engines/common/evas_op_copy/op_copy_mask_color_i386.c
src/lib/engines/common/evas_op_copy/op_copy_mask_color_neon.c
src/lib/engines/common/evas_op_copy/op_copy_pixel_.c
src/lib/engines/common/evas_op_copy/op_copy_pixel_color_.c
src/lib/engines/common/evas_op_copy/op_copy_pixel_color_i386.c
src/lib/engines/common/evas_op_copy/op_copy_pixel_color_neon.c
src/lib/engines/common/evas_op_copy/op_copy_pixel_i386.c
src/lib/engines/common/evas_op_copy/op_copy_pixel_mask_.c
src/lib/engines/common/evas_op_copy/op_copy_pixel_mask_i386.c
src/lib/engines/common/evas_op_copy/op_copy_pixel_mask_neon.c
src/lib/engines/common/evas_op_copy/op_copy_pixel_neon.c
src/lib/engines/common/evas_op_copy_main_.c
src/lib/engines/common/evas_op_mask/op_mask_color_.c
src/lib/engines/common/evas_op_mask/op_mask_color_i386.c
src/lib/engines/common/evas_op_mask/op_mask_mask_color_.c
src/lib/engines/common/evas_op_mask/op_mask_mask_color_i386.c
src/lib/engines/common/evas_op_mask/op_mask_pixel_.c
src/lib/engines/common/evas_op_mask/op_mask_pixel_color_.c
src/lib/engines/common/evas_op_mask/op_mask_pixel_color_i386.c
src/lib/engines/common/evas_op_mask/op_mask_pixel_i386.c
src/lib/engines/common/evas_op_mask/op_mask_pixel_mask_.c
src/lib/engines/common/evas_op_mask/op_mask_pixel_mask_i386.c
src/lib/engines/common/evas_op_mul/op_mul_color_.c
src/lib/engines/common/evas_op_mul/op_mul_color_i386.c
src/lib/engines/common/evas_op_mul/op_mul_mask_color_.c
src/lib/engines/common/evas_op_mul/op_mul_mask_color_i386.c
src/lib/engines/common/evas_op_mul/op_mul_pixel_.c
src/lib/engines/common/evas_op_mul/op_mul_pixel_color_.c
src/lib/engines/common/evas_op_mul/op_mul_pixel_color_i386.c
src/lib/engines/common/evas_op_mul/op_mul_pixel_i386.c
src/lib/engines/common/evas_op_mul/op_mul_pixel_mask_.c
src/lib/engines/common/evas_op_mul/op_mul_pixel_mask_i386.c
src/lib/engines/common/evas_op_sub/op_sub_color_.c
src/lib/engines/common/evas_op_sub/op_sub_color_i386.c
src/lib/engines/common/evas_op_sub/op_sub_mask_color_.c
src/lib/engines/common/evas_op_sub/op_sub_mask_color_i386.c
src/lib/engines/common/evas_op_sub/op_sub_pixel_.c
src/lib/engines/common/evas_op_sub/op_sub_pixel_color_.c
src/lib/engines/common/evas_op_sub/op_sub_pixel_color_i386.c
src/lib/engines/common/evas_op_sub/op_sub_pixel_i386.c
src/lib/engines/common/evas_op_sub/op_sub_pixel_mask_.c
src/lib/engines/common/evas_op_sub/op_sub_pixel_mask_i386.c
src/lib/engines/common/evas_pipe.c
src/lib/engines/common/evas_pipe.h
src/lib/engines/common/evas_polygon_main.c
src/lib/engines/common/evas_rectangle_main.c
src/lib/engines/common/evas_scale_main.c
src/lib/engines/common/evas_scale_main.h
src/lib/engines/common/evas_scale_sample.c
src/lib/engines/common/evas_scale_smooth.c
src/lib/engines/common/evas_scale_smooth.h
src/lib/engines/common/evas_scale_smooth_scaler.c
src/lib/engines/common/evas_scale_span.c
src/lib/engines/common/evas_scale_span.h
src/lib/engines/common_16/evas_soft16_main.c
src/lib/engines/common_8/Makefile.am [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_dither_mask.c [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_font.c [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_image_scaled_sampled.c [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_image_unscaled.c [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_line.c [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_main.c [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_polygon.c [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_rectangle.c [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_scanline_blend.c [new file with mode: 0644]
src/lib/engines/common_8/evas_soft8_scanline_fill.c [new file with mode: 0644]
src/lib/file/evas_module.c
src/lib/imaging/evas_imaging.c
src/lib/include/Makefile.am
src/lib/include/evas_cairo_common.h
src/lib/include/evas_common.h
src/lib/include/evas_common_soft8.h [new file with mode: 0644]
src/lib/include/evas_private.h
src/lib/main.c
src/modules/engines/Makefile.am
src/modules/engines/buffer/Makefile.am
src/modules/engines/buffer/evas_engine.c
src/modules/engines/cairo_x11/Makefile.am
src/modules/engines/cairo_x11/evas_engine.c
src/modules/engines/direct3d/Makefile.am
src/modules/engines/direct3d/evas_engine.c
src/modules/engines/directfb/Makefile.am
src/modules/engines/directfb/evas_engine.c
src/modules/engines/fb/Makefile.am
src/modules/engines/fb/evas_engine.c
src/modules/engines/gl_common/evas_gl_common.h
src/modules/engines/gl_common/evas_gl_context.c
src/modules/engines/gl_common/evas_gl_image.c
src/modules/engines/gl_common/evas_gl_polygon.c
src/modules/engines/gl_common/evas_gl_texture.c
src/modules/engines/gl_glew/Makefile.am
src/modules/engines/gl_glew/evas_engine.c
src/modules/engines/gl_sdl/Makefile.am
src/modules/engines/gl_sdl/evas_engine.c
src/modules/engines/gl_x11/Makefile.am
src/modules/engines/gl_x11/evas_engine.c
src/modules/engines/gl_x11/evas_x_main.c
src/modules/engines/quartz/Makefile.am
src/modules/engines/quartz/evas_engine.c
src/modules/engines/quartz/evas_engine.h
src/modules/engines/quartz/evas_quartz_private.h
src/modules/engines/software_16/evas_engine.c
src/modules/engines/software_16_ddraw/Makefile.am
src/modules/engines/software_16_ddraw/evas_engine.c
src/modules/engines/software_16_sdl/Makefile.am
src/modules/engines/software_16_sdl/evas_engine.c
src/modules/engines/software_16_wince/Makefile.am
src/modules/engines/software_16_wince/evas_engine.c
src/modules/engines/software_16_x11/Makefile.am
src/modules/engines/software_16_x11/evas_engine.c
src/modules/engines/software_8/Makefile.am [new file with mode: 0644]
src/modules/engines/software_8/evas_engine.c [new file with mode: 0644]
src/modules/engines/software_8_x11/Evas_Engine_Software_8_X11.h [new file with mode: 0644]
src/modules/engines/software_8_x11/Makefile.am [new file with mode: 0644]
src/modules/engines/software_8_x11/evas_engine.c [new file with mode: 0644]
src/modules/engines/software_8_x11/evas_engine.h [new file with mode: 0644]
src/modules/engines/software_8_x11/evas_x_buffer.c [new file with mode: 0644]
src/modules/engines/software_ddraw/Makefile.am
src/modules/engines/software_ddraw/evas_engine.c
src/modules/engines/software_gdi/Makefile.am
src/modules/engines/software_gdi/evas_engine.c
src/modules/engines/software_generic/evas_engine.c
src/modules/engines/software_qtopia/Makefile.am
src/modules/engines/software_qtopia/evas_engine.c
src/modules/engines/software_sdl/Makefile.am
src/modules/engines/software_sdl/evas_engine.c
src/modules/engines/software_x11/Makefile.am
src/modules/engines/software_x11/evas_engine.c
src/modules/engines/xrender_x11/Makefile.am
src/modules/engines/xrender_x11/evas_engine.c
src/modules/engines/xrender_x11/evas_engine.h
src/modules/engines/xrender_x11/evas_engine_xcb_render.c
src/modules/engines/xrender_x11/evas_engine_xlib_render.c
src/modules/loaders/bmp/evas_image_load_bmp.c
src/modules/loaders/gif/evas_image_load_gif.c
src/modules/loaders/jpeg/evas_image_load_jpeg.c
src/modules/loaders/pmaps/evas_image_load_pmaps.c
src/modules/loaders/png/evas_image_load_png.c
src/modules/loaders/tga/evas_image_load_tga.c
src/modules/loaders/tiff/evas_image_load_tiff.c
src/modules/loaders/xpm/evas_image_load_xpm.c
src/modules/savers/png/evas_image_save_png.c
win32/vs8/libevas.vcproj
win32/vs9/libevas.vcproj

diff --git a/COPYING b/COPYING
index 9690c3f..61a2b02 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -1,32 +1,25 @@
+Copyright notice for Evas:
 
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+Copyright (C) 2000-2010 Carsten Haitzler and various contributors (see AUTHORS)
 
-The above copyright notice and this permission notice shall be included in
-all copies of the Software and its Copyright notices. In addition publicly
-documented acknowledgment must be given that this software has been used if no
-source code of this software is made available publicly. Making the source
-available publicly means including the source for this software with the
-distribution, or a method to get this software via some reasonable mechanism
-(electronic transfer via a network or media) as well as making an offer to
-supply the source on request. This Copyright notice serves as an offer to
-supply the source on on request as well. Instead of this, supplying
-acknowledgments of use of this software in either Copyright notices, Manuals,
-Publicity and Marketing documents or any documentation provided with any
-product containing this software. This License does not apply to any software
-that links to the libraries provided by this software (statically or
-dynamically), but only to the software provided.
+All rights reserved.
 
-Please see the COPYING-PLAIN for a plain-english explanation of this notice
-and its intent.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright 
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
index e69de29..bbcf3c6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -0,0 +1,4 @@
+20YY-MM-2DD  NAME OF RELEASER
+
+       MAJOR.MINOR.MICRO release
+        
diff --git a/INSTALL b/INSTALL
index a4b76cb..23e5f25 100644 (file)
--- a/INSTALL
+++ b/INSTALL
-COMPILING and INSTALLING:
+Installation Instructions
+*************************
 
-please see the README file.
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
 
-NB: you will need pkgconfig package (available for debian and for redhat -
-try www.rpmfind.net if you're lost, or go to the pkgconfig website:
-http://www.freedesktop.org/software/pkgconfig/ ) if your are taking this from 
-CVS and having to run ./autogen.sh)
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
 
-NOTE: for compilation with MinGW, fnmatch.h is probably missing.
-      That file can be found here:
-http://www.koders.com/c/fid2B518462CB1EED3D4E31E271DB83CD1582F6EEBE.aspx
-      It should be installed in the mingw include directory.
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).  Here is a another example:
+
+     /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
 
-NOTE: for the OpenGL engine on Windows, the glew library:
-http://glew.sourceforge.net/
-      is needed.
index 1e000f4..7556599 100644 (file)
@@ -30,6 +30,7 @@ evas-software-buffer.pc \
 evas-software-qtopia.pc \
 evas-software-x11.pc \
 evas-software-16-x11.pc \
+evas-software-8-x11.pc \
 evas-xrender-x11.pc \
 evas-xrender-xcb.pc \
 evas-software-gdi.pc \
@@ -54,7 +55,6 @@ bin_SCRIPTS =
 EXTRA_DIST = \
 AUTHORS \
 COPYING \
-COPYING-PLAIN \
 autogen.sh \
 README.in \
 README \
@@ -69,6 +69,7 @@ evas-software-buffer.pc.in \
 evas-software-qtopia.pc.in \
 evas-software-x11.pc.in \
 evas-software-16-x11.pc.in \
+evas-software-8-x11.pc.in \
 evas-xrender-x11.pc.in \
 evas-xrender-xcb.pc.in \
 evas-software-gdi.pc.in \
@@ -90,6 +91,10 @@ if BUILD_ENGINE_SOFTWARE_16_X11
 pkgconfig_DATA += evas-software-16-x11.pc
 endif
 
+if BUILD_ENGINE_SOFTWARE_8_X11
+pkgconfig_DATA += evas-software-8-x11.pc
+endif
+
 if BUILD_ENGINE_DIRECTFB
 pkgconfig_DATA += evas-directfb.pc
 endif
index 1e3e6c9..305e0bb 100644 (file)
--- a/README.in
+++ b/README.in
@@ -1,63 +1,84 @@
-Evas @VERSION@
+Evas @VERSION@ ALPHA
 
-Evas is a clean display canvas API for several target display systems
-that can draw anti-aliased text, smooth super and sub-sampled scaled
-images, alpha-blend objects much and more.
+******************************************************************************
 
+ FOR ANY ISSUES PLEASE EMAIL:
+ enlightenment-devel@lists.sourceforge.net
+  
+******************************************************************************
+  
 Requirements:
 -------------
 
 Must:
-  libc libm freetype2.1.9+
+  libc
+  libm
+  eina (1.0.0 or better)
+  freetype (2.1.9 or better)
 
 Recommended:
-  libX11 libXext libXrender fontconfig libpng libjpeg eet libpthread
+  libX11
+  libXext
+  libXrender
+  fontconfig
+  libpng
+  libjpeg
+  eet (1.4.0 or better)
+  libpthread
 
 Optional:
   XCB SDL OpenGL Qtopia librsvg libtiff libgif edb DirectFB
 
---------------------------------------------------------------------------
-Evas as of 0.9.9 has a new (and incompatible) API. Why? It's much cleaner
-and more compact. Designed for portable access to different display systems.
-It is also much more optimised internally, uses much less ram than previous
-Evas libraries, and is tiny. Evas when compiled for the Ipaq is a grand
-total of 191Kb (thats all of Evas minus libjpeg, libpng, libz (required for 
-libpng), and minus freetype (required for font rendering)). I have plans that 
-may involve having an alternative font engine other than freetype to minimise
-requirements, and having a native (optional) image loader for an image
-format that may end up being custom to evas, but will minimise code &
-requirements especially for embedded use.
-
-Evas uses very little RAM too (try profiling it in memprof if you want to 
+Evas is a clean display canvas API for several target display systems
+that can draw anti-aliased text, smooth super and sub-sampled scaled
+images, alpha-blend objects much and more.
+
+Evas is designed to be portable to different display systems. Evas uses very
+little RAM too (try profiling it in memprof if you want to 
 know) most of the ram allocated, if you look, is for freetype itself,
 image pixel data, and font glyph data. You can't really avoid this, though
 evas tries to share this data as much as possible and not duplicate where it
-can. Feel free to point me at sensible memory optimisations etc. though :) I 
+can. Feel free to point me at sensible memory optimizations etc. though :) I 
 want this baby to be lean, mean tiny, fast and do everything from your 
 massive multi-cpu desktop with gobs of ram and disk to a tiny watch.
 
 Evas also supports full UTF-8 for text object strings, thus allowing for
-full internationalised text strings (if your font gives you all the
+full internationalized text strings (if your font gives you all the
 characters). I've tested with quite a few fonts and it works quite well.
 Though this requires a unicode compatible font with unicode charmap support
 (cyberbit is quite good actually as a font). For now Evas draws the fonts
 only from left to right, so arabic, hebrew etc. won't display quite right,
 direction-wise, but the characters do.
 
---------------------------------------------------------------------------
+------------------------------------------------------------------------------
+COMPILING AND INSTALLING:
+
+  ./configure
+  make
+(as root unless you are installing in your users directories):
+  make install
+
 if you want to know what options to enable
 ./configure --help
 
+Evas's rendering code assumes a decently optimizing compiler. For
+example gcc with -O2 -march=nocona for example (compile for core2 duo
+x86 or better). Yoiu may choose not to compile for a very modern
+architecture, and Evas still has MMX/SSE, NEON and other hand-crafted
+assembly, but not for everything, so make use of your compiler
+optimizing as much as possible. At least use -O2 or equivalents.
+
 Notes:
   the small dither mask is faster on the ipaq, but is not as good looking. on
-    desktop machines it makes no speed difference so only use
-    --enable-small-dither-mask if you are compiling for the ipaq
+  desktop machines it makes no speed difference so only use
+  --enable-small-dither-mask if you are compiling for the ipaq
   you need at least 1 image loader if you want to load images.
   gcc 3.0.x on solaris screws up the jpeg code so erroring out doesn't work.
     use gcc 3.2 on solaris.
 
---------------------------------------------------------------------------
-notes on features:
+notes on features (--enable-FEATURE enables it and --disable-FEATURE
+disables it, some being enabled or disabled by default or if
+dependencies are found):
 
 SCALING:
 --enable-scale-sample
@@ -70,9 +91,7 @@ speed vs. quality tradeoff
 --enable-scale-smooth
 
 this is the nicest looking scaler that is not that much slower than
-tri-linear, but it looks really good. it also uses mipmaps and is optimised
-heavily. it is recommended to always use this unless you are really
-struggling for speed and are qilling to forego the quality
+tri-linear, but it looks really good.
 
 DITHERING:
 --enable-small-dither-mask
@@ -80,13 +99,33 @@ DITHERING:
 this uses a 4x4 dither mask instead of 128x128. on desktop boxes these days
 (pentium, pentium2, amd etc.) the speed difference is not really measurable,
 but the quality of the 128x128 dither mask is quite a lot better. patterns
-of dithering are much less noticable, so it is recommended to not enable
+of dithering are much less noticeable, so it is recommended to not enable
 this unless you are struggling for speed. the compaq ipaq for example shows
 a slowdown with this large a dither mask so enabling a small dither mask is
-recommended unless you really want to forego the speed.
+recommended unless you really want to forgo the speed.
+
+--enable-line-dither-mask
+
+this is a faster alternative to the small or large dither masks above.
+this dithers only on an alternating-line basis. this only provides 1
+intermediate "dither" level whose odd and even pixels alternate
+between the 2 closest colors available, but it is very fast. almost as
+fast as no dithering. quality though will not be as good as small or
+default "large" dither masks.
+
+--enable-no-dither-mask
+
+this disables dithering entirely. this is the fastest option, but the
+lowest quality. not suggested in general unless you are really in need
+of an extra few percent speed and are willing to have fairly awful
+quality. but in general this is the standard rendering for most
+"realtime graphics" if it has to drop to lower bit-depths, so it's
+not anything unusual. just in the evas world the quality is considered
+poor enough to be discouraged as evas's internal rendering is so much
+higher quality.
 
 ENGINES:
---enable-software-x11
+--enable-software-xlib
 
 this enables the software x11 rendering engine that renders to X drawable
 targets using highly optimised software routines. there is no hardware
@@ -95,22 +134,21 @@ This is a godo generic engine that is fast and can run in X for good
 development and debugging purposes.
 
 --enable-software-xcb
+
 this enable the software xcb rendering engine. It allows the same
-features than the software x11 engine. It require the XCB and XCBImage
+features than the software xlib engine. It require the XCB and XCBImage
 libraries. For the test programs, XCBICCCM is also needed.
 
 --enable-fb
 
 this is the software framebuffer driving engine. this uses the linux
-framebuffer device (/dev/fb<x>) and will currently just inherit the current
+framebuffer device (/dev/fb{X}) and will currently just inherit the current
 framebuffer settings on the fb device and use them to run in. this engine is
-almost fully functional except for the fb management itself. i'd be quite
-happy for people to help out with fixing up the fb init & management code to
-properly set up a vt and release it etc. this engine is specifically geared
-towards peoel writing minimalist display systems for embedded devices such
-as the ipaq, zaurus, etc. it also scales up to high-res desktop systems as
-well and performs outstandingly. i have measured up to 67% speedup over X11
-using the fb driver insetad of X11.
+almost fully functional except for the fb management itself. this engine is
+specifically geared towards people writing minimalist display systems for
+embedded devices such as the ipaq, zaurus, etc. it also scales up to high-res
+desktop systems as
+well.
 
 --enable-direcfb
 
@@ -119,41 +157,160 @@ linux to access the framebuffer with (or maybe without) acceleration. for
 people making set-top boxes or just wanting an alternative to X this is
 really good. it may also be useful for embedded devices supported by
 directfb that offer acceleration (otherwise the fb driver will likely be
-faster).
+faster). as such this engine is in relative disrepair and is not
+maintained. use with great care.
+
+--enable-buffer
+
+this enables the memory buffer rendering engine. this engine renders
+to a region of memory that is considered to be a 32bit ARGB buffer of
+pixels, allowing the results of rendering to be directly read out or
+used again for other purposes.
+
+--enable-xrender-x11
+
+this engine uses the xrender api to do drawing via (possibly)
+accelerated 2d or 3d hardware means. as such xrender has never lived
+up to its possible performance levels and has fallen into disrepair.
+use this engine at your own risk. it is considered to be "bitrotting"
+and be unmaintained.
+
+--enable-xrender-xcb
+
+this is the same as xrender-x11 but uses/exposes an xcb api.
+
+--enable-gl-x11
+
+this is the opengl engine. it is intended for an x11 target (via xlib)
+rather than framebuffer (even if you use EGL, the EGL flavor is
+expected to be an x11 one). it is a full opengl based rendering engine
+with all rendering implemented as a texture + triangle pipeline and
+more. it also supports opengl-es2.0 and is reliant on modern opengl2.0+
+shader support. this engine also supports the native surface api for
+adopting pixmaps directly to textures for compositing.
+
+--enable-gl-flavor-gles
+
+this enables the opengl-es 2.0 flavor of opengl (as opposed to desktop
+opengl) when building evas's gl-x11 engine above. this will be needed
+if you are building evas for opengl-es 2.0 enabled embedded devices.
+evas works on several opengl-es 2.0 compliant gpu's and gains more
+testing and optimization regularly. it is also capable of
+texture-from-pixmap support in opengl-es like it is in desktop opengl.
+
+--enable-gles-variety-sgx
+
+this tells evas that you are building the gl-es engine for a
+shader-compiler "sgx style" opengl-es 2.0 implementation. this is
+where the shader compiler is provided at runtime and can accept the
+shader glsl source and work
+
+--enable-gles-variety-s3c6410
 
---enable-sdl
+this tells evas that you have an s3c6410 style opengl-es
+implementation that has an offline shader compiler and that needs
+pre-compiled shader binaries (provided with evas). this has not been
+tested in quite a while as the drivers and environment for this system
+have gone missing
+
+--enable-software-gdi
+
+windows gdi based engine for evas
+
+--enable-software-ddraw
+
+windows direct-draw engine for evas
+
+--enable-direct3d
+
+evas direct3d engine (experimental)
+
+--enable-quartz
+
+macos-x quartz engine (experimental)
+
+--enable-gl-glew
+
+opengl glew based gl engine for evas (experimental)
+
+--enable-software-sdl
 
 this is the sdl engine that uses sdl library (http://www.libsdl.org). This
-library should work on many operating system.
+library should work on many operating system. the buffer is
+software-rendered with evas's default software rendering core.
+
+--enable-gl-sdl
+
+opengl (and opengl-es2.0) rendering engine that uses sdl as the front
+end interface. see --enable-gl-x11 etc. for information.
+
+--enable-software-8-x11
+
+8bit only rendering core. intended for greyscale output on things like
+e-paper or simplistic greyscale LCD devices which have no color.
+
+--enable-software-16-x11
+
+16bit specific renderer. lower quality than the default. also limited
+in abilities. in a state of disrepair. do not use.
 
+--enable-software-16-ddraw
+
+16bit renderer for direct-draw. same as software-16-x11 - don't use.
+in disrepair.
+
+--enable-software-16-wince
+
+same as software-16-ddraw but for windows-ce. in disrepair. don't use.
 
 CPU:
 --enable-cpu-c
 
-this enabled the c code. you can actually build the code withotu the c
+this enabled the c code. you can actually build the code without the c
 fallback code and only have the mmx routines for example. it is suggested to
-always use this regardless uness you have some definite size issues with the
+always use this regardless unless you have some definite size issues with the
 code.
 
 --enable-cpu-mmx
 
-this enables the mmx optimised routines. this works for pentium, pentium2,
+this enables the mmx optimized routines. this works for pentium, pentium2,
 pentium3, pentium4, athlon and duron processors. it can get quite
 considerable speedups, souse it if you can. ppc owners just have to live with
 the c fallback functions unfortunately as no one has provided any ALTIVEC asm 
 routines yet. :) arm owners will also have to rely on the c fallback
 routines as i haven't managed to come up with any arm assembly that actually
-can beat the c code (when compiled with all optimisations) in speed.
+can beat the c code (when compiled with all optimizations) in speed.
 
 --enable-cpu-sse
 
-this enables sse optimizations availbale in he pentium3 and 4 cpus (not
+this enables sse optimizations available in he pentium3 and 4 cpus (not
 athlon and duron or pentium 2 or pentium cpu's). ppc owners just have to
 live with the c fallback functions unfortunately as no one has provided any
 ALTIVEC asm routines yet. :) arm owners will also have to rely on the c
 fallback routines as i haven't managed to come up with any arm assembly that 
 actually can beat the c code (when compiled with all optimizations) in speed.
 
+--enable-cpu-neon
+
+This enables support for the Arm Cortex-A8 and later Neon register
+set.  In particular it will use neon optimised code for rotations and
+drawing with the software engines.  Open GL based renderers will gain
+nothing from the use of neon.
+
+To use neon with gcc-4.4 you need a post-2009 gcc and options
+something like: -mcpu=cortex-a8 -mfloat-abi=softfp -mfpu=neon
+Note that this slightly slows down non-optimised parts of evas  but
+the gains in drawing are more then worth it overall.
+
+This is enabled by default, and turns off if a small test program is
+unable to compile.
+       
+Performance is at least 50%, and in some real world tests approaches
+100%.
+
+If you have any issues with neon, please report them to either the
+edevel mailing list or Brett Nash <nash@nash.id.uau>
+
 IMAGE LOADERS:
 --enable-image-loader-png
 
@@ -164,9 +321,85 @@ for now this is the only loader so you may as well include it.
 
 --enable-image-loader-jpeg
 
-this enables the loader code that loads jpeg files using libjpeg.
+this enables the loader code that loads jpeg files using libjpeg. this
+loader also supports load options to pre-scale jpeg images down to
+provide much faster load times while also getting downscaling by 1/2,
+1/4 or 1/8th the size in each dimension for "free". with an added
+patch to libjpeg7, it can also fast-decode a specific region of a jpeg
+file (without the patch it take a slow-path to do this).
+
+--enable-image-loader-edb
+
+edb image loader- can load images inside edb database files. not very
+useful as edb itself is no longer used by enlightenment. may be
+removed at some point, so unless you have a burning need for this,
+don't use edb files to store image data and rely on this loader
+
+--enable-image-loader-eet
+
+loads image data from eet files. eet files are the backing for edje
+storage, so this is needed for edje to work. it is very useful as it
+can load an image from anywhere in the eet archive by key value so eet
+files are like "zip" files where you can pack a whole lot of image and
+other data together and just pick out the pieces you need at runtime.
+requires the eet library.
+
+--enable-image-loader-gif
+
+gif image loader. gif is an obsolete format, but due to its longevity,
+sitll has lots of existing data around.
+
+--enable-image-loader-pmaps
+
+ppm/pnm/pgm image loader that can load the "pnm" style image format.
+not very common, but the files are simple raw RGB, greyscale image or
+bitmap data in binary or ascii format
+
+--enable-image-loader-svg
+
+this loader can load svg files via librsvg (thus it is a dependency).
+this loader supports load options to set the dpi to decode the svg at
+etc. which can then be used to create scalable images that scale to
+any size without becoming blocky or blurry, if the source is an svg
+file.
+
+--enable-image-loader-tiff
+
+this loader uses libtiff to load tiff image files
+
+--enable-image-loader-xpm
+
+this is an xpm format image loader. xpm format images are ascii files
+that look like c/c++ source code that contain images. these files are
+old-fashioned unix+x11 images you may encounter, but are inefficient
+for storage and decoding and have been superseded by png files in
+almost every way
+
+--enable-image-loader-bmp
+
+this enables the bmp image format loader. note that there seems to be
+a disagreement on 32bit bmp format images where alpha channels are
+concerned and you may run into issues with bmps generated by the gimp
+that have alpha channels. there is a problem where they don't seem to
+be spec-conformant.
+
+--enable-image-loader-tga
+
+this loader load tga format files. these files are very old-fashioned
+but found often in the 3d graphics world.
+
+FONT LOADERS:
+--enable-font-loader-eet
+
+this loader can load font (ttf) files directly from eet archives like
+the eet image loader. requires the eet library
 
 CONVERTERS:
+--enable-convert-yuv
+
+this enables an optimized yuv (yv12 601 colorspace) to ARGB32
+converter in evas
+
 --enable-convert-16-rgb-565
 
 the most common converter you'll want for 16bpp. this means 5 bits for red,
@@ -194,11 +427,11 @@ fill 16bits, with unused bits in the color masks. X on the ipaq advertises
 it as a full 16bpp 565 display (i can't remember what the linux framebuffer
 advertised it as) and so many lumps of code can be fooled into rendering
 data badly because they think the output will look as the expect. This
-renderer assuems the upper 4 bits fo each color primitie only are
+renderer assumes the upper 4 bits fo each color primitive only are
 significant and renders accordingly. this produces nice quality images on
 the ipaq and even still works in 16bpp 565 on your pc. it is highly
 recommended to use this renderer if your target is an ipaq or your device
-dislpays similar qualities of the ipaq for display purposes.
+displays similar qualities of the ipaq for display purposes.
 
 --enable-convert-16-rgb-rot-0
 
@@ -208,68 +441,195 @@ only ever want to do portrait mode - perhaps like on an ipaq embedded device)
 
 --enable-convert-16-rgb-rot-270
 
-this enables the portrait mode (270 degree rotation) converteres for 16bpp.
+this enables the portrait mode (270 degree rotation) converters for 16bpp.
 this is the standard display mode for things like pocketpc on the ipaq and
-the zaurus etc. thsi si a optimized part of the rendering pipeline to allow
+the zaurus etc. this is an optimized part of the rendering pipeline to allow
 portrait display with a much lower overhead than doing it through X.
 
+--enable-convert-16-rgb-rot-180
+
+same as --enable-convert-16-rgb-rot-270 but for 180 degrees
+
+--enable-convert-16-rgb-rot-90
+
+same as --enable-convert-16-rgb-rot-270 but for 90 degrees
+
 --enable-convert-24-rgb-888
 
-To be documented...
+this converts evas's 32bit ARGB to 24bit RGB packed format for output
+if needed
 
 --enable-convert-24-bgr-888
 
-To be documented...
+this converts evas's 32bit ARGB to 24bit packed BGR format for output
+if needed
 
 --enable-convert-32-rgb-8888
 
-To be documented...
+32bit RGB output conversion support. byteswapping compared to evas's
+native colorspace
 
 --enable-convert-32-bgr-8888
 
-To be documented...
+conversion (reduces toa memory copy) from evas's native colorspace to
+the same color format.
 
 --enable-convert-32-rgb-rot-0
 
-To be documented...
+copies without rotation evas's native image format
 
 --enable-convert-32-rgb-rot-270
 
-To be documented...
+copies evas's native ARGB32 pixels but at a rotation of 270 degrees.
 
-...
+--enable-convert-32-rgb-rot-180
 
+same as --enable-convert-32-rgb-rot-270 but for 180 degrees
 
-------------------------------------------------------------------------------
-COMPILING AND INSTALLING:
+--enable-convert-32-rgb-rot-90
 
-  ./configure
-  make
-(as root unless youa re installing in your users directories):
-  make install
-      
-------------------------------------------------------------------------------
-BUILDING PACKAGES:
+same as --enable-convert-32-rgb-rot-270 but for 90 degrees
 
-RPM: To build rpm packages:
-  
-  sudo rpm -ta @PACKAGE@-@VERSION@.tar.gz
+--enable-convert-24-rgb-ezx
+
+a special colorspace handler for 18bit color packed into 24bit output
+(where only 6 bits per r, g and b byte are used). the only known
+platform that did this was the motorola esx based phones that used
+qtopia originally and have open ezx ports for them.
+
+--enable-convert-8-gry-1
+
+enable 8bit gray to 1 bit black & white converter
+
+--enable-convert-8-gry-16
+
+8bit grey to 16 level grayscale converter
+
+--enable-convert-8-grayscale-64
+
+8bit grey to 64 level grayscale converter
+
+--enable-convert-8-rgb-332
+
+enable converter from 32bit ARGB to 8bit color "332" colorspace (3bits
+red, 3 bits green, 2 bits blue)
+
+--enable-convert-8-rgb-666
 
-You will find rpm packages in your system /usr/src/redhat/* dirs (note you may
-not need to use sudo or root if you have your own ~/.rpmrc. see rpm documents
-for more details)
+enable converter from 32bit ARGB to 8bit color "216" "websafe" 
+colorspace (6 values for red, 6 for green and 6 for blue - 6x6x6 being
+216 colors).
 
-DEB: To build deb packages:
+--enable-convert-8-rgb-232
 
-  tar zvf @PACKAGE@-@VERSION@.tar.gz
-  cd @PACKAGE@-@VERSION@
-  dpkg-buildpackage -us -uc -rfakeroot
-  cd ..
-  rm -rf @PACKAGE@-@VERSION@
+same as convert-8-rgb-332 but 2 bits red, 3 green, 2 blue
 
-You will find all the debian source, binary etc. packages put in the directory
-where you first untarred the source tarball.
+--enable-convert-8-rgb-222
 
+same as convert-8-rgb-332 but 2 bits red, 2 green, 2 blue
+
+--enable-convert-8-rgb-221
+
+same as convert-8-rgb-332 but 2 bits red, 2 green, 1 blue
+
+--enable-convert-8-rgb-121
+
+same as convert-8-rgb-332 but 1 bit red, 2 green, 1 blue
+
+--enable-convert-8-rgb-111
+
+same as convert-8-rgb-332 but 1 bit red, 1 green, 1 blue. this is the
+lowest sized colorspace supported for rgb (3bits, 8 color).
+
+MISC:
+--enable-pthreads
+
+this enables pthread support in evas so multiple threads may run
+internally for parallel rendering, loading etc.
+
+--enable-async-events
+
+this provides the ability for evas to have an asynchronous event
+notification pipe to provide events when background threads are done
+with tasks, like pre-loading image files
+
+--enable-async-preload
+
+evas can load images (preload) them in the background using a thread
+if you ask it to, and provide events when done. this goes hand-in-hand
+with --enable-pthreads and --enable-async-events. you really want all
+of these available.
+
+--enable-async-render
+
+this enables a software multi-frame threaded renderer. this will
+allocate (for example) 2 frames to 2 cores, with one core of the cpu
+rendering the previous frame while the next frame starts rendering on
+another core in the meantime allowing for higher framerates with
+software rendering, using more cpu resources that are available on
+modern multi-core cpu's.
+
+--enable-word-cache
+
+Cache rendered words and draw them as a single object, instead of
+individual characters.  This is a big gain for things like neon which
+draw large runs effectively.
+
+However it is useless on GL and similar back-ends as the cost in
+sending a word sized texture kills the performance gain (and GL is
+pretty good at drawing lots of small things anyway).
+
+By default words (strings) of more then 50 characters are not cached.
+The system caches 40 words by default, but this can be changed by
+setting EVAS_WORD_CACHE_MAX_WORDS to another number.  Setting it to 0
+will disable word-cache at run time.
+
+Text based benchmarks are 50-100% quicker.
+
+If you have any issues with word caching, please report them to either
+the e-devel mailing list or Brett Nash <nash@nash.id.uau>
+
+For GL see metric caching...
+
+--enable-metric-cache
+
+Metric caching saves character metrics between characters in words.
+This enables it to render words much quicker as it avoids things like
+space calculations and kerning calculation.
+
+The cache seize is also controlled by  EVAS_WORD_CACHE_MAX_WORDS
+
+It is useful for GL in particular, although software engines do get
+some gain.
+
+Generally it is recommended you enable either word or metric caching,
+depending on your engine use.  If you are using software, enable word
+caching (and neon on arm if you can), for GL, turn on metric caching.
+
+If you have any issues with metric caching, please report them to either
+the e-devel mailing list or Brett Nash <nash@nash.id.uau>
+
+--enable-fontconfig
+
+this enables fontconfig support for loading font files by using
+generic fontconfig font names and styles. you really should use this
+by default on any linux/unix platform for universal font support.
+
+--enable-fribidi
+
+this enables support for the fribidi library to have right to left and
+left to right font rendering so languges such as arabic, hebrew and
+other "RTL" langauges display properly.
+
+--enable-evas-magic-debug
+
+this allows oyu to enable and disable evas's extra magic number
+checks.  these allow better stability with runtime object magic
+"number" checks to make sure you are accessing a real object in memory
+of the right type, and will avoid doing "bad things" if they detect
+the wrong object type being passed in. if you are absolutely sure your
+system has no bugs in accessing objects of the wrong type with the
+wrong calls, you can gain some small performance by disabling this.
 
 NOTES:
 
@@ -280,3 +640,12 @@ To enable the async renderer compile with:
   --enable-async-render
 and also runtime set this environment variable:
   export EVAS_RENDER_MODE=non-blocking
+
+For compilation with MinGW, fnmatch.h is probably missing. That file can be
+found here:
+  http://www.koders.com/c/fid2B518462CB1EED3D4E31E271DB83CD1582F6EEBE.aspx
+It should be installed in the mingw include directory.
+            
+For the OpenGL engine on Windows, the glew library is needed:
+  http://glew.sourceforge.net/
+                  
index ec0ab30..dbd6cde 100644 (file)
@@ -1,18 +1,17 @@
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
-m4_define([v_maj], [0])
-m4_define([v_min], [9])
-m4_define([v_mic], [9])
-m4_define([v_rev], m4_esyscmd([(svnversion . | grep -v exported || echo 0) | awk -F : '{printf("%s\n", $1);}' | tr -d ' :MSP\n']))
+m4_define([v_maj], [1])
+m4_define([v_min], [0])
+m4_define([v_mic], [0])
+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
-dnl m4_undefine([v_rev])
+m4_undefine([v_rev])
 ##--   When doing snapshots - change soname. remove dnl on below line
-m4_define([relname], [ver-pre-svn-06])
-m4_define([v_rel], [-release relname])
+dnl m4_define([relname], [ver-pre-svn-07])
+dnl m4_define([v_rel], [-release relname])
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
-m4_ifdef([v_rev], [m4_define([v_ver], [v_maj.v_min.v_mic.v_rev])],
-[m4_define([v_ver], [v_maj.v_min.v_mic])])
+m4_ifdef([v_rev], [m4_define([v_ver], [v_maj.v_min.v_mic.v_rev])], [m4_define([v_ver], [v_maj.v_min.v_mic])])
 m4_define([lt_rev], m4_eval(v_maj + v_min))
 m4_define([lt_cur], v_mic)
 m4_define([lt_age], v_min)
@@ -32,7 +31,7 @@ AC_CACHE_CHECK([whether the Objective C compiler works],
                 AC_LANG_POP([Objective C])])
 ])
 
-AC_INIT([evas], [v_ver], [enlightenment-devel@lists.sourceforge.net])
+AC_INIT([evas], [v_ver-alpha], [enlightenment-devel@lists.sourceforge.net])
 AC_PREREQ([2.52])
 AC_CONFIG_SRCDIR([configure.ac])
 AC_CONFIG_MACRO_DIR([m4])
@@ -62,6 +61,8 @@ AC_SUBST(version_info)
 AC_SUBST(release_info)
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+VMAJ=v_maj
+AC_SUBST(VMAJ)
 
 EFL_CHECK_PATH_MAX
 
@@ -72,7 +73,7 @@ case "$host_os" in
       MODULE_ARCH="$host_os-$host_cpu"
       ;;
    *)
-      MODULE_ARCH="$host_os-$host_cpu-relname"
+      MODULE_ARCH="$host_os-$host_cpu-v_maj.v_min.v_mic"
       ;;
 esac
 AC_SUBST(MODULE_ARCH)
@@ -104,6 +105,7 @@ want_evas_engine_software_sdl="no"
 want_evas_engine_fb="no"
 want_evas_engine_directfb="no"
 want_evas_engine_software_qtopia="no"
+want_evas_engine_software_8_x11="no"
 want_evas_engine_software_16_x11="no"
 want_evas_engine_software_16_ddraw="no"
 want_evas_engine_software_16_wince="no"
@@ -145,7 +147,9 @@ case "$host_os" in
       ;;
    *)
       want_evas_engine_software_xlib="auto"
+      want_evas_engine_gl_x11="auto"
       want_evas_engine_xrender_x11="auto"
+      want_evas_engine_software_8_x11="auto"
       want_evas_engine_software_16_x11="auto"
       ;;
 esac
@@ -223,12 +227,12 @@ esac
 ## strong dependencies
 
 # Eina
-PKG_CHECK_MODULES([EINA], [eina-0])
+PKG_CHECK_MODULES([EINA], [eina >= 1.0.0])
 
 # Freetype
 PKG_CHECK_MODULES([FREETYPE], [freetype2 >= 9.3.0])
 
-requirement_evas="freetype2 eina-0 ${requirement_evas}"
+requirement_evas="freetype2 eina >= 1.0.0 ${requirement_evas}"
 
 ## optional dependencies
 
@@ -276,7 +280,7 @@ AC_ARG_ENABLE([fribidi],
 
 if test "x${want_fribidi}" = "xyes" -o "x${want_fribidi}" = "xauto" ; then
    PKG_CHECK_MODULES([FRIBIDI],
-      [fribidi],
+      [fribidi >= 0.19.2],
       [
        have_fribidi="yes"
        AC_DEFINE(HAVE_FRIBIDI, 1, [have fribidi support])
@@ -480,10 +484,27 @@ AC_ARG_ENABLE(gles-variety-s3c6410,
   ]
 )
 
+if test "x$gl_flavor_gles" = "xyes"; then
+  eng=""
+  if test "x$gles_variety_sgx" = "xyes"; then eng="x"$eng; fi
+  if test "x$gles_variety_s3c6410" = "xyes"; then eng="x"$eng; fi
+  if test "x$eng" = "xx"; then
+    eng=""
+  else
+     AC_MSG_ERROR(
+       [Please enable just 1 OpenGL-ES flavor. Choices are:
+          --enable-gles-variety-sgx (Most GL-ES2 GPUs with shader compiler)
+          --enable-gles-variety-s3c6410 (s3c6410 with offline shader compiler)
+        You will also need to enable the OpenGL engine for X11 with:
+          --enable-gl-x11
+       ])
+  fi
+fi
+
 #####################################################################
 ## Engines
 
-EVAS_CHECK_ENGINE([buffer], [${want_evas_engine_buffer}], [no], [Buffer])
+EVAS_CHECK_ENGINE([buffer], [${want_evas_engine_buffer}], [yes], [Buffer])
 
 EVAS_CHECK_ENGINE([software-xlib], [${want_evas_engine_software_xlib}], [yes], [Software Xlib])
 
@@ -519,6 +540,8 @@ EVAS_CHECK_ENGINE([directfb], [${want_evas_engine_directfb}], [no], [DirectFB])
 # disable cairo engine for the release
 #EVAS_CHECK_ENGINE([software-qtopia], [${want_evas_engine_software_qtopia}], [no], [Qtopia])
 
+EVAS_CHECK_ENGINE([software-8-x11], [${want_evas_engine_software_8_x11}], [yes], [Software X11 8 bits grayscale])
+
 EVAS_CHECK_ENGINE([software-16-x11], [${want_evas_engine_software_16_x11}], [yes], [Software X11 16 bits])
 
 EVAS_CHECK_ENGINE([software-16-ddraw], [${want_evas_engine_software_16_ddraw}], [no], [Software DirectDraw 16 bits])
@@ -657,6 +680,28 @@ if test "x${have_static_software_16}" = "xyes"; then
    AC_DEFINE(EVAS_STATIC_BUILD_SOFTWARE_16, [1], [Build software 16 engine as part of libevas])
 fi
 
+# if software 8 x11 is enabled - build software_8 (the generic 8bit
+# engine).
+have_evas_engine_software_8="no"
+if test "x$have_evas_engine_software_8_x11" = "xyes" -o "x$have_evas_engine_software_8_x11" = "xstatic"; then
+   have_evas_engine_software_8="yes"
+fi
+AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_8, test "x$have_evas_engine_software_8" = "xyes")
+
+# if software 8 need to be build as part of libevas.so
+have_static_software_8="no"
+AC_ARG_ENABLE([static-software-8],
+   [AC_HELP_STRING([--enable-static-software-8], [Build software 8 engine as part of libevas])],
+   [have_static_software_8=${enableval}]
+)
+AC_MSG_CHECKING([Whether to build software 8 engine as part of libevas])
+AC_MSG_RESULT([${have_static_software_8}])
+
+AM_CONDITIONAL(EVAS_STATIC_BUILD_SOFTWARE_8, test "x${have_static_software_8}" = "xyes")
+if test "x${have_static_software_8}" = "xyes"; then
+   AC_DEFINE(EVAS_STATIC_BUILD_SOFTWARE_8, [1], [Build software 8 engine as part of libevas])
+fi
+
 #####################################################################
 ## Image loaders
 
@@ -1021,25 +1066,40 @@ case $host_cpu in
 esac
 AC_MSG_CHECKING(whether to build neon code)
 AC_ARG_ENABLE(cpu-neon,
-  AC_HELP_STRING([--enable-cpu-neon], [enable neon code]),
+  AC_HELP_STRING([--enable-cpu-neon], [enable neon code - with gcc you will need these CFLAGS for it to begin to work, and even then your gcc may have broken or non-existant support: -mcpu=cortex-a8 -mfloat-abi=softfp -mfpu=neon]),
   [
-      if test "x$enableval" = "xyes" ; then
-        AC_MSG_RESULT(yes)
-        AC_DEFINE(BUILD_NEON, 1, [Build NEON Code])
-        build_cpu_neon="yes"
+     if test "x$enableval" = "xyes" ; then
+       AC_TRY_COMPILE([#include <arm_neon.h>],
+        [asm volatile ("vqadd.u8 d0, d1, d0\n")],
+        [
+          AC_MSG_RESULT(yes)
+          AC_DEFINE(BUILD_NEON, 1, [Build NEON Code])
+          build_cpu_neon="yes"
+        ],[
+          AC_MSG_RESULT(no)
+          build_cpu_neon="no"
+        ])
       else
         AC_MSG_RESULT(no)
         build_cpu_neon="no"
       fi
   ],
   [
-    AC_MSG_RESULT($build_cpu_neon)
     if test "x$build_cpu_neon" = "xyes" ; then
-      AC_DEFINE(BUILD_NEON, 1, [Build NEON Code])
+       AC_TRY_COMPILE([#include <arm_neon.h>],
+        [asm volatile ("vqadd.u8 d0, d1, d0\n")],
+        [
+          AC_MSG_RESULT(yes)
+          AC_DEFINE(BUILD_NEON, 1, [Build NEON Code])
+          build_cpu_neon="yes"
+        ],[
+          AC_MSG_RESULT(no)
+          build_cpu_neon="no"
+        ])
     fi
   ]
 )
-
+     
 #######################################
 ## C
 build_cpu_c="yes"
@@ -1078,9 +1138,48 @@ AC_MSG_RESULT($want_evas_magic_debug)
 
 AM_CONDITIONAL(EVAS_MAGIC_DEBUG, test "x$want_evas_magic_debug" = "xyes")
 if test "x$want_evas_magic_debug" = "xyes"; then
-  AC_DEFINE(EVAS_MAGIC_DEBUG, 1, [complain when peole pass in wrong object types etc.])
+  AC_DEFINE(EVAS_MAGIC_DEBUG, 1, [complain when people pass in wrong object types etc.])
+fi
+
+
+#######################################
+## Word Caching
+want_word_cache="no"
+AC_MSG_CHECKING(whether to enable caching of rendered words)
+AC_ARG_ENABLE(word-cache,
+  AC_HELP_STRING(
+    [--enable-word-cache],
+    [Enable experimental word caching to speed up rendering [[default=disabled]]]
+  ),
+  [ want_word_cache="$enableval" ]
+)
+AC_MSG_RESULT($want_word_cache)
+
+AM_CONDITIONAL(WORD_CACHE, test "x$want_word_cache" = "xyes")
+if test "x$want_word_cache" = "xyes"; then
+  AC_DEFINE(WORD_CACHE, 1, [Experimental word caching to speed up text rendering.])
 fi
 
+#######################################
+## Metric Caching
+want_metric_cache="no"
+AC_MSG_CHECKING(whether to enable caching of rendered metrics)
+AC_ARG_ENABLE(metric-cache,
+  AC_HELP_STRING(
+    [--enable-metric-cache],
+    [Enable experimental metric caching to speed up rendering [[default=disabled]]]
+  ),
+  [ want_metric_cache="$enableval" ]
+)
+AC_MSG_RESULT($want_metric_cache)
+
+AM_CONDITIONAL(METRIC_CACHE, test "x$want_metric_cache" = "xyes")
+if test "x$want_metric_cache" = "xyes"; then
+  AC_DEFINE(METRIC_CACHE, 1, [Experimental metric caching to speed up text rendering.])
+fi
+
+
+
 #####################################################################
 ## ARGB engine options
 
@@ -1353,6 +1452,7 @@ evas-opengl-sdl.pc
 evas-quartz.pc
 evas-software-buffer.pc
 evas-software-x11.pc
+evas-software-8-x11.pc
 evas-software-16-x11.pc
 evas-xrender-x11.pc
 evas-xrender-xcb.pc
@@ -1381,6 +1481,7 @@ src/lib/engines/common/evas_op_copy/Makefile
 src/lib/engines/common/evas_op_mask/Makefile
 src/lib/engines/common/evas_op_mul/Makefile
 src/lib/engines/common/evas_op_sub/Makefile
+src/lib/engines/common_8/Makefile
 src/lib/engines/common_16/Makefile
 src/modules/Makefile
 src/modules/engines/Makefile
@@ -1400,6 +1501,8 @@ src/modules/engines/gl_sdl/Makefile
 src/modules/engines/quartz/Makefile
 src/modules/engines/xrender_x11/Makefile
 src/modules/engines/software_sdl/Makefile
+src/modules/engines/software_8/Makefile
+src/modules/engines/software_8_x11/Makefile
 src/modules/engines/software_16/Makefile
 src/modules/engines/software_16_x11/Makefile
 src/modules/engines/software_16_ddraw/Makefile
@@ -1474,6 +1577,7 @@ fi
 echo "  Software Framebuffer.......: $have_evas_engine_fb"
 echo "  DirectFB...................: $have_evas_engine_directfb"
 #echo "  Software Qtopia............: $have_evas_engine_software_qtopia"
+echo "  Software 8bit grayscale....: $have_evas_engine_software_8"
 echo "  Software 16bit ............: $have_evas_engine_software_16"
 echo "  Software 16bit X11.........: $have_evas_engine_software_16_x11"
 echo "  Software 16bit Directdraw..: $have_evas_engine_software_16_ddraw"
@@ -1521,6 +1625,9 @@ echo "  Async Pipe Rendering....: $build_async_render"
 echo "  Async Events............: $build_async_events"
 echo "  Async Image Preload.....: $build_async_preload"
 echo
+echo "  Word Cache..............: $want_word_cache"
+echo "  Metric Cache............: $want_metric_cache"
+echo
 echo "ARGB Software Engine Options:"
 echo "  Sampling Scaler.........: $scaler_sample"
 echo "  Smooth Scaler...........: $scaler_smooth"
index dd0e91d..a2ab89a 100644 (file)
@@ -1,2 +1,2 @@
-Revision 49550
-Last Changed Rev 49540
+Revision 51480
+Last Changed Rev 51458
diff --git a/doc/img/edoxy.css b/doc/img/edoxy.css
new file mode 100644 (file)
index 0000000..311ca23
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ * This file contain a custom doxygen style to match e.org graphics
+ */
+
+
+
+/* BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+       font-family: Geneva, Arial, Helvetica, sans-serif;
+}*/ 
+BODY, TD {
+       font-size: 12px;
+}
+H1 {
+       text-align: center;
+       font-size: 160%;
+}
+H2 {
+       font-size: 120%;
+}
+H3 {
+       font-size: 100%;
+}
+CAPTION { 
+       font-weight: bold 
+}
+DIV.qindex {
+       width: 100%;
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       padding: 2px;
+       line-height: 140%;
+}
+DIV.navpath {
+       width: 100%;
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       padding: 2px;
+       line-height: 140%;
+}
+DIV.navtab {
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       margin-right: 15px;
+       padding: 2px;
+}
+TD.navtab {
+       font-size: 70%;
+}
+A.qindex {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D;
+}
+A.qindex:visited {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D
+}
+A.qindex:hover {
+       text-decoration: none;
+       background-color: #ddddff;
+}
+A.qindexHL {
+       text-decoration: none;
+       font-weight: bold;
+       background-color: #6666cc;
+       color: #ffffff;
+       border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+       text-decoration: none;
+       background-color: #6666cc;
+       color: #ffffff;
+}
+A.qindexHL:visited { 
+       text-decoration: none; 
+       background-color: #6666cc; 
+       color: #ffffff 
+}
+A.el { 
+       text-decoration: none; 
+       font-weight: bold 
+}
+A.elRef { 
+       font-weight: bold 
+}
+A.code:link { 
+       text-decoration: none; 
+       font-weight: normal; 
+       color: #0000FF
+}
+A.code:visited { 
+       text-decoration: none; 
+       font-weight: normal; 
+       color: #0000FF
+}
+A.codeRef:link { 
+       font-weight: normal; 
+       color: #0000FF
+}
+A.codeRef:visited { 
+       font-weight: normal; 
+       color: #0000FF
+}
+A:hover, A:visited:hover { 
+       text-decoration: none;  
+       /* background-color: #f2f2ff; */
+       color: #000055;
+}
+A.anchor {
+       color: #000;
+}
+DL.el { 
+       margin-left: -1cm 
+}
+.fragment {
+       font-family: monospace, fixed;
+       font-size: 95%;
+}
+PRE.fragment {
+       border: 1px solid #CCCCCC;
+       background-color: #f5f5f5;
+       margin-top: 4px;
+       margin-bottom: 4px;
+       margin-left: 2px;
+       margin-right: 8px;
+       padding-left: 6px;
+       padding-right: 6px;
+       padding-top: 4px;
+       padding-bottom: 4px;
+}
+DIV.ah { 
+       background-color: black; 
+       font-weight: bold; 
+       color: #ffffff; 
+       margin-bottom: 3px; 
+       margin-top: 3px 
+}
+
+DIV.groupHeader {
+       margin-left: 16px;
+       margin-top: 12px;
+       margin-bottom: 6px;
+       font-weight: bold;
+}
+DIV.groupText { 
+       margin-left: 16px; 
+       font-style: italic; 
+       font-size: 90% 
+}
+/*BODY {
+       background: white;
+       color: black;
+       margin-right: 20px;
+       margin-left: 20px;
+}*/
+TD.indexkey {
+       background-color: #e8eef2;
+       font-weight: bold;
+       padding-right  : 10px;
+       padding-top    : 2px;
+       padding-left   : 10px;
+       padding-bottom : 2px;
+       margin-left    : 0px;
+       margin-right   : 0px;
+       margin-top     : 2px;
+       margin-bottom  : 2px;
+       border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+       background-color: #e8eef2;
+       font-style: italic;
+       padding-right  : 10px;
+       padding-top    : 2px;
+       padding-left   : 10px;
+       padding-bottom : 2px;
+       margin-left    : 0px;
+       margin-right   : 0px;
+       margin-top     : 2px;
+       margin-bottom  : 2px;
+       border: 1px solid #CCCCCC;
+}
+TR.memlist {
+       background-color: #f0f0f0; 
+}
+P.formulaDsp { 
+       text-align: center; 
+}
+IMG.formulaDsp {
+}
+IMG.formulaInl { 
+       vertical-align: middle; 
+}
+SPAN.keyword       { color: #008000 }
+SPAN.keywordtype   { color: #604020 }
+SPAN.keywordflow   { color: #e08000 }
+SPAN.comment       { color: #800000 }
+SPAN.preprocessor  { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral   { color: #008080 }
+SPAN.vhdldigit     { color: #ff00ff }
+SPAN.vhdlchar      { color: #000000 }
+SPAN.vhdlkeyword   { color: #700070 }
+SPAN.vhdllogic     { color: #ff0000 }
+
+.mdescLeft {
+       padding: 0px 8px 4px 8px;
+       font-size: 80%;
+       font-style: italic;
+       background-color: #FAFAFA;
+       border-top: 1px none #E0E0E0;
+       border-right: 1px none #E0E0E0;
+       border-bottom: 1px none #E0E0E0;
+       border-left: 1px none #E0E0E0;
+       margin: 0px;
+}
+.mdescRight {
+        padding: 0px 8px 4px 8px;
+       font-size: 80%;
+       font-style: italic;
+       background-color: #FAFAFA;
+       border-top: 1px none #E0E0E0;
+       border-right: 1px none #E0E0E0;
+       border-bottom: 1px none #E0E0E0;
+       border-left: 1px none #E0E0E0;
+       margin: 0px;
+}
+.memItemLeft {
+       padding: 1px 0px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: solid;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memItemRight {
+       padding: 1px 8px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: solid;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memTemplItemLeft {
+       padding: 1px 0px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: none;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memTemplItemRight {
+       padding: 1px 8px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: none;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.memTemplParams {
+       padding: 1px 0px 0px 8px;
+       margin: 4px;
+       border-top-width: 1px;
+       border-right-width: 1px;
+       border-bottom-width: 1px;
+       border-left-width: 1px;
+       border-top-color: #E0E0E0;
+       border-right-color: #E0E0E0;
+       border-bottom-color: #E0E0E0;
+       border-left-color: #E0E0E0;
+       border-top-style: solid;
+       border-right-style: none;
+       border-bottom-style: none;
+       border-left-style: none;
+       color: #606060;
+       background-color: #FAFAFA;
+       font-size: 80%;
+}
+.search { 
+       color: #003399;
+       font-weight: bold;
+}
+FORM.search {
+       margin-bottom: 0px;
+       margin-top: 0px;
+}
+INPUT.search { 
+       font-size: 75%;
+       color: #000080;
+       font-weight: normal;
+       background-color: #e8eef2;
+}
+TD.tiny { 
+       font-size: 75%;
+}
+a {
+       color: #1A41A8;
+}
+a:visited {
+       color: #2A3798;
+}
+.dirtab { 
+       padding: 4px;
+       border-collapse: collapse;
+       border: 1px solid #84b0c7;
+}
+TH.dirtab { 
+       background: #e8eef2;
+       font-weight: bold;
+}
+HR { 
+       height: 1px;
+       border: none;
+       border-top: 1px solid black;
+}
+
+/* Style for detailed member documentation */
+.memtemplate {
+       font-size: 80%;
+       color: #606060;
+       font-weight: normal;
+       margin-left: 3px;
+} 
+.memnav { 
+       background-color: #eeeeee;
+       border: 1px solid #dddddd;
+       text-align: center;
+       margin: 2px;
+       margin-right: 15px;
+       padding: 2px;
+}
+.memitem {
+       padding: 4px;
+       background-color: #eeeeee;
+       border-width: 1px;
+       border-style: solid;
+       border-color: #dddddd;
+       -moz-border-radius: 4px 4px 4px 4px;
+}
+.memname {
+       white-space: nowrap;
+       font-weight: bold;
+        color: #ffffff;
+}
+.memdoc{
+       padding-left: 10px;
+}
+.memproto {
+       background-color: #111111;
+       width: 100%;
+       border-width: 1px;
+       border-style: solid;
+       border-color: #000000;
+       font-weight: bold;
+       -moz-border-radius: 4px 4px 4px 4px;
+}
+.paramkey {
+       text-align: right;
+       color: #ffffff;
+}
+.paramtype {
+       white-space: nowrap;
+       color: #aaaaaa;
+}
+.paramname {
+       color: #ff0000;
+       font-style: italic;
+       white-space: nowrap;
+}
+/* End Styling for detailed member documentation */
+
+/* for the tree view */
+.ftvtree {
+       font-family: sans-serif;
+       margin:0.5em;
+}
+/* these are for tree view when used as main index */
+.directory { 
+       font-size: 9pt; 
+       font-weight: bold; 
+}
+.directory h3 { 
+       margin: 0px; 
+       margin-top: 1em; 
+       font-size: 11pt; 
+}
+
+/* The following two styles can be used to replace the root node title */
+/* with an image of your choice.  Simply uncomment the next two styles, */
+/* specify the name of your image and be sure to set 'height' to the */
+/* proper pixel height of your image. */
+
+/* .directory h3.swap { */
+/*     height: 61px; */
+/*     background-repeat: no-repeat; */
+/*     background-image: url("yourimage.gif"); */
+/* } */
+/* .directory h3.swap span { */
+/*     display: none; */
+/* } */
+
+.directory > h3 { 
+       margin-top: 0; 
+}
+.directory p { 
+       margin: 0px; 
+       white-space: nowrap; 
+}
+.directory div { 
+       display: none; 
+       margin: 0px; 
+}
+.directory img { 
+       vertical-align: -30%; 
+}
+/* these are for tree view when not used as main index */
+.directory-alt { 
+       font-size: 100%; 
+       font-weight: bold; 
+}
+.directory-alt h3 { 
+       margin: 0px; 
+       margin-top: 1em; 
+       font-size: 11pt; 
+}
+.directory-alt > h3 { 
+       margin-top: 0; 
+}
+.directory-alt p { 
+       margin: 0px; 
+       white-space: nowrap; 
+}
+.directory-alt div { 
+       display: none; 
+       margin: 0px; 
+}
+.directory-alt img { 
+       vertical-align: -30%; 
+}
+
diff --git a/evas-software-8-x11.pc.in b/evas-software-8-x11.pc.in
new file mode 100644 (file)
index 0000000..1a0e46d
--- /dev/null
@@ -0,0 +1,3 @@
+Name: evas-software-8-x11
+Description: Evas software X11 8bpp grayscale engine
+Version: @VERSION@
index f443bae..70755ed 100644 (file)
@@ -9,4 +9,4 @@ Description: Evas canvas display library
 Version: @VERSION@
 Libs: -L${libdir} -levas
 Libs.private: @EFL_FNMATCH_LIBS@ @pthread_libs@
-Cflags: -I${includedir}
+Cflags: -I${includedir}/evas-@VMAJ@
index 1894ad7..b90a045 100644 (file)
@@ -51,8 +51,8 @@ if test "x${_efl_enable_pthread}" = "xyes" || test "x${_efl_enable_pthread}" = "
 
    SAVE_CFLAGS=${CFLAGS}
    CFLAGS="${CFLAGS} ${_efl_pthread_cflags}"
-   SAVE_LDFLAGS=${LDFLAGS}
-   LDFLAGS="${LDFLAGS} ${_efl_pthread_libs}"
+   SAVE_LIBS=${LIBS}
+   LIBS="${LIBS} ${_efl_pthread_libs}"
    AC_LINK_IFELSE(
       [AC_LANG_PROGRAM([[
 #include <pthread.h>
@@ -64,7 +64,7 @@ id = pthread_self();
       [_efl_have_pthread="yes"],
       [_efl_have_pthread="no"])
    CFLAGS=${SAVE_CFLAGS}
-   LDFLAGS=${SAVE_LDFLAGS}
+   LIBS=${SAVE_LIBS}
 
 fi
 
@@ -96,8 +96,8 @@ if test "x${_efl_have_pthread}" = "xyes" && test "x$1" = "xyes" ; then
 
    SAVE_CFLAGS=${CFLAGS}
    CFLAGS="${CFLAGS} ${EFL_PTHREAD_CFLAGS}"
-   SAVE_LDFLAGS=${LDFLAGS}
-   LDFLAGS="${LDFLAGS} ${EFL_PTHREAD_LIBS}"
+   SAVE_LIBS=${LIBS}
+   LIBS="${LIBS} ${EFL_PTHREAD_LIBS}"
    AC_LINK_IFELSE(
       [AC_LANG_PROGRAM([[
 #include <pthread.h>
@@ -110,7 +110,7 @@ res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
       [_efl_have_pthread_spinlock="yes"],
       [_efl_have_pthread_spinlock="no"])
    CFLAGS=${SAVE_CFLAGS}
-   LDFLAGS=${SAVE_LDFLAGS}
+   LIBS=${SAVE_LIBS}
 
 fi
 
index 0454951..54ce5d2 100644 (file)
@@ -248,6 +248,8 @@ PKG_CHECK_MODULES([XCB],
     requirement="xcb xcb-shm xcb-image pixman-1"
     evas_engine_[]$1[]_cflags="${XCB_CFLAGS}"
     evas_engine_[]$1[]_libs="${XCB_LIBS}"
+   ],[
+    have_dep="no"
    ]
 )
 
@@ -283,6 +285,8 @@ PKG_CHECK_MODULES([XCBRENDER],
     requirement="xcb xcb-shm xcb-render xcb-image pixman-1"
     evas_engine_[]$1[]_cflags="${XCBRENDER_CFLAGS}"
     evas_engine_[]$1[]_libs="${XCBRENDER_LIBS}"
+   ],[
+    have_dep="no"
    ]
 )
 
@@ -655,6 +659,42 @@ fi
 
 ])
 
+dnl use: EVAS_CHECK_ENGINE_DEP_SOFTWARE_8_X11(engine, simple, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+
+AC_DEFUN([EVAS_CHECK_ENGINE_DEP_SOFTWARE_8_X11],
+[
+
+have_dep="no"
+evas_engine_[]$1[]_cflags=""
+evas_engine_[]$1[]_libs=""
+
+PKG_CHECK_MODULES([XCB],
+   [xcb xcb-shm xcb-image >= 0.2.1 pixman-1],
+   [
+    have_dep="yes"
+    requirement="xcb xcb-shm xcb-image pixman-1"
+    evas_engine_[]$1[]_cflags="${XCB_CFLAGS}"
+    evas_engine_[]$1[]_libs="${XCB_LIBS}"
+   ],[
+    have_dep="no"
+   ]
+)
+
+AC_SUBST([evas_engine_$1_cflags])
+AC_SUBST([evas_engine_$1_libs])
+
+if test "x$3" = "xstatic" ; then
+   requirement_evas="${requirement} ${requirement_evas}"
+fi
+
+if test "x${have_dep}" = "xyes" ; then
+  m4_default([$4], [:])
+else
+  m4_default([$5], [:])
+fi
+
+])
+
 dnl use: EVAS_CHECK_ENGINE_DEP_SOFTWARE_16_X11(engine, simple, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
 AC_DEFUN([EVAS_CHECK_ENGINE_DEP_SOFTWARE_16_X11],
 [
index cd64c9d..d13688c 100644 (file)
@@ -37,7 +37,7 @@ have_dep="no"
 evas_image_loader_[]$1[]_cflags=""
 evas_image_loader_[]$1[]_libs=""
 
-PKG_CHECK_MODULES([EET], [eet >= 1.0.1], [have_dep="yes" requirement="eet"], [have_dep="no"])
+PKG_CHECK_MODULES([EET], [eet >= 1.4.0], [have_dep="yes" requirement="eet >= 1.4.0"], [have_dep="no"])
 evas_image_loader_[]$1[]_cflags="${EET_CFLAGS}"
 evas_image_loader_[]$1[]_libs="${EET_LIBS}"
 
@@ -439,7 +439,7 @@ AC_MSG_CHECKING([whether to enable Eet font loader])
 AC_MSG_RESULT([${want_loader}])
 
 if test "x$want_loader" = "xyes" -o "x$want_loader" = "xauto"; then
-    PKG_CHECK_MODULES([EET], [eet >= 1.0.1], [have_evas_font_loader_eet="yes"], [have_evas_font_loader_eet="no"])
+    PKG_CHECK_MODULES([EET], [eet >= 1.4.0], [have_evas_font_loader_eet="yes"], [have_evas_font_loader_eet="no"])
 fi
 
 if test "x${have_evas_font_loader_eet}" = "xno" -a "x$want_loader" = "xyes" -a "x$use_strict" = "xyes" ; then
@@ -448,7 +448,7 @@ fi
 
 if test "x$have_evas_font_loader_eet" = "xyes" ; then
    AC_DEFINE([BUILD_FONT_LOADER_EET], [1], [EET Font Loader Support])
-   requirement_evas="eet ${requirement_evas}"
+   requirement_evas="eet >= 1.4.0 ${requirement_evas}"
 fi
 
 popdef([UP])
index 7325c14..b8ad015 100644 (file)
@@ -25,7 +25,9 @@ evas_cserve_SOURCES = \
 evas_cserve_main.c
 
 evas_cserve_LDADD = \
-$(top_builddir)/src/lib/libevas.la
+$(top_builddir)/src/lib/libevas.la \
+@pthread_libs@ \
+@EINA_LIBS@
 
 evas_cserve_tool_LDFLAGS =
 
@@ -33,6 +35,8 @@ evas_cserve_tool_SOURCES = \
 evas_cserve_tool.c
 
 evas_cserve_tool_LDADD = \
-$(top_builddir)/src/lib/libevas.la
+$(top_builddir)/src/lib/libevas.la \
+@pthread_libs@ \
+@EINA_LIBS@
 
 endif
index 4a6745f..1f30a95 100644 (file)
@@ -1309,13 +1309,12 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
                   len++;
                }
              DBG("... malloc msg");
-             msg = malloc(len);
+             msg = calloc(1, len);
              if (msg)
                {
                   unsigned char *p;
                   
                   DBG("...   init msg");
-                  memset(msg, 0, len);
                   p = (unsigned char *)msg;
                   msg->active.mem_total = 0;
                   msg->active.count = 0;
index 88acd82..b358541 100644 (file)
@@ -35,8 +35,8 @@
 extern "C" {
 #endif
 
-#define EVAS_VERSION_MAJOR 0
-#define EVAS_VERSION_MINOR 9
+#define EVAS_VERSION_MAJOR 1
+#define EVAS_VERSION_MINOR 0
 
    typedef struct _Evas_Version
      {
@@ -151,7 +151,8 @@ typedef enum _Evas_Colorspace
      /* these are not currently supported - but planned for the future */
    EVAS_COLORSPACE_YCBCR422P601_PL, /**< YCbCr 4:2:2 Planar, ITU.BT-601 specifications. The data poitned to is just an array of row pointer, pointing to the Y rows, then the Cb, then Cr rows */
    EVAS_COLORSPACE_YCBCR422P709_PL,/**< YCbCr 4:2:2 Planar, ITU.BT-709 specifications. The data poitned to is just an array of row pointer, pointing to the Y rows, then the Cb, then Cr rows */
-   EVAS_COLORSPACE_RGB565_A5P /**< 16bit rgb565 + Alpha plane at end - 5 bits of the 8 being used per alpha byte */
+   EVAS_COLORSPACE_RGB565_A5P, /**< 16bit rgb565 + Alpha plane at end - 5 bits of the 8 being used per alpha byte */
+   EVAS_COLORSPACE_GRY8 /**< 8bit grayscale */
 } Evas_Colorspace; /**< Colorspaces for pixel data supported by Evas */
 
 /**
@@ -165,7 +166,6 @@ typedef enum _Evas_Object_Table_Homogeneous_Mode
   EVAS_OBJECT_TABLE_HOMOGENEOUS_ITEM = 2
 } Evas_Object_Table_Homogeneous_Mode; /**< Table cell pack mode. */
 
-typedef struct _Evas_Transform Evas_Transform; /**< An Evas projective or affine transform */
 typedef struct _Evas_Coord_Rectangle  Evas_Coord_Rectangle; /**< A generic rectangle handle */
 typedef struct _Evas_Point                   Evas_Point; /**< integer point */
 
@@ -226,13 +226,6 @@ typedef int           Evas_Coord;
 typedef int           Evas_Font_Size;
 typedef int           Evas_Angle;
 
-struct _Evas_Transform /** An affine or projective coordinate transformation matrix */
-{
-   float mxx, mxy, mxz;
-   float myx, myy, myz;
-   float mzx, mzy, mzz;
-};
-
 struct _Evas_Coord_Rectangle /**< A rectangle in Evas_Coord */
 {
    Evas_Coord x; /**< top-left x co-ordinate of rectangle */
@@ -341,7 +334,7 @@ struct _Evas_Native_Surface
 #define EVAS_COLOR_SPACE_ARGB                      0 /**< ARGB color space */
 #define EVAS_COLOR_SPACE_AHSV                      1 /**< AHSV color space */
 
-#define EVAS_TEXTURE_REFLECT            0 /**< Gradient and image fill tiling mode - tiling reflects */
+#define EVAS_TEXTURE_REFLECT            0 /**< image fill tiling mode - tiling reflects */
 #define EVAS_TEXTURE_REPEAT             1 /**< tiling repeats */
 #define EVAS_TEXTURE_RESTRICT           2 /**< tiling clamps - range offset ignored */
 #define EVAS_TEXTURE_RESTRICT_REFLECT   3 /**< tiling clamps and any range offset reflects */
@@ -1207,8 +1200,6 @@ typedef void      (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj
    EAPI void              evas_object_image_fill_get        (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) EINA_ARG_NONNULL(1);
    EAPI void              evas_object_image_fill_spread_set   (Evas_Object *obj, int tile_mode) EINA_ARG_NONNULL(1);
    EAPI int               evas_object_image_fill_spread_get   (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI void              evas_object_image_fill_transform_set (Evas_Object *obj, Evas_Transform *t) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_image_fill_transform_get (const Evas_Object *obj, Evas_Transform *t) EINA_ARG_NONNULL(1, 2);
    EAPI void              evas_object_image_size_set        (Evas_Object *obj, int w, int h) EINA_ARG_NONNULL(1);
    EAPI void              evas_object_image_size_get        (const Evas_Object *obj, int *w, int *h) EINA_ARG_NONNULL(1);
    EAPI int               evas_object_image_stride_get      (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
@@ -1312,9 +1303,14 @@ typedef void      (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj
  *
  * @ingroup Evas_Object_Specific
  */
-   typedef struct _Evas_Textblock_Style     Evas_Textblock_Style;
-   typedef struct _Evas_Textblock_Cursor    Evas_Textblock_Cursor;
-   typedef struct _Evas_Textblock_Rectangle Evas_Textblock_Rectangle;
+   typedef struct _Evas_Textblock_Style                 Evas_Textblock_Style;
+   typedef struct _Evas_Textblock_Cursor                Evas_Textblock_Cursor;
+   /**
+    * @typedef Evas_Object_Textblock_Node_Format
+    * A format node.
+    */
+   typedef struct _Evas_Object_Textblock_Node_Format    Evas_Object_Textblock_Node_Format;
+   typedef struct _Evas_Textblock_Rectangle             Evas_Textblock_Rectangle;
 
    struct _Evas_Textblock_Rectangle
      {
@@ -1346,42 +1342,52 @@ typedef void      (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj
 
    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);
-   EAPI const char                  *evas_object_textblock_text_markup_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
+   EAPI const char                  *evas_object_textblock_text_markup_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
 
    EAPI const Evas_Textblock_Cursor *evas_object_textblock_cursor_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
    EAPI Evas_Textblock_Cursor       *evas_object_textblock_cursor_new(Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
 
    EAPI void                         evas_textblock_cursor_free(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
 
-   EAPI void                         evas_textblock_cursor_node_first(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
-   EAPI void                         evas_textblock_cursor_node_last(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
-   EAPI Eina_Bool                    evas_textblock_cursor_node_next(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
-   EAPI Eina_Bool                    evas_textblock_cursor_node_prev(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI void                         evas_textblock_cursor_paragraph_first(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI void                         evas_textblock_cursor_paragraph_last(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool                    evas_textblock_cursor_paragraph_next(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool                    evas_textblock_cursor_paragraph_prev(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI const Evas_Object_Textblock_Node_Format *evas_textblock_node_format_first_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Evas_Object_Textblock_Node_Format *evas_textblock_node_format_last_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI const Evas_Object_Textblock_Node_Format *evas_textblock_node_format_next_get(const Evas_Object_Textblock_Node_Format *n) EINA_ARG_NONNULL(1);
+   EAPI const Evas_Object_Textblock_Node_Format *evas_textblock_node_format_prev_get(const Evas_Object_Textblock_Node_Format *n) EINA_ARG_NONNULL(1);
+   EAPI void                         evas_textblock_cursor_set_at_format(Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Format *n) EINA_ARG_NONNULL(1, 2);
+   EAPI const Evas_Object_Textblock_Node_Format *evas_textblock_cursor_format_get(const Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI const char                  *evas_textblock_node_format_text_get(const Evas_Object_Textblock_Node_Format *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
+   EAPI void                         evas_textblock_cursor_at_format_set(Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Format *fmt) EINA_ARG_NONNULL(1, 2);
+   EAPI Eina_Bool                    evas_textblock_cursor_format_is_visible_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
+   EAPI Eina_Bool                    evas_textblock_cursor_format_next(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool                    evas_textblock_cursor_format_prev(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI Eina_Bool                    evas_textblock_cursor_is_format(const Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
    EAPI Eina_Bool                    evas_textblock_cursor_char_next(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
    EAPI Eina_Bool                    evas_textblock_cursor_char_prev(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
-   EAPI void                         evas_textblock_cursor_char_first(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
-   EAPI void                         evas_textblock_cursor_char_last(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
-   EAPI void                         evas_textblock_cursor_line_first(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
-   EAPI void                         evas_textblock_cursor_line_last(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI void                         evas_textblock_cursor_paragraph_char_first(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI void                         evas_textblock_cursor_paragraph_char_last(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI void                         evas_textblock_cursor_line_char_first(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
+   EAPI void                         evas_textblock_cursor_line_char_last(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
    EAPI int                          evas_textblock_cursor_pos_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
    EAPI void                         evas_textblock_cursor_pos_set(Evas_Textblock_Cursor *cur, int pos) EINA_ARG_NONNULL(1);
    EAPI Eina_Bool                    evas_textblock_cursor_line_set(Evas_Textblock_Cursor *cur, int line) EINA_ARG_NONNULL(1);
    EAPI int                          evas_textblock_cursor_compare(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2) EINA_PURE;
    EAPI void                         evas_textblock_cursor_copy(const Evas_Textblock_Cursor *cur, Evas_Textblock_Cursor *cur_dest) EINA_ARG_NONNULL(1, 2);
 
-   EAPI void                         evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) EINA_ARG_NONNULL(1, 2);
-   EAPI void                         evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text) EINA_ARG_NONNULL(1, 2);
+   EAPI size_t                       evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) EINA_ARG_NONNULL(1, 2);
+   EAPI size_t                       evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text) EINA_ARG_NONNULL(1, 2);
 
-   EAPI void                         evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *format) EINA_ARG_NONNULL(1, 2);
-   EAPI void                         evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *format) EINA_ARG_NONNULL(1, 2);
+   EAPI Eina_Bool                    evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *format) EINA_ARG_NONNULL(1, 2);
+   EAPI Eina_Bool                    evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *format) EINA_ARG_NONNULL(1, 2);
    EAPI void                         evas_textblock_cursor_node_delete(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
    EAPI void                         evas_textblock_cursor_char_delete(Evas_Textblock_Cursor *cur) EINA_ARG_NONNULL(1);
    EAPI void                         evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_Cursor *cur2) EINA_ARG_NONNULL(1, 2);
 
-   EAPI const char                  *evas_textblock_cursor_node_text_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI int                          evas_textblock_cursor_node_text_length_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI const char                  *evas_textblock_cursor_node_format_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI Eina_Bool                    evas_textblock_cursor_node_format_is_visible_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
+   EAPI const char                  *evas_textblock_cursor_paragraph_text_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
+   EAPI int                          evas_textblock_cursor_paragraph_text_length_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
    EAPI char                        *evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2, Evas_Textblock_Text_Type format) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2) EINA_PURE;
 
    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);
@@ -1392,7 +1398,6 @@ typedef void      (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj
    EAPI Eina_Bool                    evas_textblock_cursor_format_item_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_eol_get(const Evas_Textblock_Cursor *cur) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI void                         evas_textblock_cursor_eol_set(Evas_Textblock_Cursor *cur, Eina_Bool eol) EINA_ARG_NONNULL(1);
 
    EAPI Eina_Bool                    evas_object_textblock_line_number_geometry_get(const Evas_Object *obj, int line, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) EINA_ARG_NONNULL(1);
    EAPI void                         evas_object_textblock_clear(Evas_Object *obj) EINA_ARG_NONNULL(1);
@@ -1426,58 +1431,6 @@ typedef void      (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj
    EAPI void              evas_object_polygon_points_clear  (Evas_Object *obj) EINA_ARG_NONNULL(1);
 
 /**
- * @defgroup Evas_Object_Gradient_Group Gradient Object Functions
- *
- * Functions that work on evas gradient objects.
- *
- * @ingroup Evas_Object_Specific
- */
-   EAPI Evas_Object      *evas_object_gradient_add            (Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
-   EAPI void              evas_object_gradient_color_stop_add (Evas_Object *obj, int r, int g, int b, int a, int delta) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_gradient_alpha_stop_add (Evas_Object *obj, int a, int delta) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_gradient_color_data_set (Evas_Object *obj, void *color_data, int len, Eina_Bool has_alpha) EINA_ARG_NONNULL(1, 2);
-   EAPI void              evas_object_gradient_alpha_data_set (Evas_Object *obj, void *alpha_data, int len) EINA_ARG_NONNULL(1, 2);
-   EAPI void              evas_object_gradient_clear          (Evas_Object *obj) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_gradient_type_set       (Evas_Object *obj, const char *type, const char *instance_params) EINA_ARG_NONNULL(1, 2);
-   EAPI void              evas_object_gradient_type_get       (const Evas_Object *obj, char **type, char **instance_params) EINA_ARG_NONNULL(1, 2);
-   EAPI void              evas_object_gradient_fill_set       (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_gradient_fill_get       (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_gradient_fill_angle_set (Evas_Object *obj, Evas_Angle angle) EINA_ARG_NONNULL(1);
-   EAPI Evas_Angle        evas_object_gradient_fill_angle_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI void              evas_object_gradient_fill_spread_set(Evas_Object *obj, int tile_mode) EINA_ARG_NONNULL(1);
-   EAPI int               evas_object_gradient_fill_spread_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI void              evas_object_gradient_angle_set      (Evas_Object *obj, Evas_Angle angle) EINA_ARG_NONNULL(1);
-   EAPI Evas_Angle        evas_object_gradient_angle_get      (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI void              evas_object_gradient_direction_set  (Evas_Object *obj, int direction) EINA_ARG_NONNULL(1);
-   EAPI int               evas_object_gradient_direction_get  (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI void              evas_object_gradient_offset_set     (Evas_Object *obj, float offset) EINA_ARG_NONNULL(1);
-   EAPI float             evas_object_gradient_offset_get     (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-
-/**
- * @defgroup Evas_Object_Gradient2_Group Gradient2 Object Functions
- *
- * Functions that work on evas gradient2 objects.
- *
- * @ingroup Evas_Object_Specific
- */
-   EAPI void              evas_object_gradient2_color_np_stop_insert (Evas_Object *obj, int r, int g, int b, int a, float pos) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_gradient2_fill_spread_set      (Evas_Object *obj, int tile_mode) EINA_ARG_NONNULL(1);
-   EAPI int               evas_object_gradient2_fill_spread_get      (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-   EAPI void              evas_object_gradient2_fill_transform_set   (Evas_Object *obj, Evas_Transform *t) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_gradient2_fill_transform_get   (const Evas_Object *obj, Evas_Transform *t) EINA_ARG_NONNULL(1);
-
-/* linear gradient2 objects */
-   EAPI Evas_Object      *evas_object_gradient2_linear_add      (Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
-   EAPI void              evas_object_gradient2_linear_fill_set (Evas_Object *obj, float x0, float y0, float x1, float y1) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_gradient2_linear_fill_get (const Evas_Object *obj, float *x0, float *y0, float *x1, float *y1) EINA_ARG_NONNULL(1);
-
-/* radial gradient2 objects */
-   EAPI Evas_Object      *evas_object_gradient2_radial_add      (Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
-   EAPI void              evas_object_gradient2_radial_fill_set (Evas_Object *obj, float cx, float cy, float rx, float ry) EINA_ARG_NONNULL(1);
-   EAPI void              evas_object_gradient2_radial_fill_get (const Evas_Object *obj, float *cx, float *cy, float *rx, float *ry) EINA_ARG_NONNULL(1);
-
-
-/**
  * @defgroup Evas_Smart_Group Smart Functions
  *
  * Functions that deal with Evas_Smart's, creating definition
@@ -2005,6 +1958,9 @@ struct _Evas_Smart_Cb_Description
    struct _Evas_Object_Box_Option
    {
       Evas_Object *obj;
+      Eina_Bool max_reached:1;
+      Eina_Bool min_reached:1;
+      Evas_Coord alloc_size;
    };
 
    EAPI void evas_object_box_smart_set(Evas_Object_Box_Api *api) EINA_ARG_NONNULL(1);
@@ -2182,20 +2138,6 @@ struct _Evas_Smart_Cb_Description
    EAPI void              evas_data_argb_premul             (unsigned int *data, unsigned int len);
    EAPI void              evas_data_argb_unpremul           (unsigned int *data, unsigned int len);
 
-/* Evas utility routines for working with transforms */
-   /* Set t to the identity */
-   EAPI void              evas_transform_identity_set       (Evas_Transform *t);
-   /* Left-multiply t by an xy rotation defined by the given angle (in degrees) */
-   EAPI void              evas_transform_rotate             (double angle, Evas_Transform *t);
-   /* Left-multiply t by an xy translation defined by the given dx, dy values */
-   EAPI void              evas_transform_translate          (float dx, float dy, Evas_Transform *t);
-   /* Left-multiply t by an xy scaling defined by the given sx, sy factors */
-   EAPI void              evas_transform_scale              (float sx, float sy, Evas_Transform *t);
-   /* Left-multiply t by an xy shearing defined by the given sh, sv values */
-   EAPI void              evas_transform_shear              (float sh, float sv, Evas_Transform *t);
-   /* Left-multiply t by the given transform l */
-   EAPI void              evas_transform_compose            (Evas_Transform *l, Evas_Transform *t);
-
 /* string and font handling */
    EAPI int               evas_string_char_next_get         (const char *str, int pos, int *decoded) EINA_ARG_NONNULL(1);
    EAPI int               evas_string_char_prev_get         (const char *str, int pos, int *decoded) EINA_ARG_NONNULL(1);
index d357f4e..94b0812 100644 (file)
@@ -67,6 +67,15 @@ SUBDIRS += ../modules/engines/software_16_x11/
 EVAS_STATIC_MODULE += ../modules/engines/software_16_x11/libevas_engine_software_16_x11.la
 EVAS_STATIC_LIBADD += @evas_engine_software_16_x11_libs@
 endif
+if EVAS_STATIC_BUILD_SOFTWARE_8
+SUBDIRS += ../modules/engines/software_8/
+EVAS_STATIC_MODULE += ../modules/engines/software_8/libevas_engine_software_8.la
+endif
+if EVAS_STATIC_BUILD_SOFTWARE_8_X11
+SUBDIRS += ../modules/engines/software_8_x11/
+EVAS_STATIC_MODULE += ../modules/engines/software_8_x11/libevas_engine_software_8_x11.la
+EVAS_STATIC_LIBADD += @evas_engine_software_8_x11_libs@
+endif
 if EVAS_STATIC_BUILD_SOFTWARE_SDL
 SUBDIRS += \
        ../modules/engines/software_16_sdl/ \
@@ -176,7 +185,8 @@ AM_CFLAGS = @WIN32_CFLAGS@
 
 lib_LTLIBRARIES = libevas.la
 
-include_HEADERS = Evas.h
+includes_HEADERS = Evas.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 libevas_la_SOURCES = main.c
 
@@ -219,6 +229,13 @@ libevas_la_DEPENDENCIES += engines/common_16/libevas_engine_common_16.la
 
 endif
 
+if BUILD_ENGINE_SOFTWARE_8
+
+libevas_la_LIBADD += engines/common_8/libevas_engine_common_8.la
+libevas_la_DEPENDENCIES += engines/common_8/libevas_engine_common_8.la
+
+endif
+
 libevas_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@
 
 DIST_SUBDIRS = canvas cache cserve file engines imaging include
index ca9f9aa..829380d 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include <assert.h>
 
 #include "evas_common.h"
@@ -671,14 +667,10 @@ evas_cache_engine_image_engine(Evas_Cache_Engine_Image *cache, void *engine_data
 
   on_error:
    if (!eim)
-     {
-        if (ie)
-          evas_cache_image_drop(ie);
-     }
+     evas_cache_image_drop(ie);
    else
-     {
-        evas_cache_engine_image_drop(eim);
-     }
+     evas_cache_engine_image_drop(eim);
+
    return NULL;
 }
 
index 3d3bd12..a7d7579 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
@@ -51,8 +47,7 @@ static void _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *
 static void _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie);
 
 static void
-_evas_cache_image_make_dirty(Evas_Cache_Image *cache,
-                             Image_Entry *im)
+_evas_cache_image_make_dirty(Evas_Cache_Image *cache, Image_Entry *im)
 {
    im->flags.cached = 1;
    im->flags.dirty = 1;
@@ -75,8 +70,7 @@ _evas_cache_image_make_dirty(Evas_Cache_Image *cache,
 
 static void
 _evas_cache_image_make_activ(Evas_Cache_Image *cache,
-                             Image_Entry *im,
-                             const char *key)
+                             Image_Entry *im, const char *key)
 {
    /* FIXME: Handle case when image is being processed anyway and don't do a double decode. */
    im->cache_key = key;
@@ -102,8 +96,7 @@ _evas_cache_image_make_activ(Evas_Cache_Image *cache,
 
 static void
 _evas_cache_image_make_inactiv(Evas_Cache_Image *cache,
-                               Image_Entry *im,
-                               const char *key)
+                               Image_Entry *im, const char *key)
 {
    if (im->cache_key)
      {
@@ -127,8 +120,7 @@ _evas_cache_image_make_inactiv(Evas_Cache_Image *cache,
  }
 
 static void
-_evas_cache_image_remove_lru_nodata(Evas_Cache_Image *cache,
-                                    Image_Entry *im)
+_evas_cache_image_remove_lru_nodata(Evas_Cache_Image *cache, Image_Entry *im)
 {
    if (im->flags.lru_nodata)
      {
@@ -145,8 +137,7 @@ _evas_cache_image_remove_lru_nodata(Evas_Cache_Image *cache,
 }
 
 static void
-_evas_cache_image_activ_lru_nodata(Evas_Cache_Image *cache,
-                                   Image_Entry *im)
+_evas_cache_image_activ_lru_nodata(Evas_Cache_Image *cache, Image_Entry *im)
 {
    im->flags.need_data = 0;
    im->flags.lru_nodata = 1;
@@ -161,8 +152,7 @@ _evas_cache_image_activ_lru_nodata(Evas_Cache_Image *cache,
 }
 
 static void
-_evas_cache_image_remove_activ(Evas_Cache_Image *cache,
-                               Image_Entry *ie)
+_evas_cache_image_remove_activ(Evas_Cache_Image *cache, Image_Entry *ie)
 {
    if (ie->flags.cached)
      {
@@ -205,8 +195,7 @@ _evas_cache_image_remove_activ(Evas_Cache_Image *cache,
 static void
 _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie)
 {
-   if (!ie)
-       return ;
+   if (!ie) return;
 
    if (cache->func.debug)
      cache->func.debug("deleting", ie);
@@ -333,8 +322,7 @@ _evas_cache_image_entry_new(Evas_Cache_Image *cache,
 static void
 _evas_cache_image_entry_surface_alloc__locked(Evas_Cache_Image *cache,
                                              Image_Entry *ie,
-                                             int wmin,
-                                             int hmin)
+                                             int wmin, int hmin)
 {
    if (ie->allocated.w == wmin && ie->allocated.h == hmin)
      return ;
@@ -353,9 +341,7 @@ _evas_cache_image_entry_surface_alloc__locked(Evas_Cache_Image *cache,
 
 static void
 _evas_cache_image_entry_surface_alloc(Evas_Cache_Image *cache,
-                                      Image_Entry *ie,
-                                      int w,
-                                      int h)
+                                      Image_Entry *ie, int w, int h)
 {
    int  wmin;
    int  hmin;
@@ -466,8 +452,7 @@ _evas_cache_image_async_cancel(void *data)
 }
 
 static int
-_evas_cache_image_entry_preload_add(Image_Entry *ie,
-                                   const void *target)
+_evas_cache_image_entry_preload_add(Image_Entry *ie, const void *target)
 {
    Evas_Cache_Target *tg;
 
@@ -577,11 +562,10 @@ evas_cache_image_set(Evas_Cache_Image *cache, int limit)
 EAPI Evas_Cache_Image *
 evas_cache_image_init(const Evas_Cache_Image_Func *cb)
 {
-   Evas_Cache_Image    *new;
+   Evas_Cache_Image *new;
 
    new = malloc(sizeof (Evas_Cache_Image));
-   if (!new)
-     return NULL;
+   if (!new) return NULL;
 
    new->func = *cb;
 
@@ -806,8 +790,8 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
 #endif
    if (im)
      {
-        time_t  t;
-        int     ok;
+        time_t t;
+        int ok;
 
         ok = 1;
         t = time(NULL);
@@ -915,8 +899,8 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
 EAPI void
 evas_cache_image_drop(Image_Entry *im)
 {
-   Evas_Cache_Image    *cache;
-   int                              references;
+   Evas_Cache_Image *cache;
+   int references;
 
    assert(im);
    assert(im->cache);
@@ -935,16 +919,16 @@ evas_cache_image_drop(Image_Entry *im)
    if (references == 0)
      {
 #ifdef EVAS_FRAME_QUEUING
-        LKL(((RGBA_Image *)im)->ref_fq_add);
-        LKL(((RGBA_Image *)im)->ref_fq_del);
-        if (((RGBA_Image *)im)->ref_fq[0] != ((RGBA_Image *)im)->ref_fq[1])
+        LKL(im->ref_fq_add);
+        LKL(im->ref_fq_del);
+        if (im->ref_fq[0] != im->ref_fq[1])
           {
-             LKU(((RGBA_Image *)im)->ref_fq_add);
-             LKU(((RGBA_Image *)im)->ref_fq_del);
+             LKU(im->ref_fq_add);
+             LKU(im->ref_fq_del);
              return;
           }
-       LKU(((RGBA_Image *)im)->ref_fq_add);
-       LKU(((RGBA_Image *)im)->ref_fq_del);
+       LKU(im->ref_fq_add);
+       LKU(im->ref_fq_del);
 #endif
 
 #ifdef BUILD_ASYNC_PRELOAD
@@ -970,9 +954,9 @@ evas_cache_image_drop(Image_Entry *im)
 EAPI void
 evas_cache_image_data_not_needed(Image_Entry *im)
 {
-   Evas_Cache_Image    *cache;
-   int   references;
-   
+   Evas_Cache_Image *cache;
+   int references;
+
    assert(im);
    assert(im->cache);
 
@@ -995,9 +979,9 @@ evas_cache_image_data_not_needed(Image_Entry *im)
 EAPI Image_Entry *
 evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h)
 {
-   Image_Entry          *im_dirty = im;
-   Evas_Cache_Image     *cache;
-   int                           references;
+   Image_Entry *im_dirty = im;
+   Evas_Cache_Image *cache;
+   int references;
 
    assert(im);
    assert(im->cache);
@@ -1019,13 +1003,12 @@ evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h)
         else
 #endif
           {
-             int        error;
+             int error;
 
-             im_dirty = evas_cache_image_copied_data
-               (cache, im->w, im->h, 
-                evas_cache_image_pixels(im), 
-                im->flags.alpha, 
-                im->space);
+             im_dirty = 
+               evas_cache_image_copied_data(cache, im->w, im->h, 
+                                            evas_cache_image_pixels(im), 
+                                            im->flags.alpha, im->space);
              if (!im_dirty) goto on_error;
              if (cache->func.debug)
                cache->func.debug("dirty-src", im);
@@ -1075,9 +1058,9 @@ evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h)
 EAPI Image_Entry *
 evas_cache_image_alone(Image_Entry *im)
 {
-   Evas_Cache_Image     *cache;
-   Image_Entry          *im_dirty = im;
-   int                           references;
+   Evas_Cache_Image *cache;
+   Image_Entry *im_dirty = im;
+   int references;
 
    assert(im);
    assert(im->cache);
@@ -1101,7 +1084,7 @@ evas_cache_image_alone(Image_Entry *im)
      }
    else
      {
-        int     error;
+        int error;
 
         im_dirty = evas_cache_image_copied_data
           (cache, im->w, im->h, 
@@ -1148,7 +1131,7 @@ evas_cache_image_alone(Image_Entry *im)
 EAPI Image_Entry *
 evas_cache_image_copied_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace)
 {
-   Image_Entry  *im;
+   Image_Entry *im;
 
    assert(cache);
 
@@ -1185,7 +1168,7 @@ evas_cache_image_copied_data(Evas_Cache_Image *cache, int w, int h, DATA32 *imag
 EAPI Image_Entry *
 evas_cache_image_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace)
 {
-   Image_Entry  *im;
+   Image_Entry *im;
 
    assert(cache);
 
@@ -1219,7 +1202,7 @@ evas_cache_image_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data,
 EAPI void
 evas_cache_image_surface_alloc(Image_Entry *im, int w, int h)
 {
-   Evas_Cache_Image     *cache;
+   Evas_Cache_Image *cache;
 
    assert(im);
    assert(im->cache);
@@ -1239,9 +1222,9 @@ evas_cache_image_surface_alloc(Image_Entry *im, int w, int h)
 EAPI Image_Entry *
 evas_cache_image_size_set(Image_Entry *im, int w, int h)
 {
-   Evas_Cache_Image    *cache;
-   Image_Entry         *new;
-   int                  error;
+   Evas_Cache_Image *cache;
+   Image_Entry *new;
+   int error;
 
    assert(im);
    assert(im->cache);
@@ -1308,10 +1291,7 @@ evas_cache_image_load_data(Image_Entry *im)
    assert(im->cache);
    cache = im->cache;
 
-   if (im->flags.loaded)
-     {
-       return;
-     }
+   if (im->flags.loaded) return;
 
 #ifdef BUILD_ASYNC_PRELOAD
    if (im->preload)
@@ -1380,7 +1360,7 @@ evas_cache_image_unload_data(Image_Entry *im)
    assert(im->cache);
    cache = im->cache;
 
-   if (im->flags.in_progress) return ;
+   if (im->flags.in_progress) return;
 
    evas_cache_image_preload_cancel(im, NULL);
 
@@ -1395,7 +1375,6 @@ evas_cache_image_unload_data(Image_Entry *im)
 #endif
        return;
      }
-   evas_common_rgba_image_scalecache_dirty(im);
    cache->func.destructor(im);
 
 #ifdef BUILD_ASYNC_PRELOAD
@@ -1433,8 +1412,6 @@ EAPI void
 evas_cache_image_preload_data(Image_Entry *im, const void *target)
 {
 #ifdef BUILD_ASYNC_PRELOAD
-   Evas_Cache_Image    *cache;
-
    assert(im);
    assert(im->cache);
 
@@ -1444,8 +1421,6 @@ evas_cache_image_preload_data(Image_Entry *im, const void *target)
        return;
      }
 
-   cache = im->cache;
-
    if (!_evas_cache_image_entry_preload_add(im, target))
      evas_object_inform_call_image_preloaded((Evas_Object *)target);
 #else
@@ -1458,14 +1433,10 @@ EAPI void
 evas_cache_image_preload_cancel(Image_Entry *im, const void *target)
 {
 #ifdef BUILD_ASYNC_PRELOAD
-   Evas_Cache_Image *cache;
-
    assert(im);
    assert(im->cache);
-   cache = im->cache;
-
-   if (target == NULL) return ;
 
+   if (target == NULL) return;
    _evas_cache_image_entry_preload_remove(im, target);
 #else
    (void)im;
@@ -1523,7 +1494,7 @@ evas_cache_image_empty(Evas_Cache_Image *cache)
 EAPI void
 evas_cache_image_colorspace(Image_Entry *im, int cspace)
 {
-   Evas_Cache_Image    *cache;
+   Evas_Cache_Image *cache;
 
    assert(im);
    assert(im->cache);
@@ -1539,7 +1510,7 @@ evas_cache_image_colorspace(Image_Entry *im, int cspace)
 EAPI void *
 evas_cache_private_from_image_entry_get(Image_Entry *im)
 {
-   Evas_Cache_Image    *cache;
+   Evas_Cache_Image *cache;
 
    assert(im);
    assert(im->cache);
@@ -1568,7 +1539,7 @@ evas_cache_private_set(Evas_Cache_Image *cache, const void *data)
 EAPI DATA32 *
 evas_cache_image_pixels(Image_Entry *im)
 {
-   Evas_Cache_Image    *cache;
+   Evas_Cache_Image *cache;
 
    assert(im);
    assert(im->cache);
index acab76f..91f982a 100644 (file)
 typedef struct _Evas_Preload_Pthread_Worker Evas_Preload_Pthread_Worker;
 typedef struct _Evas_Preload_Pthread_Data Evas_Preload_Pthread_Data;
 
+typedef void (*_evas_preload_pthread_func)(void *data);
+
 struct _Evas_Preload_Pthread_Worker
 {
-   void (*func_heavy)(void *data);
-   void (*func_end)(void *data);
-   void (*func_cancel)(void *data);
+   _evas_preload_pthread_func func_heavy;
+   _evas_preload_pthread_func func_end;
+   _evas_preload_pthread_func func_cancel;
 
    const void *data;
 
@@ -56,7 +58,7 @@ _evas_preload_thread_end(Evas_Preload_Pthread_Data *pth)
 }
 
 static void
-_evas_preload_thread_done(void *target, Evas_Callback_Type type, void *event_info)
+_evas_preload_thread_done(void *target __UNUSED__, Evas_Callback_Type type __UNUSED__, void *event_info)
 {
    Evas_Preload_Pthread_Worker *work;
 
@@ -120,7 +122,7 @@ _evas_preload_thread_worker(Evas_Preload_Pthread_Data *pth)
 
    work->data = pth;
    work->func_heavy = NULL;
-   work->func_end = (void *) _evas_preload_thread_end;
+   work->func_end = (_evas_preload_pthread_func) _evas_preload_thread_end;
    work->func_cancel = NULL;
    work->cancel = EINA_FALSE;
 
@@ -171,9 +173,9 @@ _evas_preload_thread_shutdown(void)
 }
 
 Evas_Preload_Pthread *
-evas_preload_thread_run(void (*func_heavy)(void *data),
-                       void (*func_end)(void *data),
-                       void (*func_cancel)(void *data),
+evas_preload_thread_run(void (*func_heavy) (void *data),
+                       void (*func_end) (void *data),
+                       void (*func_cancel) (void *data),
                        const void *data)
 {
 #ifdef BUILD_ASYNC_PRELOAD
index 1bb051d..d5959fa 100644 (file)
@@ -27,8 +27,6 @@ evas_key_grab.c \
 evas_layer.c \
 evas_main.c \
 evas_name.c \
-evas_object_gradient.c \
-evas_object_gradient2.c \
 evas_object_image.c \
 evas_object_main.c \
 evas_object_inform.c \
@@ -54,6 +52,3 @@ evas_map.c
 
 libevas_canvas_la_LIBADD = @EVIL_LIBS@
 
-EXTRA_DIST = \
-evas_object_gradient2_linear.c \
-evas_object_gradient2_radial.c
index 565440d..c4aabfa 100644 (file)
@@ -17,7 +17,7 @@ _evas_post_event_callback_call(Evas *e)
      {
         if ((!skip) && (!e->delete_me) && (!pc->delete_me))
           {
-             if (!pc->func(pc->data, e)) skip = 1;
+             if (!pc->func((void*)pc->data, e)) skip = 1;
           }
         free(pc);
      }
index 5c7e606..86c55a4 100644 (file)
@@ -155,15 +155,20 @@ evas_new(void)
    e->hinting = EVAS_FONT_HINTING_BYTECODE;
    e->name_hash = eina_hash_string_superfast_new(NULL);
 
-   eina_array_step_set(&e->delete_objects, 256);
-   eina_array_step_set(&e->active_objects, 256);
-   eina_array_step_set(&e->restack_objects, 256);
-   eina_array_step_set(&e->render_objects, 256);
-   eina_array_step_set(&e->pending_objects, 256);
-   eina_array_step_set(&e->obscuring_objects, 256);
-   eina_array_step_set(&e->temporary_objects, 256);
-   eina_array_step_set(&e->calculate_objects, 256);
-   eina_array_step_set(&e->clip_changes, 256);
+#define EVAS_ARRAY_SET(E, Array)               \
+   eina_array_step_set(&E->Array, sizeof (E->Array), 256);
+
+   EVAS_ARRAY_SET(e, delete_objects);
+   EVAS_ARRAY_SET(e, active_objects);
+   EVAS_ARRAY_SET(e, restack_objects);
+   EVAS_ARRAY_SET(e, render_objects);
+   EVAS_ARRAY_SET(e, pending_objects);
+   EVAS_ARRAY_SET(e, obscuring_objects);
+   EVAS_ARRAY_SET(e, temporary_objects);
+   EVAS_ARRAY_SET(e, calculate_objects);
+   EVAS_ARRAY_SET(e, clip_changes);
+
+#undef EVAS_ARRAY_SET
 
    return e;
 }
@@ -1152,3 +1157,122 @@ evas_load_error_str(int error)
         return "Unknown error";
      }
 }
+
+/**
+ * Convert a given color from HSV to RGB format.
+ *
+ * @param h The Hue component of the color.
+ * @param s The Saturation component of the color.
+ * @param v The Value component of the color.
+ * @param r The Red component of the color.
+ * @param g The Green component of the color.
+ * @param b The Blue component of the color.
+ *
+ * This function converts a given color in HSV color format to RGB
+ * color format.
+ *
+ * @ingroup Evas_Utils
+ **/
+EAPI void
+evas_color_hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b)
+{
+   evas_common_convert_color_hsv_to_rgb(h, s, v, r, g, b);
+}
+
+/**
+ * Convert a given color from RGB to HSV format.
+ *
+ * @param r The Red component of the color.
+ * @param g The Green component of the color.
+ * @param b The Blue component of the color.
+ * @param h The Hue component of the color.
+ * @param s The Saturation component of the color.
+ * @param v The Value component of the color.
+ *
+ * This function converts a given color in RGB color format to HSV
+ * color format.
+ *
+ * @ingroup Evas_Utils
+ **/
+EAPI void
+evas_color_rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v)
+{
+   evas_common_convert_color_rgb_to_hsv(r, g, b, h, s, v);
+}
+
+/**
+ * Pre-multiplies a rgb triplet by an alpha factor.
+ *
+ * @param a The alpha factor.
+ * @param r The Red component of the color.
+ * @param g The Green component of the color.
+ * @param b The Blue component of the color.
+ *
+ * This function pre-multiplies a given rbg triplet by an alpha
+ * factor. Alpha factor is used to define transparency.
+ *
+ * @ingroup Evas_Utils
+ **/
+EAPI void
+evas_color_argb_premul(int a, int *r, int *g, int *b)
+{
+   evas_common_convert_color_argb_premul(a, r, g, b);
+}
+
+/**
+ * Undo pre-multiplication of a rgb triplet by an alpha factor.
+ *
+ * @param a The alpha factor.
+ * @param r The Red component of the color.
+ * @param g The Green component of the color.
+ * @param b The Blue component of the color.
+ *
+ * This function undoes pre-multiplication a given rbg triplet by an
+ * alpha factor. Alpha factor is used to define transparency.
+ *
+ * @see evas_color_argb_premul().
+ *
+ * @ingroup Evas_Utils
+ **/
+EAPI void
+evas_color_argb_unpremul(int a, int *r, int *g, int *b)
+{
+   evas_common_convert_color_argb_unpremul(a, r, g, b);
+}
+
+/**
+ * Pre-multiplies data by an alpha factor.
+ *
+ * @param data The data value.
+ * @param len  The lenght value.
+ *
+ * This function pre-multiplies a given data by an alpha
+ * factor. Alpha factor is used to define transparency.
+ *
+ * @ingroup Evas_Utils
+ **/
+EAPI void
+evas_data_argb_premul(unsigned int *data, unsigned int len)
+{
+   if (!data || (len < 1)) return;
+   evas_common_convert_argb_premul(data, len);
+}
+
+/**
+ * Undo pre-multiplication data by an alpha factor.
+ *
+ * @param data The data value.
+ * @param len  The lenght value.
+ *
+ * This function undoes pre-multiplication of a given data by an alpha
+ * factor. Alpha factor is used to define transparency.
+ *
+ * @ingroup Evas_Utils
+ **/
+EAPI void
+evas_data_argb_unpremul(unsigned int *data, unsigned int len)
+{
+   if (!data || (len < 1)) return;
+   evas_common_convert_argb_unpremul(data, len);
+}
+
index c2fa14b..c1923cd 100644 (file)
@@ -26,6 +26,9 @@ struct _Evas_Object_Box_Accessor
 
 static const char _evas_object_box_type[] = "Evas_Object_Box";
 
+
+static void _sizing_eval(Evas_Object *obj);
+
 #define EVAS_OBJECT_BOX_DATA_GET(o, ptr)                       \
   Evas_Object_Box_Data *ptr = evas_object_smart_data_get(o)
 
@@ -139,6 +142,12 @@ _on_child_hints_changed(void *data, Evas *evas __UNUSED__, Evas_Object *o __UNUS
    if (!priv->layouting) evas_object_smart_changed(box);
 }
 
+static void
+_on_hints_changed(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *o , void *einfo __UNUSED__)
+{
+   _sizing_eval(o);
+}
+
 static Evas_Object_Box_Option *
 _evas_object_box_option_new(Evas_Object *o, Evas_Object_Box_Data *priv, Evas_Object *child)
 {
@@ -425,6 +434,9 @@ _evas_object_box_smart_add(Evas_Object *o)
      }
    _evas_object_box_parent_sc->add(o);
 
+
+   evas_object_event_callback_add
+     (o, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_hints_changed, o);
    priv->children = NULL;
    priv->align.h = 0.5;
    priv->align.v = 0.5;
index 0c52aeb..ca04c5a 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_private.h"
 #include "../engines/common/evas_convert_color.h"
@@ -19,8 +15,7 @@ struct _Evas_Object_Image
    DATA32            magic;
 
    struct {
-      Evas_Common_Transform  transform;
-      int         spread;
+      int                  spread;
       Evas_Coord_Rectangle fill;
       struct {
         short         w, h, stride;
@@ -37,6 +32,8 @@ struct _Evas_Object_Image
 
       unsigned char  smooth_scale : 1;
       unsigned char  has_alpha :1;
+      unsigned char  opaque :1;
+      unsigned char  opaque_valid :1;
    } cur, prev;
 
    int               pixels_checked_out;
@@ -341,6 +338,7 @@ evas_object_image_border_set(Evas_Object *obj, int l, int r, int t, int b)
    o->cur.border.r = r;
    o->cur.border.t = t;
    o->cur.border.b = b;
+   o->cur.opaque_valid = 0;
    o->changed = 1;
    evas_object_change(obj);
 }
@@ -592,6 +590,7 @@ evas_object_image_fill_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Co
    o->cur.fill.y = y;
    o->cur.fill.w = w;
    o->cur.fill.h = h;
+   o->cur.opaque_valid = 0;   
    o->changed = 1;
    evas_object_change(obj);
 }
@@ -681,86 +680,6 @@ evas_object_image_fill_spread_get(const Evas_Object *obj)
    return o->cur.spread;
 }
 
-EAPI void
-evas_object_image_fill_transform_set(Evas_Object *obj, Evas_Transform *t)
-{
-   Evas_Object_Image *o;
-
-   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();
-   if (!t)
-     {
-       o->cur.transform.mxx = 1;
-       o->cur.transform.mxy = 0;
-       o->cur.transform.mxz = 0;
-       o->cur.transform.myx = 0;
-       o->cur.transform.myy = 1;
-       o->cur.transform.myz = 0;
-       o->cur.transform.mzx = 0;
-       o->cur.transform.mzy = 0;
-       o->cur.transform.mzz = 1;
-
-       o->changed = 1;
-       evas_object_change(obj);
-       return;
-     }
-   if ( (o->cur.transform.mxx == t->mxx) ||
-        (o->cur.transform.mxy == t->mxy) ||
-        (o->cur.transform.mxy == t->mxy) ||
-        (o->cur.transform.mxy == t->mxy) ||
-        (o->cur.transform.mxy == t->mxy) ||
-        (o->cur.transform.mxy == t->mxy) ||
-        (o->cur.transform.mxy == t->mxy) ||
-        (o->cur.transform.mxy == t->mxy) ||
-        (o->cur.transform.mxy == t->mxy) )
-           return;
-
-   o->cur.transform.mxx = t->mxx;
-   o->cur.transform.mxy = t->mxy;
-   o->cur.transform.mxz = t->mxz;
-   o->cur.transform.myx = t->myx;
-   o->cur.transform.myy = t->myy;
-   o->cur.transform.myz = t->myz;
-   o->cur.transform.mzx = t->mzx;
-   o->cur.transform.mzy = t->mzy;
-   o->cur.transform.mzz = t->mzz;
-
-   o->changed = 1;
-   evas_object_change(obj);
-}
-
-/*FIXME: To be documented*/
-EAPI void
-evas_object_image_fill_transform_get(const Evas_Object *obj, Evas_Transform *t)
-{
-   Evas_Object_Image *o;
-
-   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();
-   if (t)
-     {
-        t->mxx = o->cur.transform.mxx;
-        t->mxy = o->cur.transform.mxy;
-        t->mxz = o->cur.transform.mxz;
-        t->myx = o->cur.transform.myx;
-        t->myy = o->cur.transform.myy;
-        t->myz = o->cur.transform.myz;
-        t->mzx = o->cur.transform.mzx;
-        t->mzy = o->cur.transform.mzy;
-        t->mzz = o->cur.transform.mzz;
-     }
-}
-
 /**
  * Sets the size of the given image object.
  *
@@ -796,19 +715,33 @@ evas_object_image_size_set(Evas_Object *obj, int w, int h)
    o->cur.image.w = w;
    o->cur.image.h = h;
    if (o->engine_data)
-     o->engine_data = obj->layer->evas->engine.func->image_size_set(obj->layer->evas->engine.data.output,
-                                                                   o->engine_data,
-                                                                   w, h);
+      o->engine_data = obj->layer->evas->engine.func->image_size_set(obj->layer->evas->engine.data.output,
+                                                                     o->engine_data,
+                                                                     w, h);
    else
-     o->engine_data = obj->layer->evas->engine.func->image_new_from_copied_data
-     (obj->layer->evas->engine.data.output, w, h, NULL, o->cur.has_alpha,
-      o->cur.cspace);
-
-   if (obj->layer->evas->engine.func->image_stride_get)
-     obj->layer->evas->engine.func->image_stride_get(obj->layer->evas->engine.data.output,
-                                                    o->engine_data, &stride);
+      o->engine_data = obj->layer->evas->engine.func->image_new_from_copied_data
+      (obj->layer->evas->engine.data.output, w, h, NULL, o->cur.has_alpha,
+          o->cur.cspace);
+   
+   if (o->engine_data)
+     {
+        if (obj->layer->evas->engine.func->image_scale_hint_set)
+           obj->layer->evas->engine.func->image_scale_hint_set
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, o->scale_hint);
+        if (obj->layer->evas->engine.func->image_content_hint_set)
+           obj->layer->evas->engine.func->image_content_hint_set
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, o->content_hint);
+        if (obj->layer->evas->engine.func->image_stride_get)
+           obj->layer->evas->engine.func->image_stride_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, &stride);
+        else
+           stride = w;
+     }
    else
-     stride = w;
+      stride = w;
    o->cur.image.stride = stride;
 
 /* FIXME - in engine call above
@@ -978,6 +911,26 @@ evas_object_image_data_set(Evas_Object *obj, void *data)
                                                                              data,
                                                                              o->cur.has_alpha,
                                                                              o->cur.cspace);
+        if (o->engine_data)
+          {
+             int stride = 0;
+             
+             if (obj->layer->evas->engine.func->image_scale_hint_set)
+                obj->layer->evas->engine.func->image_scale_hint_set
+                (obj->layer->evas->engine.data.output,
+                    o->engine_data, o->scale_hint);
+             if (obj->layer->evas->engine.func->image_content_hint_set)
+                obj->layer->evas->engine.func->image_content_hint_set
+                (obj->layer->evas->engine.data.output,
+                    o->engine_data, o->content_hint); 
+             if (obj->layer->evas->engine.func->image_stride_get)
+                obj->layer->evas->engine.func->image_stride_get
+                (obj->layer->evas->engine.data.output,
+                    o->engine_data, &stride);
+             else
+                stride = o->cur.image.w;
+             o->cur.image.stride = stride;
+         }
      }
    else
      {
@@ -1040,10 +993,30 @@ evas_object_image_data_get(const Evas_Object *obj, Eina_Bool for_writing)
 #endif
 
    data = NULL;
+   if (obj->layer->evas->engine.func->image_scale_hint_set)
+      obj->layer->evas->engine.func->image_scale_hint_set
+      (obj->layer->evas->engine.data.output,
+          o->engine_data, o->scale_hint);
+   if (obj->layer->evas->engine.func->image_content_hint_set)
+      obj->layer->evas->engine.func->image_content_hint_set
+      (obj->layer->evas->engine.data.output,
+          o->engine_data, o->content_hint);
    o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
                                                                  o->engine_data,
                                                                  for_writing,
                                                                  &data);
+   if (o->engine_data)
+     {
+        int stride = 0;
+
+        if (obj->layer->evas->engine.func->image_stride_get)
+           obj->layer->evas->engine.func->image_stride_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, &stride);
+        else
+           stride = o->cur.image.w;
+        o->cur.image.stride = stride;
+     }
    o->pixels_checked_out++;
    if (for_writing)
      {
@@ -1141,9 +1114,28 @@ evas_object_image_data_copy_set(Evas_Object *obj, void *data)
                                                                              o->cur.has_alpha,
                                                                              o->cur.cspace);
    if (o->engine_data)
-     o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
-                                                                    o->engine_data,
-                                                                    o->cur.has_alpha);
+     {
+        int stride = 0;
+
+        o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
+                                                                        o->engine_data,
+                                                                        o->cur.has_alpha);
+        if (obj->layer->evas->engine.func->image_scale_hint_set)
+           obj->layer->evas->engine.func->image_scale_hint_set
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, o->scale_hint);
+        if (obj->layer->evas->engine.func->image_content_hint_set)
+           obj->layer->evas->engine.func->image_content_hint_set
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, o->content_hint);
+        if (obj->layer->evas->engine.func->image_stride_get)
+           obj->layer->evas->engine.func->image_stride_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, &stride);
+        else
+           stride = o->cur.image.w;
+        o->cur.image.stride = stride;
+     }
    o->pixels_checked_out = 0;
    EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
 }
@@ -1211,12 +1203,29 @@ evas_object_image_alpha_set(Evas_Object *obj, Eina_Bool has_alpha)
    o->cur.has_alpha = has_alpha;
    if (o->engine_data)
      {
+        int stride = 0;
+        
 #ifdef EVAS_FRAME_QUEUING
         evas_common_pipe_op_image_flush(o->engine_data);
 #endif
         o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
                                                                     o->engine_data,
                                                                     o->cur.has_alpha);
+        if (obj->layer->evas->engine.func->image_scale_hint_set)
+           obj->layer->evas->engine.func->image_scale_hint_set
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, o->scale_hint);
+        if (obj->layer->evas->engine.func->image_content_hint_set)
+           obj->layer->evas->engine.func->image_content_hint_set
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, o->content_hint);
+        if (obj->layer->evas->engine.func->image_stride_get)
+           obj->layer->evas->engine.func->image_stride_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, &stride);
+        else
+           stride = o->cur.image.w;
+        o->cur.image.stride = stride;
      }
    evas_object_image_data_update_add(obj, 0, 0, o->cur.image.w, o->cur.image.h);
    EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
@@ -1884,9 +1893,11 @@ evas_object_image_native_surface_set(Evas_Object *obj, Evas_Native_Surface *surf
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
-   obj->layer->evas->engine.func->image_native_set(obj->layer->evas->engine.data.output,
-                                                  o->engine_data,
-                                                  surf);
+   if (!obj->layer->evas->engine.func->image_native_set) return;
+   o->engine_data = 
+      obj->layer->evas->engine.func->image_native_set(obj->layer->evas->engine.data.output,
+                                                      o->engine_data,
+                                                      surf);
 }
 
 /**
@@ -1910,6 +1921,7 @@ evas_object_image_native_surface_get(const Evas_Object *obj)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return NULL;
    MAGIC_CHECK_END();
+   if (!obj->layer->evas->engine.func->image_native_get) return NULL;
    return obj->layer->evas->engine.func->image_native_get(obj->layer->evas->engine.data.output,
                                                          o->engine_data);
 }
@@ -1935,14 +1947,28 @@ evas_object_image_scale_hint_set(Evas_Object *obj, Evas_Image_Scale_Hint hint)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+   if (o->scale_hint == hint) return;
 #ifdef EVAS_FRAME_QUEUING
-   if (o->scale_hint != hint)
-     {
-        if (o->engine_data)
-          evas_common_pipe_op_image_flush(o->engine_data);
-     }
+   if (o->engine_data)
+      evas_common_pipe_op_image_flush(o->engine_data);
 #endif
    o->scale_hint = hint;
+   if (o->engine_data)
+     {
+        int stride = 0;
+        
+        if (obj->layer->evas->engine.func->image_scale_hint_set)
+           obj->layer->evas->engine.func->image_scale_hint_set
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, o->scale_hint);
+        if (obj->layer->evas->engine.func->image_stride_get)
+           obj->layer->evas->engine.func->image_stride_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, &stride);
+        else
+           stride = o->cur.image.w;
+        o->cur.image.stride = stride;
+     }
 }
 
 /**
@@ -1989,7 +2015,28 @@ evas_object_image_content_hint_set(Evas_Object *obj, Evas_Image_Content_Hint hin
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+   if (o->content_hint == hint) return;
+#ifdef EVAS_FRAME_QUEUING
+   if (o->engine_data)
+      evas_common_pipe_op_image_flush(o->engine_data);
+#endif
    o->content_hint = hint;
+   if (o->engine_data)
+     {
+        int stride = 0;
+        
+        if (obj->layer->evas->engine.func->image_content_hint_set)
+           obj->layer->evas->engine.func->image_content_hint_set
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, o->content_hint);
+        if (obj->layer->evas->engine.func->image_stride_get)
+           obj->layer->evas->engine.func->image_stride_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, &stride);
+        else
+           stride = o->cur.image.w;
+        o->cur.image.stride = stride;
+     }
 }
 
 /**
@@ -2152,10 +2199,11 @@ evas_object_image_unload(Evas_Object *obj, Eina_Bool dirty)
    if (dirty)
      {
         if (o->engine_data)
-          o->engine_data = obj->layer->evas->engine.func->image_dirty_region(obj->layer->evas->engine.data.output,
-                                                                             o->engine_data,
-                                                                             0, 0,
-                                                                             o->cur.image.w, o->cur.image.h);
+          o->engine_data = obj->layer->evas->engine.func->image_dirty_region
+           (obj->layer->evas->engine.data.output,
+               o->engine_data,
+               0, 0,
+               o->cur.image.w, o->cur.image.h);
      }
    if (o->engine_data)
      obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
@@ -2186,27 +2234,32 @@ evas_object_image_load(Evas_Object *obj)
    lo.region.y = o->load_opts.region.y;
    lo.region.w = o->load_opts.region.w;
    lo.region.h = o->load_opts.region.h;
-   o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output,
-                                                             o->cur.file,
-                                                             o->cur.key,
-                                                             &o->load_error,
-                                                             &lo);
+   o->engine_data = obj->layer->evas->engine.func->image_load
+      (obj->layer->evas->engine.data.output,
+          o->cur.file,
+          o->cur.key,
+          &o->load_error,
+          &lo);
    if (o->engine_data)
      {
        int w, h;
        int stride;
 
-       obj->layer->evas->engine.func->image_size_get(obj->layer->evas->engine.data.output,
-                                                     o->engine_data, &w, &h);
+       obj->layer->evas->engine.func->image_size_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, &w, &h);
        if (obj->layer->evas->engine.func->image_stride_get)
-         obj->layer->evas->engine.func->image_stride_get(obj->layer->evas->engine.data.output,
-                                                         o->engine_data, &stride);
+         obj->layer->evas->engine.func->image_stride_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data, &stride);
        else
          stride = w;
-       o->cur.has_alpha = obj->layer->evas->engine.func->image_alpha_get(obj->layer->evas->engine.data.output,
-                                                                         o->engine_data);
-       o->cur.cspace = obj->layer->evas->engine.func->image_colorspace_get(obj->layer->evas->engine.data.output,
-                                                                           o->engine_data);
+       o->cur.has_alpha = obj->layer->evas->engine.func->image_alpha_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data);
+       o->cur.cspace = obj->layer->evas->engine.func->image_colorspace_get
+           (obj->layer->evas->engine.data.output,
+               o->engine_data);
        o->cur.image.w = w;
        o->cur.image.h = h;
        o->cur.image.stride = stride;
@@ -2299,8 +2352,8 @@ evas_object_image_new(void)
    o->cur.border.fill = 1;
    o->cur.border.scale = 1.0;
    o->cur.cspace = EVAS_COLORSPACE_ARGB8888;
-   o->cur.transform.mxx = o->cur.transform.myy = o->cur.transform.mzz = 1;
    o->cur.spread = EVAS_TEXTURE_REPEAT;
+   o->cur.opaque_valid = 0;
    o->prev = o->cur;
    return o;
 }
@@ -2893,14 +2946,24 @@ evas_object_image_is_opaque(Evas_Object *obj)
    /* this returns 1 if the internal object data implies that the object is */
    /* currently fully opaque over the entire rectangle it occupies */
    o = (Evas_Object_Image *)(obj->object_data);
-   if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1))
-     return 0;
-   if (((o->cur.border.l != 0) ||
-       (o->cur.border.r != 0) ||
-       (o->cur.border.t != 0) ||
-       (o->cur.border.b != 0)) &&
-       (!o->cur.border.fill)) return 0;
-   if (!o->engine_data) return 0;
+   if (o->cur.opaque_valid)
+     {
+        if (!o->cur.opaque) return 0;
+     }
+   else
+     {
+        o->cur.opaque = 0;
+        o->cur.opaque_valid = 1;
+        if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1))
+           return 0;
+        if (((o->cur.border.l != 0) ||
+             (o->cur.border.r != 0) ||
+             (o->cur.border.t != 0) ||
+             (o->cur.border.b != 0)) &&
+            (!o->cur.border.fill)) return 0;
+        if (!o->engine_data) return 0;
+        o->cur.opaque = 1;
+     }
    if ((obj->cur.map) && (obj->cur.usemap)) return 0;
    if (obj->cur.render_op == EVAS_RENDER_COPY) return 1;
    if (o->cur.has_alpha) return 0;
@@ -2915,14 +2978,24 @@ evas_object_image_was_opaque(Evas_Object *obj)
    /* this returns 1 if the internal object data implies that the object was */
    /* previously fully opaque over the entire rectangle it occupies */
    o = (Evas_Object_Image *)(obj->object_data);
-   if ((o->prev.fill.w < 1) || (o->prev.fill.h < 1))
-     return 0;
-   if (((o->prev.border.l != 0) ||
-       (o->prev.border.r != 0) ||
-       (o->prev.border.t != 0) ||
-       (o->prev.border.b != 0)) &&
-       (!o->prev.border.fill)) return 0;
-   if (!o->engine_data) return 0;
+   if (o->prev.opaque_valid)
+     {
+        if (!o->prev.opaque) return 0;
+     }
+   else
+     {
+        o->prev.opaque = 0;
+        o->prev.opaque_valid = 1;
+        if ((o->prev.fill.w < 1) || (o->prev.fill.h < 1))
+           return 0;
+        if (((o->prev.border.l != 0) ||
+             (o->prev.border.r != 0) ||
+             (o->prev.border.t != 0) ||
+             (o->prev.border.b != 0)) &&
+            (!o->prev.border.fill)) return 0;
+        if (!o->engine_data) return 0;
+        o->prev.opaque = 1;
+     }
    if (obj->prev.usemap) return 0;
    if (obj->prev.render_op == EVAS_RENDER_COPY) return 1;
    if (o->prev.has_alpha) return 0;
@@ -3033,10 +3106,11 @@ evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
    
    stride = o->cur.image.stride;
    
-   o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
-                                                                 o->engine_data,
-                                                                 0,
-                                                                 &data);
+   o->engine_data = obj->layer->evas->engine.func->image_data_get
+      (obj->layer->evas->engine.data.output,
+          o->engine_data,
+          0,
+          &data);
    if (!data)
      return 0;
 
@@ -3106,7 +3180,7 @@ evas_object_image_get_opaque_rect(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y
 }
 
 static int
-evas_object_image_can_map(Evas_Object *obj)
+evas_object_image_can_map(Evas_Object *obj __UNUSED__)
 {
    return 1;
 }
index 39f0acf..11a2f1e 100644 (file)
@@ -440,7 +440,7 @@ static void *evas_object_line_engine_data_get(Evas_Object *obj)
 }
 
 static int
-evas_object_line_is_opaque(Evas_Object *obj)
+evas_object_line_is_opaque(Evas_Object *obj __UNUSED__)
 {
    /* this returns 1 if the internal object data implies that the object is */
    /* currently fully opaque over the entire line it occupies */
@@ -448,7 +448,7 @@ evas_object_line_is_opaque(Evas_Object *obj)
 }
 
 static int
-evas_object_line_was_opaque(Evas_Object *obj)
+evas_object_line_was_opaque(Evas_Object *obj __UNUSED__)
 {
    /* this returns 1 if the internal object data implies that the object was */
    /* previously fully opaque over the entire line it occupies */
@@ -456,7 +456,7 @@ evas_object_line_was_opaque(Evas_Object *obj)
 }
 
 static int
-evas_object_line_is_inside(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
+evas_object_line_is_inside(Evas_Object *obj __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
 {
    /* this returns 1 if the canvas co-ordinates are inside the object based */
    /* on object private data. not much use for rects, but for polys, images */
@@ -465,7 +465,7 @@ evas_object_line_is_inside(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord
 }
 
 static int
-evas_object_line_was_inside(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
+evas_object_line_was_inside(Evas_Object *obj __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
 {
    /* this returns 1 if the canvas co-ordinates were inside the object based */
    /* on object private data. not much use for rects, but for polys, images */
index 1cbb9aa..a43d204 100644 (file)
@@ -35,7 +35,7 @@ get_layer_objects(Evas_Layer *l)
 
 /* evas internal stuff */
 Evas_Object *
-evas_object_new(Evas *e)
+evas_object_new(Evas *e __UNUSED__)
 {
    Evas_Object *obj;
 
index 43a85f8..19cc36d 100644 (file)
@@ -480,7 +480,7 @@ static void *evas_object_polygon_engine_data_get(Evas_Object *obj)
 }
 
 static int
-evas_object_polygon_is_opaque(Evas_Object *obj)
+evas_object_polygon_is_opaque(Evas_Object *obj __UNUSED__)
 {
    /* this returns 1 if the internal object data implies that the object is */
    /* currently fully opaque over the entire line it occupies */
@@ -488,7 +488,7 @@ evas_object_polygon_is_opaque(Evas_Object *obj)
 }
 
 static int
-evas_object_polygon_was_opaque(Evas_Object *obj)
+evas_object_polygon_was_opaque(Evas_Object *obj __UNUSED__)
 {
    /* this returns 1 if the internal object data implies that the object was */
    /* previously fully opaque over the entire line it occupies */
@@ -496,7 +496,7 @@ evas_object_polygon_was_opaque(Evas_Object *obj)
 }
 
 static int
-evas_object_polygon_is_inside(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
+evas_object_polygon_is_inside(Evas_Object *obj __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
 {
    /* this returns 1 if the canvas co-ordinates are inside the object based */
    /* on object private data. not much use for rects, but for polys, images */
@@ -505,7 +505,7 @@ evas_object_polygon_is_inside(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Co
 }
 
 static int
-evas_object_polygon_was_inside(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
+evas_object_polygon_was_inside(Evas_Object *obj __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
 {
    /* this returns 1 if the canvas co-ordinates were inside the object based */
    /* on object private data. not much use for rects, but for polys, images */
index 1b89f7e..cdc93fd 100644 (file)
@@ -1,4 +1,4 @@
-#include "evas_common.h"
+#include "evas_common.h" /* Includes evas_bidi_utils stuff. */
 #include "evas_private.h"
 
 /* save typing */
@@ -9,22 +9,25 @@
 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 Evas_Object_Text;
 
 struct _Evas_Object_Text
 {
    DATA32               magic;
 
    struct {
-      const char       *text;
-      const char       *font;
-      const char       *source;
-      Evas_Font_Size    size;
+      const Eina_Unicode  *text; /*The shaped text */
+      const char          *utf8_text; /* The text exposed to the API */
+      const char          *font;
+      const char          *source;
+      Evas_Font_Size       size;
       struct {
         unsigned char  r, g, b, a;
       } outline, shadow, glow, glow2;
 
-      unsigned char     style;
+      unsigned char               style;
+      Evas_BiDi_Props             intl_props;
+      Evas_BiDi_Paragraph_Props   paragraph_bidi_props;
    } cur, prev;
 
    float                ascent, descent;
@@ -74,6 +77,7 @@ static const Evas_Object_Func object_func =
      NULL,
      evas_object_text_scale_update,
      NULL,
+     NULL,
      NULL
 };
 
@@ -132,9 +136,12 @@ evas_object_text_font_source_set(Evas_Object *obj, const char *font_source)
    if ((o->cur.source) && (font_source) &&
        (!strcmp(o->cur.source, font_source)))
      return;
+   /*
    if (o->cur.source) eina_stringshare_del(o->cur.source);
    if (font_source) o->cur.source = eina_stringshare_add(font_source);
    else o->cur.source = NULL;
+    */
+   eina_stringshare_replace(&o->cur.source, font_source);
 }
 
 /**
@@ -172,8 +179,7 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
    int is, was = 0, pass = 0;
    int same_font = 0;
 
-   if (!font) return;
-   if (size <= 0) return;
+   if ((!font) || (size <= 0)) return;
    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
    return;
    MAGIC_CHECK_END();
@@ -209,9 +215,12 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
      }
    if (!same_font)
      {
+       /*
        if (o->cur.font) eina_stringshare_del(o->cur.font);
        if (font) o->cur.font = eina_stringshare_add(font);
        else o->cur.font = NULL;
+        */
+       eina_stringshare_replace(&o->cur.font, font);
        o->prev.font = NULL;
      }
    o->cur.size = size;
@@ -222,11 +231,11 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
      {
        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,
-                                  &w, &h);
-       o->ascent = ENFN->font_ascent_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);
@@ -314,12 +323,12 @@ evas_object_text_font_get(const Evas_Object *obj, const char **font, Evas_Font_S
  * @param text Text to display.
  */
 EAPI void
-evas_object_text_text_set(Evas_Object *obj, const char *text)
+evas_object_text_text_set(Evas_Object *obj, const char *_text)
 {
    Evas_Object_Text *o;
    int is, was;
-
-   if (!text) text = "";
+   Eina_Unicode *text;
+   
    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
    return;
    MAGIC_CHECK_END();
@@ -327,15 +336,39 @@ evas_object_text_text_set(Evas_Object *obj, const char *text)
    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
    return;
    MAGIC_CHECK_END();
-   if ((o->cur.text) && (text) && (!strcmp(o->cur.text, text))) return;
+
+   text = evas_common_encoding_utf8_to_unicode(_text, NULL);
+
+   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 */
-   if (o->cur.text) eina_stringshare_del(o->cur.text);
-   if ((text) && (*text)) o->cur.text = eina_stringshare_add(text);
-   else o->cur.text = NULL;
+   /*Update intl_props*/
+#ifdef BIDI_SUPPORT
+   evas_bidi_update_props(text, o->cur.intl_props.props);
+#endif
+   if (o->cur.text) eina_ustringshare_del(o->cur.text);
+   if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text);
+
+   if ((text) && (*text)) 
+     {
+        o->cur.text = eina_ustringshare_add(text);
+        o->cur.utf8_text = eina_stringshare_add(_text);
+     }
+   else 
+     {
+        o->cur.text = NULL;
+        o->cur.utf8_text = NULL;
+     }
+
    o->prev.text = NULL;
+
    if ((o->engine_data) && (o->cur.text))
      {
        int w, h;
@@ -343,7 +376,7 @@ evas_object_text_text_set(Evas_Object *obj, const char *text)
 
        ENFN->font_string_size_get(ENDT,
                                   o->engine_data,
-                                  o->cur.text,
+                                  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;
@@ -373,6 +406,7 @@ evas_object_text_text_set(Evas_Object *obj, const char *text)
                                obj->layer->evas->last_timestamp,
                                NULL);
    evas_object_inform_call_resize(obj);
+   if (text) free(text);
 }
 
 /**
@@ -392,7 +426,7 @@ evas_object_text_text_get(const Evas_Object *obj)
    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
    return NULL;
    MAGIC_CHECK_END();
-   return o->cur.text;
+   return o->cur.utf8_text;
 }
 
 /**
@@ -522,7 +556,7 @@ evas_object_text_horiz_advance_get(const Evas_Object *obj)
    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);
+   return ENFN->font_h_advance_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props);
 }
 
 /**
@@ -545,7 +579,7 @@ evas_object_text_vert_advance_get(const Evas_Object *obj)
    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);
+   return ENFN->font_v_advance_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props);
 }
 
 /**
@@ -585,10 +619,8 @@ evas_object_text_char_pos_get(const Evas_Object *obj, int pos, Evas_Coord *cx, E
    if (!o->cur.text) return EINA_FALSE;
    inset =
      ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
-   ret = ENFN->font_char_coords_get(ENDT, o->engine_data, o->cur.text,
-                                                            pos,
-                                                            &x, &y,
-                                                            &w, &h);
+   ret = ENFN->font_char_coords_get(ENDT, o->engine_data, o->cur.text, &o->cur.intl_props,
+                                   pos, &x, &y, &w, &h);
    evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
    y += o->max_ascent - t;
    x -= inset + l;
@@ -597,14 +629,14 @@ evas_object_text_char_pos_get(const Evas_Object *obj, int pos, Evas_Coord *cx, E
        w += x;
        x = 0;
      }
-   if (x + w > obj->cur.geometry.w) w = obj->cur.geometry.w - x;
+   if ((x + w) > obj->cur.geometry.w) w = obj->cur.geometry.w - x;
    if (w < 0) w = 0;
    if (y < 0)
      {
        h += y;
        y = 0;
      }
-   if (y + h > obj->cur.geometry.h) h = obj->cur.geometry.h - y;
+   if ((y + h) > obj->cur.geometry.h) h = obj->cur.geometry.h - y;
    if (h < 0) h = 0;
    if (cx) *cx = x;
    if (cy) *cy = y;
@@ -642,7 +674,7 @@ evas_object_text_last_up_to_pos(const Evas_Object *obj, Evas_Coord x, Evas_Coord
      ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
    return ENFN->font_last_up_to_pos(ENDT,
                                       o->engine_data,
-                                      o->cur.text,
+                                      o->cur.text, &o->cur.intl_props,
                                       x + inset,
                                       y - o->max_ascent);      
 }
@@ -674,7 +706,7 @@ evas_object_text_char_coords_get(const Evas_Object *obj, Evas_Coord x, Evas_Coor
      ENFN->font_inset_get(ENDT, o->engine_data, o->cur.text);
    ret = ENFN->font_char_at_coords_get(ENDT,
                                       o->engine_data,
-                                      o->cur.text,
+                                      o->cur.text, &o->cur.intl_props,
                                       x + inset,
                                       y - o->max_ascent,
                                       &rx, &ry,
@@ -687,14 +719,14 @@ evas_object_text_char_coords_get(const Evas_Object *obj, Evas_Coord x, Evas_Coor
        rw += rx;
        rx = 0;
      }
-   if (rx + rw > obj->cur.geometry.w) rw = obj->cur.geometry.w - rx;
+   if ((rx + rw) > obj->cur.geometry.w) rw = obj->cur.geometry.w - rx;
    if (rw < 0) rw = 0;
    if (ry < 0)
      {
        rh += ry;
        ry = 0;
      }
-   if (ry + rh > obj->cur.geometry.h) rh = obj->cur.geometry.h - ry;
+   if ((ry + rh) > obj->cur.geometry.h) rh = obj->cur.geometry.h - ry;
    if (rh < 0) rh = 0;
    if (cx) *cx = rx;
    if (cy) *cy = ry;
@@ -722,8 +754,7 @@ evas_object_text_style_set(Evas_Object *obj, Evas_Text_Style_Type style)
    MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
    return;
    MAGIC_CHECK_END();
-   if (o->cur.style == style)
-     return;
+   if (o->cur.style == style) return;
    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);
@@ -1036,8 +1067,8 @@ evas_font_path_append(Evas *e, const char *path)
    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
    return;
    MAGIC_CHECK_END();
-   if (!path) return;
 
+   if (!path) return;
    e->font_path = eina_list_append(e->font_path, eina_stringshare_add(path));
 }
 
@@ -1264,10 +1295,9 @@ evas_string_char_next_get(const char *str, int pos, int *decoded)
    int p, d;
 
    if (decoded) *decoded = 0;
-   if (!str) return 0;
-   if (pos < 0) return 0;
+   if ((!str) || (pos < 0)) return 0;
    p = pos;
-   d = evas_common_font_utf8_get_next((unsigned char *)str, &p);
+   d = evas_common_encoding_utf8_get_next(str, &p);
    if (decoded) *decoded = d;
    return p;
 }
@@ -1285,10 +1315,9 @@ evas_string_char_prev_get(const char *str, int pos, int *decoded)
    int p, d;
 
    if (decoded) *decoded = 0;
-   if (!str) return 0;
-   if (pos < 1) return 0;
+   if ((!str) || (pos < 1)) return 0;
    p = pos;
-   d = evas_common_font_utf8_get_prev((unsigned char *)str, &p);
+   d = evas_common_encoding_utf8_get_prev(str, &p);
    if (decoded) *decoded = d;
    return p;
 }
@@ -1302,8 +1331,8 @@ evas_string_char_prev_get(const char *str, int pos, int *decoded)
 EAPI int
 evas_string_char_len_get(const char *str)
 {
-       if (!str) return 0;
-       return evas_common_font_utf8_get_len((const unsigned char *) str);
+   if (!str) return 0;
+   return evas_common_encoding_utf8_get_len(str);
 }
 
 /**
@@ -1427,6 +1456,10 @@ evas_object_text_new(void)
    o = calloc(1, sizeof(Evas_Object_Text));
    o->magic = MAGIC_OBJ_TEXT;
    o->prev = o->cur;
+   o->cur.intl_props.props = &o->cur.paragraph_bidi_props;
+#ifdef BIDI_SUPPORT
+   o->cur.intl_props.props->direction = EVAS_BIDI_PARAGRAPH_NATURAL;
+#endif
    return o;
 }
 
@@ -1441,10 +1474,13 @@ evas_object_text_free(Evas_Object *obj)
    return;
    MAGIC_CHECK_END();
    /* free obj */
-   if (o->cur.text) eina_stringshare_del(o->cur.text);
+   if (o->cur.text) eina_ustringshare_del(o->cur.text);
+   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);
+   if (o->cur.intl_props.props->embedding_levels) free(o->cur.intl_props.props->embedding_levels);
+   if (o->cur.intl_props.props->char_types) free(o->cur.intl_props.props->char_types);
    o->magic = 0;
    free(o);
 }
@@ -1456,11 +1492,11 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur
    Evas_Object_Text *o;
    const char vals[5][5] =
      {
-         {0, 1, 2, 1, 0},
-         {1, 3, 4, 3, 1},
-         {2, 4, 5, 4, 2},
-         {1, 3, 4, 3, 1},
-         {0, 1, 2, 1, 0}
+       {0, 1, 2, 1, 0},
+       {1, 3, 4, 3, 1},
+       {2, 4, 5, 4, 2},
+       {1, 3, 4, 3, 1},
+       {0, 1, 2, 1, 0}
      };
    int sl = 0, st = 0;
 
@@ -1530,7 +1566,7 @@ 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.text, &o->cur.intl_props);
 #if 0
 #define DRAW_TEXT(ox, oy) \
    if ((o->engine_data) && (o->cur.text)) \
@@ -1547,7 +1583,7 @@ evas_object_text_render(Evas_Object *obj, void *output, void *context, void *sur
                     obj->cur.cache.geometry.h, \
                     obj->cur.geometry.w, \
                     obj->cur.geometry.h, \
-                    o->cur.text);
+                    o->cur.text, &o->cur.intl_props);
 #endif
    /* shadows */
    if (o->cur.style == EVAS_TEXT_STYLE_SHADOW)
@@ -1652,11 +1688,11 @@ evas_object_text_render_pre(Evas_Object *obj)
    /* dont pre-render the obj twice! */
    if (obj->pre_render_done) return;
    obj->pre_render_done = 1;
-   /* pre-render phase. this does anything an object needs to do just before */
-   /* rendering. this could mean loading the image data, retrieving it from */
-   /* elsewhere, decoding video etc. */
-   /* then when this is done the object needs to figure if it changed and */
-   /* if so what and where and add thr appropriate redraw rectangles */
+   /* pre-render phase. this does anything an object needs to do just before
+    rendering. This could mean loading the image data, retrieving it from 
+    elsewhere, decoding video etc.
+    Then when this is done the object needs to figure if it changed and 
+    if so what and where and add the appropriate redraw rectangles */
    o = (Evas_Object_Text *)(obj->object_data);
    /* if someone is clipping this obj - go calculate the clipper */
    if (obj->cur.clipper)
@@ -1665,19 +1701,21 @@ evas_object_text_render_pre(Evas_Object *obj)
          evas_object_clip_recalc(obj->cur.clipper);
        obj->cur.clipper->func->render_pre(obj->cur.clipper);
      }
-   /* now figure what changed and add draw rects */
-   /* if it just became visible or invisible */
+   /* now figure what changed and add draw rects
+    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)
      {
-       evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, obj, is_v, was_v);
+       evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, 
+                                             obj, is_v, was_v);
        goto done;
      }
    if ((obj->cur.map != obj->prev.map) ||
        (obj->cur.usemap != obj->prev.usemap))
      {
-       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
+       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, 
+                                           obj);
         goto done;
      }
    /* its not visible - we accounted for it appearing or not so just abort */
@@ -1687,7 +1725,8 @@ evas_object_text_render_pre(Evas_Object *obj)
    /* if we restacked (layer or just within a layer) and dont clip anyone */
    if (obj->restack)
      {
-       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
+       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, 
+                                           obj);
        goto done;
      }
    /* if it changed color */
@@ -1696,37 +1735,43 @@ evas_object_text_render_pre(Evas_Object *obj)
        (obj->cur.color.b != obj->prev.color.b) ||
        (obj->cur.color.a != obj->prev.color.a))
      {
-       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
+       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, 
+                                           obj);
        goto done;
      }
-   /* if it changed geometry - and obviously not visibility or color */
-   /* caluclate differences since we have a constant color fill */
-   /* we really only need to update the differences */
+   /* if it changed geometry - and obviously not visibility or color
+    calculate differences since we have a constant color fill
+    we really only need to update the differences */
    if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
        (obj->cur.geometry.y != obj->prev.geometry.y) ||
        (obj->cur.geometry.w != obj->prev.geometry.w) ||
        (obj->cur.geometry.h != obj->prev.geometry.h))
      {
-       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
+       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, 
+                                           obj);
        goto done;
      }
    if (obj->cur.render_op != obj->prev.render_op)
      {
-       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
+       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, 
+                                           obj);
        goto done;
      }
    if (obj->cur.scale != obj->prev.scale)
      {
-       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
+       evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, 
+                                           obj);
        goto done;
      }
    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) && 
+               (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) && (strcmp(o->cur.text, o->prev.text))) ||
+           ((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.style != o->prev.style)) ||
@@ -1747,12 +1792,14 @@ evas_object_text_render_pre(Evas_Object *obj)
            ((o->cur.glow2.b != o->prev.glow2.b)) ||
            ((o->cur.glow2.a != o->prev.glow2.a)))
          {
-            evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
+            evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, 
+                                                obj);
             goto done;
          }
      }
    done:
-   evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, obj, is_v, was_v);
+   evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, 
+                                        obj, is_v, was_v);
 }
 
 static void
@@ -1760,9 +1807,9 @@ evas_object_text_render_post(Evas_Object *obj)
 {
    Evas_Object_Text *o;
 
-   /* this moves the current data to the previous state parts of the object */
-   /* in whatever way is safest for the object. also if we don't need object */
-   /* data anymore we can free it if the object deems this is a good idea */
+   /* this moves the current data to the previous state parts of the object
+    in whatever way is safest for the object. also if we don't need object
+    data anymore we can free it if the object deems this is a good idea */
    o = (Evas_Object_Text *)(obj->object_data);
    /* remove those pesky changes */
    evas_object_clip_changes_clean(obj);
@@ -1772,7 +1819,8 @@ evas_object_text_render_post(Evas_Object *obj)
    o->changed = 0;
 }
 
-static unsigned int evas_object_text_id_get(Evas_Object *obj)
+static unsigned int 
+evas_object_text_id_get(Evas_Object *obj)
 {
    Evas_Object_Text *o;
 
@@ -1781,7 +1829,8 @@ static unsigned int evas_object_text_id_get(Evas_Object *obj)
    return MAGIC_OBJ_TEXT;
 }
 
-static unsigned int evas_object_text_visual_id_get(Evas_Object *obj)
+static unsigned int 
+evas_object_text_visual_id_get(Evas_Object *obj)
 {
    Evas_Object_Text *o;
 
@@ -1790,7 +1839,8 @@ static unsigned int evas_object_text_visual_id_get(Evas_Object *obj)
    return MAGIC_OBJ_SHAPE;
 }
 
-static void *evas_object_text_engine_data_get(Evas_Object *obj)
+static void *
+evas_object_text_engine_data_get(Evas_Object *obj)
 {
    Evas_Object_Text *o;
 
@@ -1800,18 +1850,18 @@ static void *evas_object_text_engine_data_get(Evas_Object *obj)
 }
 
 static int
-evas_object_text_is_opaque(Evas_Object *obj)
+evas_object_text_is_opaque(Evas_Object *obj __UNUSED__)
 {
-   /* this returns 1 if the internal object data implies that the object is */
-   /* currently fulyl opque over the entire gradient it occupies */
+   /* this returns 1 if the internal object data implies that the object is 
+    currently fully opaque over the entire gradient it occupies */
    return 0;
 }
 
 static int
-evas_object_text_was_opaque(Evas_Object *obj)
+evas_object_text_was_opaque(Evas_Object *obj __UNUSED__)
 {
-   /* this returns 1 if the internal object data implies that the object was */
-   /* currently fulyl opque over the entire gradient it occupies */
+   /* this returns 1 if the internal object data implies that the object was
+    currently fully opaque over the entire gradient it occupies */
    return 0;
 }
 
@@ -1858,7 +1908,7 @@ _evas_object_text_rehint(Evas_Object *obj)
 
        ENFN->font_string_size_get(ENDT,
                                   o->engine_data,
-                                  o->cur.text,
+                                  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;
index 4082bb6..5d7cda2 100644 (file)
@@ -1,7 +1,133 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+/**
+ * @addtogroup Evas_Object_Textblock
+ *
+ * @{
+ */
+
+/**
+ * @section Evas_Object_Textblock_Tutorial Textblock Object Tutorial
+ *
+ * This part explains about the textblock object's API and proper usage.
+ * If you want to develop textblock, you should also refer to @ref Evas_Object_Textblock_Internal.
+ * The main user of the textblock object is the edje entry object in Edje, so
+ * that's a good place to learn from, but I think this document is more than
+ * enough, if it's not, please request for me info and I'll update it.
+ *
+ * @subsection textblock_intro Introduction
+ * The textblock objects is, as implied, an object that can show big chunks of
+ * text. Textblock supports many features including: Text formatting, automatic
+ * and manual text alignment, embedding items (for example icons) and more.
+ * Textblock has three important parts, the text paragraphs, the format nodes
+ * and the cursors.
+ *
+ * @subsection textblock_cursors Textblock Object Cursors
+ * A textblock Cursor @ref Evas_Textblock_Cursor is data type that represents
+ * a position in a textblock. Each cursor contains information about the
+ * paragraph it points to, the position in that paragraph and the object itself.
+ * Cursors register to textblock objects upon creation, this means that once
+ * you created a cursor, it belongs to a specific obj and you can't for example
+ * copy a cursor "into" a cursor of a different object. Registered cursors
+ * also have the added benefit of updating automatically upon textblock changes,
+ * this means that if you have a cursor pointing to a specific character, it'll
+ * still point to it even after you change the whole object completely (as long
+ * as the char was not deleted), this is not possible without updating, beacuse
+ * as mentioned, each cursor holds a character position. There are many
+ * functions that handle cursors, just check out the evas_textblock_cursor*
+ * functions. For creation and deletion of cursors check out:
+ * @see evas_object_textblock_cursor_new()
+ * @see evas_textblock_cursor_free()
+ * @note Cursors are generally the correct way to handle text in the textblock object, and there are enough functions to do everything you need with them (no need to get big chunks of text and processing them yourself).
+ *
+ * @subsection textblock_paragraphs Textblock Object Paragraphs
+ * The textblock object is made out of text splitted to paragraphs (delimited
+ * by the paragraph separation character). Each paragraph has many (or none)
+ * format nodes associated with it which are responsible for the formatting
+ * of that paragraph.
+ *
+ * @subsection textblock_format_nodes Textblock Object Format Nodes
+ * As explained in @ref textblock_paragraphs each one of the format nodes
+ * is associated with a paragraph.
+ * There are two types of format nodes, visible and invisible:
+ * Visible: formats that a cursor can point to, i.e formats that
+ * occupy space, for example: newlines, tabs, items and etc.
+ * Invisible: formats that don't occupy space, for example: bold and underline.
+ * Being able to access format nodes is very important for some uses. For
+ * example, edje uses the "<a>" format to create links in the text (and pop
+ * popups above them when clicked). For the textblock object a is just a
+ * formatting instruction (how to color the text), but edje utilizes the access
+ * to the format nodes to make it do more.
+ * For more information, take a look at all the evas_textblock_node_format_*
+ * functions.
+ * The translation of "<tag>" tags to actual format is done according to the
+ * tags defined in the style, see @ref evas_textblock_style_set
+ *
+ * @subsection textblock_special_formats Special Formats
+ * @todo Write @textblock_special_formats
  */
 
+/**
+ * @internal
+ * @section Evas_Object_Textblock_Internal Internal Textblock Object Tutorial
+ *
+ * This explains the internal design of the Evas Textblock Object, it's assumed
+ * that the reader of this section has already read @ref Evas_Object_Textblock_Tutorial "Textblock's usage docs.".
+ *
+ * @subsection textblock_internal_intro Introduction
+ * There are two main parts to the textblock object, the first being the node
+ * system, and the second being the layout system. The former is just an
+ * internal representation of the markup text, while the latter is the internal
+ * visual representation of the text (i.e positioning, sizing, fonts and etc).
+ *
+ * @subsection textblock_nodes The Nodes system
+ * The nodes mechanism consists of two main data types:
+ * ::Evas_Object_Textblock_Node_Text and ::Evas_Object_Textblock_Node_Format
+ * the former is for Text nodes and the latter is for format nodes.
+ * There's always at least one text node, even if there are only formats.
+ *
+ * @subsection textblock_nodes_text Text nodes
+ * Each text node is essentially a paragraph, it includes an @ref Eina_UStrbuf
+ * that stores the actual paragraph text, a utf8 string to store the paragraph
+ * text in utf8 (which is not used internally at all), A pointer to it's
+ * main @ref textblock_nodes_format_internal "Format Node" and the paragraph's
+ * @ref evas_bidi_props "BiDi properties". The pointer to the format node may be
+ * NULL if there's no format node anywhere before the end of the text node,
+ * not even in previous text nodes. If not NULL, it points to the first format
+ * node pointing to text inside of the text node, or if there is none, it points
+ * to the previous's text nodes format node. Each paragraph has a format node
+ * representing a paragraph separator pointing to it's last position except
+ * for the last paragraph, which has no such constraint. This constraint
+ * happens because text nodes are paragraphs and paragraphs are delimited by
+ * paragraph separators.
+ *
+ * @subsection textblock_nodes_format_internal Format Nodes - Internal
+ * Each format node stores a group of format information, for example the
+ * markup: \<font=Vera,Kochi font_size=10 align=left\> will all be inserted
+ * inside the same format node, altohugh it consists of different formatting
+ * commands.
+ * Each node has a pointer to it's text node, this pointer is NEVER NULL, even
+ * if there's only one format, and no text, a text node is created. Each format
+ * node includes an offset from the last format node of the same text node. For
+ * example, the markup "0<b>12</b>" will create two format nodes, the first
+ * having an offset of 1 and the second an offset of 2. Each format node also
+ * includes a @ref Eina_Strbuf that includes the textual representation of the
+ * format, and a boolean stating if the format is a visible format or not, see
+ * @ref textblock_nodes_format_visible
+ *
+ * @subsection textblock_nodes_format_visible Visible Format Nodes
+ * There are two types of format nodes, visible and invisible. They are the same
+ * in every way, except for the representation in the text node. While invisible
+ * format nodes have no representation in the text node, the visible ones do.
+ * The Uniceode object replacement character (0xFFFC) is inserted to every place
+ * a visible format node points to. This makes it very easy to treat visible
+ * formats as items in the text, both for BiDi purposes and cursor handling
+ * purposes.
+ * Here are a few example visible an invisible formats:
+ * Visible: newline char, tab, paragraph separator and an embedded item.
+ * Invisible: setting the color, font or alignment of the text.
+ *
+ * @subsection textblock_layout The layout system
+ * @todo write @ref textblock_layout
+ */
 #include "evas_common.h"
 #include "evas_private.h"
 
 /* private magic number for textblock objects */
 static const char o_type[] = "textblock";
 
+/* The char to be inserted instead of visible formats */
+#define EVAS_TEXTBLOCK_REPLACEMENT_CHAR 0xFFFC
+
 /* private struct for textblock object internal data */
+/**
+ * @intrenal
+ * @typedef Evas_Object_Textblock
+ * The actual textblock object.
+ */
 typedef struct _Evas_Object_Textblock             Evas_Object_Textblock;
+/**
+ * @intrenal
+ * @typedef Evas_Object_Style_Tag
+ * The structure used for finding style tags.
+ */
 typedef struct _Evas_Object_Style_Tag             Evas_Object_Style_Tag;
-typedef struct _Evas_Object_Textblock_Node        Evas_Object_Textblock_Node;
+/**
+ * @intrenal
+ * @typedef Evas_Object_Textblock_Node_Text
+ * A text node.
+ */
+typedef struct _Evas_Object_Textblock_Node_Text   Evas_Object_Textblock_Node_Text;
+/*
+ * Defined in Evas.h
+typedef struct _Evas_Object_Textblock_Node_Format Evas_Object_Textblock_Node_Format;
+*/
+
+/**
+ * @intrenal
+ * @typedef Evas_Object_Textblock_Paragraph
+ * A layouting paragraph.
+ */
+typedef struct _Evas_Object_Textblock_Paragraph   Evas_Object_Textblock_Paragraph;
+/**
+ * @intrenal
+ * @typedef Evas_Object_Textblock_Line
+ * A layouting line.
+ */
 typedef struct _Evas_Object_Textblock_Line        Evas_Object_Textblock_Line;
+/**
+ * @intrenal
+ * @typedef Evas_Object_Textblock_Item
+ * A layouting item.
+ */
 typedef struct _Evas_Object_Textblock_Item        Evas_Object_Textblock_Item;
+/**
+ * @intrenal
+ * @typedef Evas_Object_Textblock_Format_Item
+ * A layouting format item.
+ */
 typedef struct _Evas_Object_Textblock_Format_Item Evas_Object_Textblock_Format_Item;
+/**
+ * @intrenal
+ * @typedef Evas_Object_Textblock_Format
+ * A textblock format.
+ */
 typedef struct _Evas_Object_Textblock_Format      Evas_Object_Textblock_Format;
 
 /* the current state of the formatting */
+/**
+ * @intrenal
+ * @def GET_PREV(text, ind)
+ * Gets the index of the previous char in the text text, this simply returns
+ * the current char pointed to and decrements ind but ensures it stays in
+ * the text range.
+ */
+#define GET_PREV(text, ind) (((ind) > 0) ? (text[(ind)--]) : (text[ind]))
+/**
+ * @intrenal
+ * @def GET_NEXT(text, ind)
+ * Gets the index of the next in the text text, this simply returns
+ * the current char pointed to and increments indd but ensures it stays in
+ * the text range.
+ */
+#define GET_NEXT(text, ind) ((text[ind]) ? (text[(ind)++]) : (text[ind]))
 
-#define  NODE_TEXT   0
-#define  NODE_FORMAT 1
-
+/*FIXME: document the structs and struct items. */
 struct _Evas_Object_Style_Tag
 {
    EINA_INLIST;
@@ -35,11 +224,43 @@ struct _Evas_Object_Style_Tag
    size_t replace_len;
 };
 
-struct _Evas_Object_Textblock_Node
+struct _Evas_Object_Textblock_Node_Text
+{
+   EINA_INLIST;
+   Eina_UStrbuf                       *unicode;
+   char *                              utf8;
+   Evas_Object_Textblock_Node_Format  *format_node;
+   Evas_BiDi_Paragraph_Props           bidi_props;
+};
+
+struct _Evas_Object_Textblock_Node_Format
+{
+   EINA_INLIST;
+   Eina_Strbuf                        *format;
+   Evas_Object_Textblock_Node_Text    *text_node;
+   size_t                              offset;
+   Eina_Bool                           visible;
+};
+
+/**
+ * @intrenal
+ * @def _NODE_TEXT(x)
+ * A convinience macro for casting to a text node.
+ */
+#define _NODE_TEXT(x)  ((Evas_Object_Textblock_Node_Text *) (x))
+/**
+ * @intrenal
+ * @def _NODE_FORMAT(x)
+ * A convinience macro for casting to a format node.
+ */
+#define _NODE_FORMAT(x)  ((Evas_Object_Textblock_Node_Format *) (x))
+
+struct _Evas_Object_Textblock_Paragraph
 {
    EINA_INLIST;
-   Eina_Strbuf *text;
-   int          type;
+   Evas_Object_Textblock_Line        *lines;
+   int                                x, y, w, h;
+   int                                par_no;
 };
 
 struct _Evas_Object_Textblock_Line
@@ -55,31 +276,33 @@ struct _Evas_Object_Textblock_Line
 struct _Evas_Object_Textblock_Item
 {
    EINA_INLIST;
-   char                         *text;
-   Evas_Object_Textblock_Format *format;
-   Evas_Object_Textblock_Node   *source_node;
-   int                           x, w, h;
-   int                           inset, baseline;
-   int                           source_pos;
-   unsigned char                 type;
+   Eina_Unicode                    *text;
+   Evas_Object_Textblock_Format    *format;
+   Evas_Object_Textblock_Node_Text *source_node;
+   int                              x, w, h;
+   int                              inset, baseline;
+   size_t                           source_pos;
+   unsigned char                    type;
+   Evas_BiDi_Props                  bidi_props;
 };
 
 struct _Evas_Object_Textblock_Format_Item
 {
    EINA_INLIST;
-   const char                   *item;
-   Evas_Object_Textblock_Node   *source_node;
-   int                           x, w, h, y, ascent, descent;
-   unsigned char                 vsize : 2;
-   unsigned char                 size : 2;
-   unsigned char                 formatme : 1;
-   unsigned char                 ___padding___ : 3;
+   const char                          *item;
+   Evas_Object_Textblock_Node_Format   *source_node;
+   int                                  x, w, h, y, ascent, descent;
+   unsigned char                        vsize : 2;
+   unsigned char                        size : 2;
+   unsigned char                        formatme : 1;
+   unsigned char                        ___padding___ : 3;
 };
 
 struct _Evas_Object_Textblock_Format
 {
    int                  ref;
    double               halign;
+   Eina_Bool            halign_auto;
    double               valign;
    struct {
       const char       *name;
@@ -102,6 +325,7 @@ struct _Evas_Object_Textblock_Format
    double               linerelsize;
    int                  linegap;
    double               linerelgap;
+   double               linefill;
    unsigned char        style;
    unsigned char        wrap_word : 1;
    unsigned char        wrap_char : 1;
@@ -122,33 +346,34 @@ struct _Evas_Textblock_Style
 
 struct _Evas_Textblock_Cursor
 {
-   Evas_Object                *obj;
-   int                         pos;
-   Evas_Object_Textblock_Node *node;
-   Eina_Bool                   eol : 1;
+   Evas_Object                     *obj;
+   size_t                           pos;
+   Evas_Object_Textblock_Node_Text *node;
+
 };
 
 struct _Evas_Object_Textblock
 {
-   DATA32                       magic;
-   Evas_Textblock_Style        *style;
-   Evas_Textblock_Cursor       *cursor;
-   Eina_List                   *cursors;
-   Evas_Object_Textblock_Node  *nodes;
-   Evas_Object_Textblock_Line  *lines;
-   int                          last_w;
+   DATA32                              magic;
+   Evas_Textblock_Style               *style;
+   Evas_Textblock_Cursor              *cursor;
+   Eina_List                          *cursors;
+   Evas_Object_Textblock_Node_Text    *text_nodes;
+   Evas_Object_Textblock_Node_Format  *format_nodes;
+   Evas_Object_Textblock_Paragraph    *paragraphs;
+   int                                 last_w;
    struct {
-      int                       l, r, t, b;
+      int                              l, r, t, b;
    } style_pad;
-   char                        *markup_text;
-   void                        *engine_data;
-   const char                  *repch;
+   char                               *markup_text;
+   void                               *engine_data;
+   const char                         *repch;
    struct {
-      int                       w, h;
-      unsigned char             valid : 1;
+      int                              w, h;
+      unsigned char                    valid : 1;
    } formatted, native;
-   unsigned char                redraw : 1;
-   unsigned char                changed : 1;
+   unsigned char                       redraw : 1;
+   unsigned char                       changed : 1;
 };
 
 /* private methods for textblock objects */
@@ -219,12 +444,23 @@ static const Evas_Object_Func object_func =
    MAGIC_CHECK_END();
 
 
-/**
- * @addtogroup Evas_Object_Textblock
- * @{
- */
+
+static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_before_or_at_pos_get(const Evas_Textblock_Cursor *cur);
+static size_t _evas_textblock_node_format_pos_get(const Evas_Object_Textblock_Node_Format *fmt);
+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_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.
+ * @param ts The ts to be cleared. Must not be NULL.
+ */
 static void
 _style_clear(Evas_Textblock_Style *ts)
 {
@@ -245,6 +481,16 @@ _style_clear(Evas_Textblock_Style *ts)
    ts->tags = 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.
+ * @param s The replace string to match.
+ * @param replace_len the length of the replace string.
+ * @param[out] tag_len The length of the tag found. - Must not be NULL.
+ * @return The tag found.
+ */
 static inline const char *
 _style_match_replace(Evas_Textblock_Style *ts, const char *s, size_t replace_len, size_t *tag_len)
 {
@@ -263,6 +509,15 @@ _style_match_replace(Evas_Textblock_Style *ts, const char *s, size_t replace_len
    return NULL;
 }
 
+/**
+ * @internal
+ * Searches inside the tags stored in the style for the tag matching s.
+ * @param ts The ts to be cleared. Must not be NULL.
+ * @param s The tag to be matched.
+ * @param tag_len the length of the tag string.
+ * @param[out] replace_len The length of the replcaement found. - Must not be NULL.
+ * @return The replacement string found.
+ */
 static inline const char *
 _style_match_tag(Evas_Textblock_Style *ts, const char *s, size_t tag_len, size_t *replace_len)
 {
@@ -281,25 +536,43 @@ _style_match_tag(Evas_Textblock_Style *ts, const char *s, size_t tag_len, size_t
    return NULL;
 }
 
+/**
+ * @internal
+ * Clears all the nodes (text and format) of the textblock object.
+ * @param obj The evas object, must not be NULL.
+ */
 static void
 _nodes_clear(const Evas_Object *obj)
 {
    Evas_Object_Textblock *o;
 
    o = (Evas_Object_Textblock *)(obj->object_data);
-   while (o->nodes)
+   while (o->text_nodes)
+     {
+       Evas_Object_Textblock_Node_Text *n;
+
+       n = o->text_nodes;
+       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)
      {
-       Evas_Object_Textblock_Node *n;
+        Evas_Object_Textblock_Node_Format *n;
 
-       n = (Evas_Object_Textblock_Node *)o->nodes;
-       o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n));
-       if (n->text) eina_strbuf_free(n->text);
-       free(n);
+        n = o->format_nodes;
+        o->format_nodes = _NODE_FORMAT(eina_inlist_remove(EINA_INLIST_GET(o->format_nodes), EINA_INLIST_GET(n)));
+        _evas_textblock_node_format_free(n);
      }
 }
 
+/**
+ * @internal
+ * Unrefs and frees (if needed) a textblock format.
+ * @param obj The Evas_Object, Must not be NULL.
+ * @param fmt the format to be cleaned, must not be NULL.
+ */
 static void
-_format_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
+_format_unref_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
 {
    fmt->ref--;
    if (fmt->ref > 0) return;
@@ -310,275 +583,211 @@ _format_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
    free(fmt);
 }
 
+/**
+ * @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)
 {
    while (ln->items)
      {
-       Evas_Object_Textblock_Item *it;
+        Evas_Object_Textblock_Item *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_free(obj, it->format);
-       free(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);
      }
    while (ln->format_items)
      {
-       Evas_Object_Textblock_Format_Item *fi;
+        Evas_Object_Textblock_Format_Item *fi;
 
-       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);
+        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);
      }
    if (ln) free(ln);
 }
 
-static void
-_lines_clear(const Evas_Object *obj, Evas_Object_Textblock_Line *lines)
-{
-   while (lines)
-     {
-       Evas_Object_Textblock_Line *ln;
-
-       ln = (Evas_Object_Textblock_Line *)lines;
-       lines = (Evas_Object_Textblock_Line *)eina_inlist_remove(EINA_INLIST_GET(lines), EINA_INLIST_GET(ln));
-       _line_free(obj, ln);
-     }
-}
-
-static void
-_nodes_adjacent_merge(const Evas_Object *obj, Evas_Object_Textblock_Node *n1)
-{
-   Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n0, *n2;
-   Eina_List *l;
-   Evas_Textblock_Cursor *data;
-   int plen;
-
-   if (n1->type != NODE_TEXT) return;
-   o = (Evas_Object_Textblock *)(obj->object_data);
-   n0 = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n1))->prev;
-   n2 = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n1))->next;
-   if ((n0) && (n0->type == NODE_TEXT))
-     {
-       plen = eina_strbuf_length_get(n0->text);
-       eina_strbuf_append_length(n0->text, eina_strbuf_string_get(n1->text),
-                                 eina_strbuf_length_get(n1->text));
-        o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove
-          (EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n1));
-//     (EINA_INLIST_GET(n0))->next = EINA_INLIST_GET(n2);
-//     if (n2) (EINA_INLIST_GET(n2))->prev = EINA_INLIST_GET(n0);
-       // fix any cursors in n1
-       if (n1 == o->cursor->node)
-         {
-            o->cursor->node = n0;
-            o->cursor->pos += plen;
-         }
-       EINA_LIST_FOREACH(o->cursors, l, data)
-         {
-            if (n1 == data->node)
-              {
-                 data->node = n0;
-                 data->pos += plen;
-              }
-         }
-       if (n1->text) eina_strbuf_free(n1->text);
-       free(n1);
-       n1 = n0;
-        n2 = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n1))->next;
-     }
-   if ((n2) && (n2->type == NODE_TEXT))
-     {
-       n0 = n1;
-       n1 = n2;
-       n2 = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n1))->next;
-       plen = eina_strbuf_length_get(n0->text);
-       eina_strbuf_append_length(n0->text, eina_strbuf_string_get(n1->text),
-                                 eina_strbuf_length_get(n1->text));
-        o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove
-          (EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n1));
-//     (EINA_INLIST_GET(n0))->next = EINA_INLIST_GET(n2);
-//     if (n2) (EINA_INLIST_GET(n2))->prev = EINA_INLIST_GET(n0);
-       // fix any cursors in n1
-       if (n1 == o->cursor->node)
-         {
-            o->cursor->node = n0;
-            o->cursor->pos += plen;
-         }
-       EINA_LIST_FOREACH(o->cursors, l, data)
-         {
-            if (n1 == data->node)
-              {
-                 data->node = n0;
-                 data->pos += plen;
-              }
-         }
-       if (n1->text) eina_strbuf_free(n1->text);
-       free(n1);
-     }
-}
-
 /* table of html escapes (that i can find) this should be ordered with the
  * most common first as it's a linear search to match - no hash for this.
  *
  * these are stored as one large string and one additional array that
  * contains the offsets to the tokens for space efficiency.
  */
+/**
+ * @internal
+ * @var escape_strings[]
+ * This string consists of NULL terminated pairs of strings, the first of
+ * every pair is an escape and the second is the value of the escape.
+ */
 static const char escape_strings[] =
-       /* most common escaped stuff */
-       " \0"          "\x20\0" /* NOTE: this here to avoid escaping to &nbsp */
-       "&nbsp;\0"     "\x20\0" /* NOTE: we allow nsbp's to break as we map early - maybe map to ascii 0x01 and then make the rendering code think 0x01 -> 0x20 */
-       "&quot;\0"     "\x22\0"
-       "&amp;\0"      "\x26\0"
-       "&lt;\0"       "\x3c\0"
-       "&gt;\0"       "\x3e\0"
-       /* all the rest */
-       "&iexcl;\0"    "\xc2\xa1\0"
-       "&cent;\0"     "\xc2\xa2\0"
-       "&pound;\0"    "\xc2\xa3\0"
-       "&curren;\0"   "\xc2\xa4\0"
-       "&yen;\0"      "\xc2\xa5\0"
-       "&brvbar;\0"   "\xc2\xa6\0"
-       "&sect;\0"     "\xc2\xa7\0"
-       "&uml;\0"      "\xc2\xa8\0"
-       "&copy;\0"     "\xc2\xa9\0"
-       "&ordf;\0"     "\xc2\xaa\0"
-       "&laquo;\0"    "\xc2\xab\0"
-       "&not;\0"      "\xc2\xac\0"
-       "&reg;\0"      "\xc2\xae\0"
-       "&macr;\0"     "\xc2\xaf\0"
-       "&deg;\0"      "\xc2\xb0\0"
-       "&plusmn;\0"   "\xc2\xb1\0"
-       "&sup2;\0"     "\xc2\xb2\0"
-       "&sup3;\0"     "\xc2\xb3\0"
-       "&acute;\0"    "\xc2\xb4\0"
-       "&micro;\0"    "\xc2\xb5\0"
-       "&para;\0"     "\xc2\xb6\0"
-       "&middot;\0"   "\xc2\xb7\0"
-       "&cedil;\0"    "\xc2\xb8\0"
-       "&sup1;\0"     "\xc2\xb9\0"
-       "&ordm;\0"     "\xc2\xba\0"
-       "&raquo;\0"    "\xc2\xbb\0"
-       "&frac14;\0"   "\xc2\xbc\0"
-       "&frac12;\0"   "\xc2\xbd\0"
-       "&frac34;\0"   "\xc2\xbe\0"
-       "&iquest;\0"   "\xc2\xbf\0"
-       "&Agrave;\0"   "\xc3\x80\0"
-       "&Aacute;\0"   "\xc3\x81\0"
-       "&Acirc;\0"    "\xc3\x82\0"
-       "&Atilde;\0"   "\xc3\x83\0"
-       "&Auml;\0"     "\xc3\x84\0"
-       "&Aring;\0"    "\xc3\x85\0"
-       "&Aelig;\0"    "\xc3\x86\0"
-       "&Ccedil;\0"   "\xc3\x87\0"
-       "&Egrave;\0"   "\xc3\x88\0"
-       "&Eacute;\0"   "\xc3\x89\0"
-       "&Ecirc;\0"    "\xc3\x8a\0"
-       "&Euml;\0"     "\xc3\x8b\0"
-       "&Igrave;\0"   "\xc3\x8c\0"
-       "&Iacute;\0"   "\xc3\x8d\0"
-       "&Icirc;\0"    "\xc3\x8e\0"
-       "&Iuml;\0"     "\xc3\x8f\0"
-       "&Eth;\0"      "\xc3\x90\0"
-       "&Ntilde;\0"   "\xc3\x91\0"
-       "&Ograve;\0"   "\xc3\x92\0"
-       "&Oacute;\0"   "\xc3\x93\0"
-       "&Ocirc;\0"    "\xc3\x94\0"
-       "&Otilde;\0"   "\xc3\x95\0"
-       "&Ouml;\0"     "\xc3\x96\0"
-       "&times;\0"    "\xc3\x97\0"
-       "&Oslash;\0"   "\xc3\x98\0"
-       "&Ugrave;\0"   "\xc3\x99\0"
-       "&Uacute;\0"   "\xc3\x9a\0"
-       "&Ucirc;\0"    "\xc3\x9b\0"
-       "&Yacute;\0"   "\xc3\x9d\0"
-       "&Thorn;\0"    "\xc3\x9e\0"
-       "&szlig;\0"    "\xc3\x9f\0"
-       "&agrave;\0"   "\xc3\xa0\0"
-       "&aacute;\0"   "\xc3\xa1\0"
-       "&acirc;\0"    "\xc3\xa2\0"
-       "&atilde;\0"   "\xc3\xa3\0"
-       "&auml;\0"     "\xc3\xa4\0"
-       "&aring;\0"    "\xc3\xa5\0"
-       "&aelig;\0"    "\xc3\xa6\0"
-       "&ccedil;\0"   "\xc3\xa7\0"
-       "&egrave;\0"   "\xc3\xa8\0"
-       "&eacute;\0"   "\xc3\xa9\0"
-       "&ecirc;\0"    "\xc3\xaa\0"
-       "&euml;\0"     "\xc3\xab\0"
-       "&igrave;\0"   "\xc3\xac\0"
-       "&iacute;\0"   "\xc3\xad\0"
-       "&icirc;\0"    "\xc3\xae\0"
-       "&iuml;\0"     "\xc3\xaf\0"
-       "&eth;\0"      "\xc3\xb0\0"
-       "&ntilde;\0"   "\xc3\xb1\0"
-       "&ograve;\0"   "\xc3\xb2\0"
-       "&oacute;\0"   "\xc3\xb3\0"
-       "&ocirc;\0"    "\xc3\xb4\0"
-       "&otilde;\0"   "\xc3\xb5\0"
-       "&ouml;\0"     "\xc3\xb6\0"
-       "&divide;\0"   "\xc3\xb7\0"
-       "&oslash;\0"   "\xc3\xb8\0"
-       "&ugrave;\0"   "\xc3\xb9\0"
-       "&uacute;\0"   "\xc3\xba\0"
-       "&ucirc;\0"    "\xc3\xbb\0"
-       "&uuml;\0"     "\xc3\xbc\0"
-       "&yacute;\0"   "\xc3\xbd\0"
-       "&thorn;\0"    "\xc3\xbe\0"
-       "&yuml;\0"     "\xc3\xbf\0"
-       "&alpha;\0"    "\xce\x91\0"
-       "&beta;\0"     "\xce\x92\0"
-       "&gamma;\0"    "\xce\x93\0"
-       "&delta;\0"    "\xce\x94\0"
-       "&epsilon;\0"  "\xce\x95\0"
-       "&zeta;\0"     "\xce\x96\0"
-       "&eta;\0"      "\xce\x97\0"
-       "&theta;\0"    "\xce\x98\0"
-       "&iota;\0"     "\xce\x99\0"
-       "&kappa;\0"    "\xce\x9a\0"
-       "&lambda;\0"   "\xce\x9b\0"
-       "&mu;\0"       "\xce\x9c\0"
-       "&nu;\0"       "\xce\x9d\0"
-       "&xi;\0"       "\xce\x9e\0"
-       "&omicron;\0"  "\xce\x9f\0"
-       "&pi;\0"       "\xce\xa0\0"
-       "&rho;\0"      "\xce\xa1\0"
-       "&sigma;\0"    "\xce\xa3\0"
-       "&tau;\0"      "\xce\xa4\0"
-       "&upsilon;\0"  "\xce\xa5\0"
-       "&phi;\0"      "\xce\xa6\0"
-       "&chi;\0"      "\xce\xa7\0"
-       "&psi;\0"      "\xce\xa8\0"
-       "&omega;\0"    "\xce\xa9\0"
-       "&hellip;\0"   "\xe2\x80\xa6\0"
-       "&euro;\0"     "\xe2\x82\xac\0"
-       "&larr;\0"     "\xe2\x86\x90\0"
-       "&uarr;\0"     "\xe2\x86\x91\0"
-       "&rarr;\0"     "\xe2\x86\x92\0"
-       "&darr;\0"     "\xe2\x86\x93\0"
-       "&harr;\0"     "\xe2\x86\x94\0"
-       "&larr;\0"     "\xe2\x87\x90\0"
-       "&rarr;\0"     "\xe2\x87\x92\0"
-       "&forall;\0"   "\xe2\x88\x80\0"
-       "&exist;\0"    "\xe2\x88\x83\0"
-       "&nabla;\0"    "\xe2\x88\x87\0"
-       "&prod;\0"     "\xe2\x88\x8f\0"
-       "&sum;\0"      "\xe2\x88\x91\0"
-       "&and;\0"      "\xe2\x88\xa7\0"
-       "&or;\0"       "\xe2\x88\xa8\0"
-       "&int;\0"      "\xe2\x88\xab\0"
-       "&ne;\0"       "\xe2\x89\xa0\0"
-       "&equiv;\0"    "\xe2\x89\xa1\0"
-       "&oplus;\0"    "\xe2\x8a\x95\0"
-       "&perp;\0"     "\xe2\x8a\xa5\0"
+/* most common escaped stuff */
+" \0"          "\x20\0" /* NOTE: this here to avoid escaping to &nbsp */
+"&nbsp;\0"     "\x20\0" /* NOTE: we allow nsbp's to break as we map early - maybe map to ascii 0x01 and then make the rendering code think 0x01 -> 0x20 */
+"&quot;\0"     "\x22\0"
+"&amp;\0"      "\x26\0"
+"&lt;\0"       "\x3c\0"
+"&gt;\0"       "\x3e\0"
+/* all the rest */
+"&iexcl;\0"    "\xc2\xa1\0"
+"&cent;\0"     "\xc2\xa2\0"
+"&pound;\0"    "\xc2\xa3\0"
+"&curren;\0"   "\xc2\xa4\0"
+"&yen;\0"      "\xc2\xa5\0"
+"&brvbar;\0"   "\xc2\xa6\0"
+"&sect;\0"     "\xc2\xa7\0"
+"&uml;\0"      "\xc2\xa8\0"
+"&copy;\0"     "\xc2\xa9\0"
+"&ordf;\0"     "\xc2\xaa\0"
+"&laquo;\0"    "\xc2\xab\0"
+"&not;\0"      "\xc2\xac\0"
+"&reg;\0"      "\xc2\xae\0"
+"&macr;\0"     "\xc2\xaf\0"
+"&deg;\0"      "\xc2\xb0\0"
+"&plusmn;\0"   "\xc2\xb1\0"
+"&sup2;\0"     "\xc2\xb2\0"
+"&sup3;\0"     "\xc2\xb3\0"
+"&acute;\0"    "\xc2\xb4\0"
+"&micro;\0"    "\xc2\xb5\0"
+"&para;\0"     "\xc2\xb6\0"
+"&middot;\0"   "\xc2\xb7\0"
+"&cedil;\0"    "\xc2\xb8\0"
+"&sup1;\0"     "\xc2\xb9\0"
+"&ordm;\0"     "\xc2\xba\0"
+"&raquo;\0"    "\xc2\xbb\0"
+"&frac14;\0"   "\xc2\xbc\0"
+"&frac12;\0"   "\xc2\xbd\0"
+"&frac34;\0"   "\xc2\xbe\0"
+"&iquest;\0"   "\xc2\xbf\0"
+"&Agrave;\0"   "\xc3\x80\0"
+"&Aacute;\0"   "\xc3\x81\0"
+"&Acirc;\0"    "\xc3\x82\0"
+"&Atilde;\0"   "\xc3\x83\0"
+"&Auml;\0"     "\xc3\x84\0"
+"&Aring;\0"    "\xc3\x85\0"
+"&Aelig;\0"    "\xc3\x86\0"
+"&Ccedil;\0"   "\xc3\x87\0"
+"&Egrave;\0"   "\xc3\x88\0"
+"&Eacute;\0"   "\xc3\x89\0"
+"&Ecirc;\0"    "\xc3\x8a\0"
+"&Euml;\0"     "\xc3\x8b\0"
+"&Igrave;\0"   "\xc3\x8c\0"
+"&Iacute;\0"   "\xc3\x8d\0"
+"&Icirc;\0"    "\xc3\x8e\0"
+"&Iuml;\0"     "\xc3\x8f\0"
+"&Eth;\0"      "\xc3\x90\0"
+"&Ntilde;\0"   "\xc3\x91\0"
+"&Ograve;\0"   "\xc3\x92\0"
+"&Oacute;\0"   "\xc3\x93\0"
+"&Ocirc;\0"    "\xc3\x94\0"
+"&Otilde;\0"   "\xc3\x95\0"
+"&Ouml;\0"     "\xc3\x96\0"
+"&times;\0"    "\xc3\x97\0"
+"&Oslash;\0"   "\xc3\x98\0"
+"&Ugrave;\0"   "\xc3\x99\0"
+"&Uacute;\0"   "\xc3\x9a\0"
+"&Ucirc;\0"    "\xc3\x9b\0"
+"&Yacute;\0"   "\xc3\x9d\0"
+"&Thorn;\0"    "\xc3\x9e\0"
+"&szlig;\0"    "\xc3\x9f\0"
+"&agrave;\0"   "\xc3\xa0\0"
+"&aacute;\0"   "\xc3\xa1\0"
+"&acirc;\0"    "\xc3\xa2\0"
+"&atilde;\0"   "\xc3\xa3\0"
+"&auml;\0"     "\xc3\xa4\0"
+"&aring;\0"    "\xc3\xa5\0"
+"&aelig;\0"    "\xc3\xa6\0"
+"&ccedil;\0"   "\xc3\xa7\0"
+"&egrave;\0"   "\xc3\xa8\0"
+"&eacute;\0"   "\xc3\xa9\0"
+"&ecirc;\0"    "\xc3\xaa\0"
+"&euml;\0"     "\xc3\xab\0"
+"&igrave;\0"   "\xc3\xac\0"
+"&iacute;\0"   "\xc3\xad\0"
+"&icirc;\0"    "\xc3\xae\0"
+"&iuml;\0"     "\xc3\xaf\0"
+"&eth;\0"      "\xc3\xb0\0"
+"&ntilde;\0"   "\xc3\xb1\0"
+"&ograve;\0"   "\xc3\xb2\0"
+"&oacute;\0"   "\xc3\xb3\0"
+"&ocirc;\0"    "\xc3\xb4\0"
+"&otilde;\0"   "\xc3\xb5\0"
+"&ouml;\0"     "\xc3\xb6\0"
+"&divide;\0"   "\xc3\xb7\0"
+"&oslash;\0"   "\xc3\xb8\0"
+"&ugrave;\0"   "\xc3\xb9\0"
+"&uacute;\0"   "\xc3\xba\0"
+"&ucirc;\0"    "\xc3\xbb\0"
+"&uuml;\0"     "\xc3\xbc\0"
+"&yacute;\0"   "\xc3\xbd\0"
+"&thorn;\0"    "\xc3\xbe\0"
+"&yuml;\0"     "\xc3\xbf\0"
+"&alpha;\0"    "\xce\x91\0"
+"&beta;\0"     "\xce\x92\0"
+"&gamma;\0"    "\xce\x93\0"
+"&delta;\0"    "\xce\x94\0"
+"&epsilon;\0"  "\xce\x95\0"
+"&zeta;\0"     "\xce\x96\0"
+"&eta;\0"      "\xce\x97\0"
+"&theta;\0"    "\xce\x98\0"
+"&iota;\0"     "\xce\x99\0"
+"&kappa;\0"    "\xce\x9a\0"
+"&lambda;\0"   "\xce\x9b\0"
+"&mu;\0"       "\xce\x9c\0"
+"&nu;\0"       "\xce\x9d\0"
+"&xi;\0"       "\xce\x9e\0"
+"&omicron;\0"  "\xce\x9f\0"
+"&pi;\0"       "\xce\xa0\0"
+"&rho;\0"      "\xce\xa1\0"
+"&sigma;\0"    "\xce\xa3\0"
+"&tau;\0"      "\xce\xa4\0"
+"&upsilon;\0"  "\xce\xa5\0"
+"&phi;\0"      "\xce\xa6\0"
+"&chi;\0"      "\xce\xa7\0"
+"&psi;\0"      "\xce\xa8\0"
+"&omega;\0"    "\xce\xa9\0"
+"&hellip;\0"   "\xe2\x80\xa6\0"
+"&euro;\0"     "\xe2\x82\xac\0"
+"&larr;\0"     "\xe2\x86\x90\0"
+"&uarr;\0"     "\xe2\x86\x91\0"
+"&rarr;\0"     "\xe2\x86\x92\0"
+"&darr;\0"     "\xe2\x86\x93\0"
+"&harr;\0"     "\xe2\x86\x94\0"
+"&larr;\0"     "\xe2\x87\x90\0"
+"&rarr;\0"     "\xe2\x87\x92\0"
+"&forall;\0"   "\xe2\x88\x80\0"
+"&exist;\0"    "\xe2\x88\x83\0"
+"&nabla;\0"    "\xe2\x88\x87\0"
+"&prod;\0"     "\xe2\x88\x8f\0"
+"&sum;\0"      "\xe2\x88\x91\0"
+"&and;\0"      "\xe2\x88\xa7\0"
+"&or;\0"       "\xe2\x88\xa8\0"
+"&int;\0"      "\xe2\x88\xab\0"
+"&ne;\0"       "\xe2\x89\xa0\0"
+"&equiv;\0"    "\xe2\x89\xa1\0"
+"&oplus;\0"    "\xe2\x8a\x95\0"
+"&perp;\0"     "\xe2\x8a\xa5\0"
+"&dagger;\0"   "\xe2\x80\xa0\0"
+"&Dagger;\0"   "\xe2\x80\xa1\0"
+"&bull;\0"     "\xe2\x80\xa2\0"
 ;
 
 
-static int
-_is_white(int c)
+/**
+ * @internal
+ * Checks if a char is a whitespace.
+ * @param c the unicode codepoint.
+ * @return EINA_TRUE if the unicode codepoint is a whitespace, EINA_FALSE otherwise.
+ */
+static Eina_Bool
+_is_white(Eina_Unicode c)
 {
    /*
     * unicode list of whitespace chars
@@ -597,30 +806,42 @@ _is_white(int c)
     * 3000 IDEOGRAPHIC SPACE
     */
    if (
-       (c == 0x20) ||
-       ((c >= 0x9) && (c <= 0xd)) ||
-       (c == 0x85) ||
-       (c == 0xa0) ||
-       (c == 0x1680) ||
-       (c == 0x180e) ||
-       ((c >= 0x2000) && (c <= 0x200a)) ||
-       (c == 0x2028) ||
-       (c == 0x2029) ||
-       (c == 0x202f) ||
-       (c == 0x205f) ||
-       (c == 0x3000)
-       )
-     return 1;
-   return 0;
+         (c == 0x20) ||
+         ((c >= 0x9) && (c <= 0xd)) ||
+         (c == 0x85) ||
+         (c == 0xa0) ||
+         (c == 0x1680) ||
+         (c == 0x180e) ||
+         ((c >= 0x2000) && (c <= 0x200a)) ||
+         (c == 0x2028) ||
+         (c == 0x2029) ||
+         (c == 0x202f) ||
+         (c == 0x205f) ||
+         (c == 0x3000)
+      )
+     return EINA_TRUE;
+   return EINA_FALSE;
 }
 
+/**
+ * @internal
+ * Creates a copy of a string without the whitespaces between byte indexes
+ * clean_start and clean_end and frees str.
+ *
+ * FIXME: BROKEN FOR NON-ENGLISH.
+ * @param clean_start The byte index of the location to start cleaning at.
+ * @param clean_end The byte index of the location to end cleaning at.
+ * @param str The string to copy and free.
+ * @return a copy of str cleaned of whitespaces.
+ */
 static char *
 _clean_white(int clean_start, int clean_end, char *str)
 {
    char *p, *p2, *str2 = NULL;
    int white, pwhite, start, ok;
 
-   return str;
+   /*FIXME: fix this function */
+   return strdup(str);
    str2 = malloc(strlen(str) + 2);
    p = str;
    p2 = str2;
@@ -629,79 +850,105 @@ _clean_white(int clean_start, int clean_end, char *str)
    ok = 1;
    while (*p != 0)
      {
-       pwhite = white;
-       if (isspace(*p) || _is_white(*p)) white = 1;
-       else white = 0;
-       if ((pwhite) && (white)) ok = 0;
-       else
-         {
-            if (!clean_start)
-              {
-                 if ((start) && (pwhite) && (!white))
-                   {
-//                    *p2 = ' ';
-//                    p2++;
-                   }
-              }
-            ok = 1;
-            if (!white) start = 0;
-         }
-       if (clean_start)
-         {
-            if ((start) && (ok)) ok = 0;
-         }
-       if (ok)
-         {
-            *p2 = *p;
-            p2++;
-         }
-       p++;
+        pwhite = white;
+        if (_is_white(*p)) white = 1;
+        else white = 0;
+        if ((pwhite) && (white)) ok = 0;
+        else
+          {
+             if (!clean_start)
+               {
+                  if ((start) && (pwhite) && (!white))
+                    {
+                       //                     *p2 = ' ';
+                       //                     p2++;
+                    }
+               }
+             ok = 1;
+             if (!white) start = 0;
+          }
+        if (clean_start)
+          {
+             if ((start) && (ok)) ok = 0;
+          }
+        if (ok)
+          {
+             *p2 = *p;
+             p2++;
+          }
+        p++;
      }
    *p2 = 0;
    if (clean_end)
      {
-       while (p2 > str2)
-         {
-            p2--;
-            if (!(isspace(*p2) || _is_white(*p2))) break;
-            *p2 = 0;
-         }
+        while (p2 > str2)
+          {
+             p2--;
+             if (!(isspace(*p2) || _is_white(*p2))) break;
+             *p2 = 0;
+          }
      }
    free(str);
    return str2;
 }
 
-static void
-_append_text_run(Evas_Object_Textblock *o, char *s, char *p)
+/**
+ * @internal
+ * Appends the text between s and p to the main cursor of the object.
+ *
+ * @param o The textblock to append to.
+ * @param[in] s start of the string
+ * @param[in] p end of the string
+ */
+static void __UNUSED__
+_append_text_run(Evas_Object_Textblock *o, const char *s, const char *p)
 {
    if ((s) && (p > s))
      {
-       char *ts;
+        char *ts;
 
-       ts = alloca(p - s + 1);
-       strncpy(ts, s, p - s);
-       ts[p - s] = 0;
-       ts = _clean_white(0, 0, ts);
-       evas_textblock_cursor_text_append(o->cursor, ts);
+        ts = alloca(p - s + 1);
+        strncpy(ts, s, p - s);
+        ts[p - s] = 0;
+        ts = _clean_white(0, 0, ts);
+        evas_textblock_cursor_text_append(o->cursor, ts);
+        free(ts);
      }
 }
 
+/**
+ * @internal
+ * Prepends the text between s and p to the main cursor of the object.
+ *
+ * @param o The textblock to prepend to.
+ * @param[in] s start of the string
+ * @param[in] p end of the string
+ */
 static void
-_prepend_text_run(Evas_Object_Textblock *o, char *s, char *p)
+_prepend_text_run(Evas_Object_Textblock *o, const char *s, const char *p)
 {
    if ((s) && (p > s))
      {
-       char *ts;
+        char *ts;
 
-       ts = alloca(p - s + 1);
-       strncpy(ts, s, p - s);
-       ts[p - s] = 0;
-       ts = _clean_white(0, 0, ts);
-       evas_textblock_cursor_text_prepend(o->cursor, ts);
+        ts = alloca(p - s + 1);
+        strncpy(ts, s, p - s);
+        ts[p - s] = 0;
+        ts = _clean_white(0, 0, ts);
+        evas_textblock_cursor_text_prepend(o->cursor, ts);
+        free(ts);
      }
 }
 
 
+/**
+ * @internal
+ * Returns the numeric value of HEX chars for example for ch = 'A'
+ * the function will return 10.
+ *
+ * @param ch The HEX char.
+ * @return numeric value of HEX.
+ */
 static int
 _hex_string_get(char ch)
 {
@@ -711,6 +958,21 @@ _hex_string_get(char ch)
    return 0;
 }
 
+/**
+ * @internal
+ * Parses a string of one of the formas:
+ * 1. "#RRGGBB"
+ * 2. "#RRGGBBAA"
+ * 3. "#RGB"
+ * 4. "#RGBA"
+ * To the rgba values.
+ *
+ * @param[in] str The string to parse - NOT NULL.
+ * @param[out] r The Red value - NOT NULL.
+ * @param[out] g The Green value - NOT NULL.
+ * @param[out] b The Blue value - NOT NULL.
+ * @param[out] a The Alpha value - NOT NULL.
+ */
 static void
 _format_color_parse(const char *str, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a)
 {
@@ -721,44 +983,47 @@ _format_color_parse(const char *str, unsigned char *r, unsigned char *g, unsigne
 
    if (slen == 7) /* #RRGGBB */
      {
-       *r = (_hex_string_get(str[1]) << 4) | (_hex_string_get(str[2]));
-       *g = (_hex_string_get(str[3]) << 4) | (_hex_string_get(str[4]));
-       *b = (_hex_string_get(str[5]) << 4) | (_hex_string_get(str[6]));
-       *a = 0xff;
+        *r = (_hex_string_get(str[1]) << 4) | (_hex_string_get(str[2]));
+        *g = (_hex_string_get(str[3]) << 4) | (_hex_string_get(str[4]));
+        *b = (_hex_string_get(str[5]) << 4) | (_hex_string_get(str[6]));
+        *a = 0xff;
      }
    else if (slen == 9) /* #RRGGBBAA */
      {
-       *r = (_hex_string_get(str[1]) << 4) | (_hex_string_get(str[2]));
-       *g = (_hex_string_get(str[3]) << 4) | (_hex_string_get(str[4]));
-       *b = (_hex_string_get(str[5]) << 4) | (_hex_string_get(str[6]));
-       *a = (_hex_string_get(str[7]) << 4) | (_hex_string_get(str[8]));
+        *r = (_hex_string_get(str[1]) << 4) | (_hex_string_get(str[2]));
+        *g = (_hex_string_get(str[3]) << 4) | (_hex_string_get(str[4]));
+        *b = (_hex_string_get(str[5]) << 4) | (_hex_string_get(str[6]));
+        *a = (_hex_string_get(str[7]) << 4) | (_hex_string_get(str[8]));
      }
    else if (slen == 4) /* #RGB */
      {
-       *r = _hex_string_get(str[1]);
-       *r = (*r << 4) | *r;
-       *g = _hex_string_get(str[2]);
-       *g = (*g << 4) | *g;
-       *b = _hex_string_get(str[3]);
-       *b = (*b << 4) | *b;
-       *a = 0xff;
+        *r = _hex_string_get(str[1]);
+        *r = (*r << 4) | *r;
+        *g = _hex_string_get(str[2]);
+        *g = (*g << 4) | *g;
+        *b = _hex_string_get(str[3]);
+        *b = (*b << 4) | *b;
+        *a = 0xff;
      }
    else if (slen == 5) /* #RGBA */
      {
-       *r = _hex_string_get(str[1]);
-       *r = (*r << 4) | *r;
-       *g = _hex_string_get(str[2]);
-       *g = (*g << 4) | *g;
-       *b = _hex_string_get(str[3]);
-       *b = (*b << 4) | *b;
-       *a = _hex_string_get(str[4]);
-       *a = (*a << 4) | *a;
+        *r = _hex_string_get(str[1]);
+        *r = (*r << 4) | *r;
+        *g = _hex_string_get(str[2]);
+        *g = (*g << 4) | *g;
+        *b = _hex_string_get(str[3]);
+        *b = (*b << 4) | *b;
+        *a = _hex_string_get(str[4]);
+        *a = (*a << 4) | *a;
      }
    *r = (*r * *a) / 255;
    *g = (*g * *a) / 255;
    *b = (*b * *a) / 255;
 }
 
+/* The refcount for the formats. */
+static int format_refcount = 0;
+/* Holders for the stringshares */
 static const char *fontstr = NULL;
 static const char *font_fallbacksstr = NULL;
 static const char *font_sizestr = NULL;
@@ -787,45 +1052,59 @@ static const char *linerelsizestr = NULL;
 static const char *linegapstr = NULL;
 static const char *linerelgapstr = NULL;
 static const char *itemstr = NULL;
+static const char *linefillstr = NULL;
 
+/**
+ * @internal
+ * Init the format strings.
+ */
 static void
 _format_command_init(void)
 {
-   if (fontstr) return;
-   fontstr = eina_stringshare_add("font");
-   font_fallbacksstr = eina_stringshare_add("font_fallbacks");
-   font_sizestr = eina_stringshare_add("font_size");
-   font_sourcestr = eina_stringshare_add("font_source");
-   colorstr = eina_stringshare_add("color");
-   underline_colorstr = eina_stringshare_add("underline_color");
-   underline2_colorstr = eina_stringshare_add("underline2_color");
-   outline_colorstr = eina_stringshare_add("outline_color");
-   shadow_colorstr = eina_stringshare_add("shadow_color");
-   glow_colorstr = eina_stringshare_add("glow_color");
-   glow2_colorstr = eina_stringshare_add("glow2_color");
-   backing_colorstr = eina_stringshare_add("backing_color");
-   strikethrough_colorstr = eina_stringshare_add("strikethrough_color");
-   alignstr = eina_stringshare_add("align");
-   valignstr = eina_stringshare_add("valign");
-   wrapstr = eina_stringshare_add("wrap");
-   left_marginstr = eina_stringshare_add("left_margin");
-   right_marginstr = eina_stringshare_add("right_margin");
-   underlinestr = eina_stringshare_add("underline");
-   strikethroughstr = eina_stringshare_add("strikethrough");
-   backingstr = eina_stringshare_add("backing");
-   stylestr = eina_stringshare_add("style");
-   tabstopsstr = eina_stringshare_add("tabstops");
-   linesizestr = eina_stringshare_add("linesize");
-   linerelsizestr = eina_stringshare_add("linerelsize");
-   linegapstr = eina_stringshare_add("linegap");
-   linerelgapstr = eina_stringshare_add("linerelgap");
-   itemstr = eina_stringshare_add("item");
+   if (format_refcount == 0)
+     {
+        fontstr = eina_stringshare_add("font");
+        font_fallbacksstr = eina_stringshare_add("font_fallbacks");
+        font_sizestr = eina_stringshare_add("font_size");
+        font_sourcestr = eina_stringshare_add("font_source");
+        colorstr = eina_stringshare_add("color");
+        underline_colorstr = eina_stringshare_add("underline_color");
+        underline2_colorstr = eina_stringshare_add("underline2_color");
+        outline_colorstr = eina_stringshare_add("outline_color");
+        shadow_colorstr = eina_stringshare_add("shadow_color");
+        glow_colorstr = eina_stringshare_add("glow_color");
+        glow2_colorstr = eina_stringshare_add("glow2_color");
+        backing_colorstr = eina_stringshare_add("backing_color");
+        strikethrough_colorstr = eina_stringshare_add("strikethrough_color");
+        alignstr = eina_stringshare_add("align");
+        valignstr = eina_stringshare_add("valign");
+        wrapstr = eina_stringshare_add("wrap");
+        left_marginstr = eina_stringshare_add("left_margin");
+        right_marginstr = eina_stringshare_add("right_margin");
+        underlinestr = eina_stringshare_add("underline");
+        strikethroughstr = eina_stringshare_add("strikethrough");
+        backingstr = eina_stringshare_add("backing");
+        stylestr = eina_stringshare_add("style");
+        tabstopsstr = eina_stringshare_add("tabstops");
+        linesizestr = eina_stringshare_add("linesize");
+        linerelsizestr = eina_stringshare_add("linerelsize");
+        linegapstr = eina_stringshare_add("linegap");
+        linerelgapstr = eina_stringshare_add("linerelgap");
+        itemstr = eina_stringshare_add("item");
+        linefillstr = eina_stringshare_add("linefill");
+     }
+   format_refcount++;
 }
 
+/**
+ * @internal
+ * Shutdown the format strings.
+ */
 static void
 _format_command_shutdown(void)
 {
-   return;
+   if (--format_refcount > 0) return;
+
    eina_stringshare_del(fontstr);
    eina_stringshare_del(font_fallbacksstr);
    eina_stringshare_del(font_sizestr);
@@ -854,8 +1133,16 @@ _format_command_shutdown(void)
    eina_stringshare_del(linegapstr);
    eina_stringshare_del(linerelgapstr);
    eina_stringshare_del(itemstr);
+   eina_stringshare_del(linefillstr);
 }
 
+/**
+ * @internal
+ * Copies str to dst while removing the \\ char, i.e unescape the escape sequences.
+ *
+ * @param[out] dst the destination string - Should not be NULL.
+ * @param[in] src the source string - Should not be NULL.
+ */
 static void
 _format_clean_param(char *dst, const char *src)
 {
@@ -871,6 +1158,15 @@ _format_clean_param(char *dst, const char *src)
    *ds = 0;
 }
 
+/**
+ * @internal
+ * Parses the cmd and parameter and adds the parsed format to fmt.
+ *
+ * @param obj the evas object - should not be NULL.
+ * @param fmt The format to populate - should not be NULL.
+ * @param[in] cmd the command to proccess, should be stringshared.
+ * @param[in] param the parameter of the command.
+ */
 static void
 _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char *cmd, const char *param)
 {
@@ -882,231 +1178,239 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
    _format_clean_param(tmp_param, param);
    if (cmd == fontstr)
      {
-       if ((!fmt->font.name) ||
-           ((fmt->font.name) && (strcmp(fmt->font.name, tmp_param))))
-         {
-            if (fmt->font.name) eina_stringshare_del(fmt->font.name);
-            fmt->font.name = eina_stringshare_add(tmp_param);
-            new_font = 1;
-         }
+        if ((!fmt->font.name) ||
+              ((fmt->font.name) && (strcmp(fmt->font.name, tmp_param))))
+          {
+             if (fmt->font.name) eina_stringshare_del(fmt->font.name);
+             fmt->font.name = eina_stringshare_add(tmp_param);
+             new_font = 1;
+          }
      }
    else if (cmd == font_fallbacksstr)
      {
-       if ((!fmt->font.fallbacks) ||
-           ((fmt->font.fallbacks) && (strcmp(fmt->font.fallbacks, tmp_param))))
-         {
-            /* policy - when we say "fallbacks" do we prepend and use prior
-             * fallbacks... or should we replace. for now we replace
-             */
-            if (fmt->font.fallbacks) eina_stringshare_del(fmt->font.fallbacks);
-            fmt->font.fallbacks = eina_stringshare_add(tmp_param);
-            new_font = 1;
-         }
+        if ((!fmt->font.fallbacks) ||
+              ((fmt->font.fallbacks) && (strcmp(fmt->font.fallbacks, tmp_param))))
+          {
+             /* policy - when we say "fallbacks" do we prepend and use prior
+              * fallbacks... or should we replace. for now we replace
+              */
+             if (fmt->font.fallbacks) eina_stringshare_del(fmt->font.fallbacks);
+             fmt->font.fallbacks = eina_stringshare_add(tmp_param);
+             new_font = 1;
+          }
      }
    else if (cmd == font_sizestr)
      {
-       int v;
+        int v;
 
-       v = atoi(tmp_param);
-       if (v != fmt->font.size)
-         {
-            fmt->font.size = v;
-            new_font = 1;
-         }
+        v = atoi(tmp_param);
+        if (v != fmt->font.size)
+          {
+             fmt->font.size = v;
+             new_font = 1;
+          }
      }
    else if (cmd == font_sourcestr)
      {
-       if ((!fmt->font.source) ||
-           ((fmt->font.source) && (strcmp(fmt->font.source, tmp_param))))
-         {
-            if (fmt->font.source) eina_stringshare_del(fmt->font.source);
-            fmt->font.source = eina_stringshare_add(tmp_param);
-            new_font = 1;
-         }
+        if ((!fmt->font.source) ||
+              ((fmt->font.source) && (strcmp(fmt->font.source, tmp_param))))
+          {
+             if (fmt->font.source) eina_stringshare_del(fmt->font.source);
+             fmt->font.source = eina_stringshare_add(tmp_param);
+             new_font = 1;
+          }
      }
    else if (cmd == colorstr)
      _format_color_parse(tmp_param,
-                        &(fmt->color.normal.r), &(fmt->color.normal.g),
-                        &(fmt->color.normal.b), &(fmt->color.normal.a));
+           &(fmt->color.normal.r), &(fmt->color.normal.g),
+           &(fmt->color.normal.b), &(fmt->color.normal.a));
    else if (cmd == underline_colorstr)
      _format_color_parse(tmp_param,
-                        &(fmt->color.underline.r), &(fmt->color.underline.g),
-                        &(fmt->color.underline.b), &(fmt->color.underline.a));
+           &(fmt->color.underline.r), &(fmt->color.underline.g),
+           &(fmt->color.underline.b), &(fmt->color.underline.a));
    else if (cmd == underline2_colorstr)
      _format_color_parse(tmp_param,
-                        &(fmt->color.underline2.r), &(fmt->color.underline2.g),
-                        &(fmt->color.underline2.b), &(fmt->color.underline2.a));
+           &(fmt->color.underline2.r), &(fmt->color.underline2.g),
+           &(fmt->color.underline2.b), &(fmt->color.underline2.a));
    else if (cmd == outline_colorstr)
      _format_color_parse(tmp_param,
-                        &(fmt->color.outline.r), &(fmt->color.outline.g),
-                        &(fmt->color.outline.b), &(fmt->color.outline.a));
+           &(fmt->color.outline.r), &(fmt->color.outline.g),
+           &(fmt->color.outline.b), &(fmt->color.outline.a));
    else if (cmd == shadow_colorstr)
      _format_color_parse(tmp_param,
-                        &(fmt->color.shadow.r), &(fmt->color.shadow.g),
-                        &(fmt->color.shadow.b), &(fmt->color.shadow.a));
+           &(fmt->color.shadow.r), &(fmt->color.shadow.g),
+           &(fmt->color.shadow.b), &(fmt->color.shadow.a));
    else if (cmd == glow_colorstr)
      _format_color_parse(tmp_param,
-                        &(fmt->color.glow.r), &(fmt->color.glow.g),
-                        &(fmt->color.glow.b), &(fmt->color.glow.a));
+           &(fmt->color.glow.r), &(fmt->color.glow.g),
+           &(fmt->color.glow.b), &(fmt->color.glow.a));
    else if (cmd == glow2_colorstr)
      _format_color_parse(tmp_param,
-                        &(fmt->color.glow2.r), &(fmt->color.glow2.g),
-                        &(fmt->color.glow2.b), &(fmt->color.glow2.a));
+           &(fmt->color.glow2.r), &(fmt->color.glow2.g),
+           &(fmt->color.glow2.b), &(fmt->color.glow2.a));
    else if (cmd == backing_colorstr)
      _format_color_parse(tmp_param,
-                        &(fmt->color.backing.r), &(fmt->color.backing.g),
-                        &(fmt->color.backing.b), &(fmt->color.backing.a));
+           &(fmt->color.backing.r), &(fmt->color.backing.g),
+           &(fmt->color.backing.b), &(fmt->color.backing.a));
    else if (cmd == strikethrough_colorstr)
      _format_color_parse(tmp_param,
-                        &(fmt->color.strikethrough.r), &(fmt->color.strikethrough.g),
-                        &(fmt->color.strikethrough.b), &(fmt->color.strikethrough.a));
+           &(fmt->color.strikethrough.r), &(fmt->color.strikethrough.g),
+           &(fmt->color.strikethrough.b), &(fmt->color.strikethrough.a));
    else if (cmd == alignstr)
      {
-       if (!strcmp(tmp_param, "middle")) fmt->halign = 0.5;
-       else if (!strcmp(tmp_param, "center")) fmt->halign = 0.5;
-       else if (!strcmp(tmp_param, "left")) fmt->halign = 0.0;
-       else if (!strcmp(tmp_param, "right")) fmt->halign = 1.0;
-       else
-         {
-            char *endptr = NULL;
-            double val = strtod(tmp_param, &endptr);
-            if (endptr)
-              {
-                 while (*endptr && _is_white(*endptr))
-                   endptr++;
-                 if (*endptr == '%')
-                   val /= 100.0;
-              }
-            fmt->halign = val;;
-            if (fmt->halign < 0.0) fmt->halign = 0.0;
-            else if (fmt->halign > 1.0) fmt->halign = 1.0;
-         }
+        if (!strcmp(tmp_param, "auto"))
+          {
+             fmt->halign_auto = EINA_TRUE;
+          }
+        else
+          {
+             if (!strcmp(tmp_param, "middle")) fmt->halign = 0.5;
+             else if (!strcmp(tmp_param, "center")) fmt->halign = 0.5;
+             else if (!strcmp(tmp_param, "left")) fmt->halign = 0.0;
+             else if (!strcmp(tmp_param, "right")) fmt->halign = 1.0;
+             else
+               {
+                  char *endptr = NULL;
+                  double val = strtod(tmp_param, &endptr);
+                  if (endptr)
+                    {
+                       while (*endptr && _is_white(*endptr))
+                         endptr++;
+                       if (*endptr == '%')
+                         val /= 100.0;
+                    }
+                  fmt->halign = val;
+                  if (fmt->halign < 0.0) fmt->halign = 0.0;
+                  else if (fmt->halign > 1.0) fmt->halign = 1.0;
+               }
+             fmt->halign_auto = EINA_FALSE;
+          }
      }
    else if (cmd == valignstr)
      {
         if (!strcmp(tmp_param, "top")) fmt->valign = 0.0;
-       else if (!strcmp(tmp_param, "middle")) fmt->valign = 0.5;
-       else if (!strcmp(tmp_param, "center")) fmt->valign = 0.5;
-       else if (!strcmp(tmp_param, "bottom")) fmt->valign = 1.0;
-       else if (!strcmp(tmp_param, "baseline")) fmt->valign = -1.0;
-       else if (!strcmp(tmp_param, "base")) fmt->valign = -1.0;
-       else
-         {
-            char *endptr = NULL;
-            double val = strtod(tmp_param, &endptr);
-            if (endptr)
-              {
-                 while (*endptr && _is_white(*endptr))
-                   endptr++;
-                 if (*endptr == '%')
-                   val /= 100.0;
-              }
-            fmt->valign = val;
-            if (fmt->valign < 0.0) fmt->valign = 0.0;
-            else if (fmt->valign > 1.0) fmt->valign = 1.0;
-         }
+        else if (!strcmp(tmp_param, "middle")) fmt->valign = 0.5;
+        else if (!strcmp(tmp_param, "center")) fmt->valign = 0.5;
+        else if (!strcmp(tmp_param, "bottom")) fmt->valign = 1.0;
+        else if (!strcmp(tmp_param, "baseline")) fmt->valign = -1.0;
+        else if (!strcmp(tmp_param, "base")) fmt->valign = -1.0;
+        else
+          {
+             char *endptr = NULL;
+             double val = strtod(tmp_param, &endptr);
+             if (endptr)
+               {
+                  while (*endptr && _is_white(*endptr))
+                    endptr++;
+                  if (*endptr == '%')
+                    val /= 100.0;
+               }
+             fmt->valign = val;
+             if (fmt->valign < 0.0) fmt->valign = 0.0;
+             else if (fmt->valign > 1.0) fmt->valign = 1.0;
+          }
      }
    else if (cmd == wrapstr)
      {
-       if (!strcmp(tmp_param, "word"))
-         {
-            fmt->wrap_word = 1;
-            fmt->wrap_char = 0;
-         }
-       else if (!strcmp(tmp_param, "char"))
-         {
-            fmt->wrap_word = 0;
-            fmt->wrap_char = 1;
-         }
-       else
-         {
-            fmt->wrap_word = 0;
-            fmt->wrap_char = 0;
-         }
+        if (!strcmp(tmp_param, "word"))
+          {
+             fmt->wrap_word = 1;
+             fmt->wrap_char = 0;
+          }
+        else if (!strcmp(tmp_param, "char"))
+          {
+             fmt->wrap_word = 0;
+             fmt->wrap_char = 1;
+          }
+        else
+          {
+             fmt->wrap_word = 0;
+             fmt->wrap_char = 0;
+          }
      }
    else if (cmd == left_marginstr)
      {
-       if (!strcmp(tmp_param, "reset"))
-         fmt->margin.l = 0;
-       else
-         {
-            if (tmp_param[0] == '+')
-              fmt->margin.l += atoi(&(tmp_param[1]));
-            else if (tmp_param[0] == '-')
-              fmt->margin.l -= atoi(&(tmp_param[1]));
-            else
-              fmt->margin.l = atoi(tmp_param);
-            if (fmt->margin.l < 0) fmt->margin.l = 0;
-         }
+        if (!strcmp(tmp_param, "reset"))
+          fmt->margin.l = 0;
+        else
+          {
+             if (tmp_param[0] == '+')
+               fmt->margin.l += atoi(&(tmp_param[1]));
+             else if (tmp_param[0] == '-')
+               fmt->margin.l -= atoi(&(tmp_param[1]));
+             else
+               fmt->margin.l = atoi(tmp_param);
+             if (fmt->margin.l < 0) fmt->margin.l = 0;
+          }
      }
    else if (cmd == right_marginstr)
      {
-       if (!strcmp(tmp_param, "reset"))
-         fmt->margin.r = 0;
-       else
-         {
-            if (tmp_param[0] == '+')
-              fmt->margin.r += atoi(&(tmp_param[1]));
-            else if (tmp_param[0] == '-')
-              fmt->margin.r -= atoi(&(tmp_param[1]));
-            else
-              fmt->margin.r = atoi(tmp_param);
-            if (fmt->margin.r < 0) fmt->margin.r = 0;
-         }
+        if (!strcmp(tmp_param, "reset"))
+          fmt->margin.r = 0;
+        else
+          {
+             if (tmp_param[0] == '+')
+               fmt->margin.r += atoi(&(tmp_param[1]));
+             else if (tmp_param[0] == '-')
+               fmt->margin.r -= atoi(&(tmp_param[1]));
+             else
+               fmt->margin.r = atoi(tmp_param);
+             if (fmt->margin.r < 0) fmt->margin.r = 0;
+          }
      }
    else if (cmd == underlinestr)
      {
-       if (!strcmp(tmp_param, "off"))
-         {
-            fmt->underline = 0;
-            fmt->underline2 = 0;
-         }
-       else if ((!strcmp(tmp_param, "on")) ||
-                (!strcmp(tmp_param, "single")))
-         {
-            fmt->underline = 1;
-            fmt->underline2 = 0;
-         }
-       else if (!strcmp(tmp_param, "double"))
-         {
-            fmt->underline = 1;
-            fmt->underline2 = 1;
-         }
+        if (!strcmp(tmp_param, "off"))
+          {
+             fmt->underline = 0;
+             fmt->underline2 = 0;
+          }
+        else if ((!strcmp(tmp_param, "on")) ||
+              (!strcmp(tmp_param, "single")))
+          {
+             fmt->underline = 1;
+             fmt->underline2 = 0;
+          }
+        else if (!strcmp(tmp_param, "double"))
+          {
+             fmt->underline = 1;
+             fmt->underline2 = 1;
+          }
      }
    else if (cmd == strikethroughstr)
      {
-       if (!strcmp(tmp_param, "off"))
-         fmt->strikethrough = 0;
-       else if (!strcmp(tmp_param, "on"))
-         fmt->strikethrough = 1;
+        if (!strcmp(tmp_param, "off"))
+          fmt->strikethrough = 0;
+        else if (!strcmp(tmp_param, "on"))
+          fmt->strikethrough = 1;
      }
    else if (cmd == backingstr)
      {
-       if (!strcmp(tmp_param, "off"))
-         fmt->backing = 0;
-       else if (!strcmp(tmp_param, "on"))
-         fmt->backing = 1;
+        if (!strcmp(tmp_param, "off"))
+          fmt->backing = 0;
+        else if (!strcmp(tmp_param, "on"))
+          fmt->backing = 1;
      }
    else if (cmd == stylestr)
      {
-       if (!strcmp(tmp_param, "off")) fmt->style = EVAS_TEXT_STYLE_PLAIN;
-       else if (!strcmp(tmp_param, "none")) fmt->style = EVAS_TEXT_STYLE_PLAIN;
-       else if (!strcmp(tmp_param, "plain")) fmt->style = EVAS_TEXT_STYLE_PLAIN;
-       else if (!strcmp(tmp_param, "shadow")) fmt->style = EVAS_TEXT_STYLE_SHADOW;
-       else if (!strcmp(tmp_param, "outline")) fmt->style = EVAS_TEXT_STYLE_OUTLINE;
-       else if (!strcmp(tmp_param, "soft_outline")) fmt->style = EVAS_TEXT_STYLE_SOFT_OUTLINE;
-       else if (!strcmp(tmp_param, "outline_shadow")) fmt->style = EVAS_TEXT_STYLE_OUTLINE_SHADOW;
-       else if (!strcmp(tmp_param, "outline_soft_shadow")) fmt->style = EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW;
-       else if (!strcmp(tmp_param, "glow")) fmt->style = EVAS_TEXT_STYLE_GLOW;
-       else if (!strcmp(tmp_param, "far_shadow")) fmt->style = EVAS_TEXT_STYLE_FAR_SHADOW;
-       else if (!strcmp(tmp_param, "soft_shadow")) fmt->style = EVAS_TEXT_STYLE_SOFT_SHADOW;
-       else if (!strcmp(tmp_param, "far_soft_shadow")) fmt->style = EVAS_TEXT_STYLE_FAR_SOFT_SHADOW;
-       else fmt->style = EVAS_TEXT_STYLE_PLAIN;
+        if (!strcmp(tmp_param, "off")) fmt->style = EVAS_TEXT_STYLE_PLAIN;
+        else if (!strcmp(tmp_param, "none")) fmt->style = EVAS_TEXT_STYLE_PLAIN;
+        else if (!strcmp(tmp_param, "plain")) fmt->style = EVAS_TEXT_STYLE_PLAIN;
+        else if (!strcmp(tmp_param, "shadow")) fmt->style = EVAS_TEXT_STYLE_SHADOW;
+        else if (!strcmp(tmp_param, "outline")) fmt->style = EVAS_TEXT_STYLE_OUTLINE;
+        else if (!strcmp(tmp_param, "soft_outline")) fmt->style = EVAS_TEXT_STYLE_SOFT_OUTLINE;
+        else if (!strcmp(tmp_param, "outline_shadow")) fmt->style = EVAS_TEXT_STYLE_OUTLINE_SHADOW;
+        else if (!strcmp(tmp_param, "outline_soft_shadow")) fmt->style = EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW;
+        else if (!strcmp(tmp_param, "glow")) fmt->style = EVAS_TEXT_STYLE_GLOW;
+        else if (!strcmp(tmp_param, "far_shadow")) fmt->style = EVAS_TEXT_STYLE_FAR_SHADOW;
+        else if (!strcmp(tmp_param, "soft_shadow")) fmt->style = EVAS_TEXT_STYLE_SOFT_SHADOW;
+        else if (!strcmp(tmp_param, "far_soft_shadow")) fmt->style = EVAS_TEXT_STYLE_FAR_SOFT_SHADOW;
+        else fmt->style = EVAS_TEXT_STYLE_PLAIN;
      }
    else if (cmd == tabstopsstr)
      {
-       fmt->tabstops = atoi(tmp_param);
-       if (fmt->tabstops < 1) fmt->tabstops = 1;
+        fmt->tabstops = atoi(tmp_param);
+        if (fmt->tabstops < 1) fmt->tabstops = 1;
      }
    else if (cmd == linesizestr)
      {
@@ -1115,18 +1419,18 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
      }
    else if (cmd == linerelsizestr)
      {
-       char *endptr = NULL;
-       double val = strtod(tmp_param, &endptr);
-       if (endptr)
-         {
-            while (*endptr && _is_white(*endptr))
-              endptr++;
-            if (*endptr == '%')
-              {
-                 fmt->linerelsize = val / 100.0;
-                 fmt->linesize = 0;
-                 if (fmt->linerelsize < 0.0) fmt->linerelsize = 0.0;
-              }
+        char *endptr = NULL;
+        double val = strtod(tmp_param, &endptr);
+        if (endptr)
+          {
+             while (*endptr && _is_white(*endptr))
+               endptr++;
+             if (*endptr == '%')
+               {
+                  fmt->linerelsize = val / 100.0;
+                  fmt->linesize = 0;
+                  if (fmt->linerelsize < 0.0) fmt->linerelsize = 0.0;
+               }
           }
      }
    else if (cmd == linegapstr)
@@ -1136,109 +1440,162 @@ _format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char
      }
    else if (cmd == linerelgapstr)
      {
-       char *endptr = NULL;
-       double val = strtod(tmp_param, &endptr);
-       if (endptr)
-         {
-            while (*endptr && _is_white(*endptr))
-              endptr++;
-            if (*endptr == '%')
-              {
-                 fmt->linerelgap = val / 100.0;
-                 fmt->linegap = 0;
-                 if (fmt->linerelgap < 0.0) fmt->linerelgap = 0.0;
-              }
+        char *endptr = NULL;
+        double val = strtod(tmp_param, &endptr);
+        if (endptr)
+          {
+             while (*endptr && _is_white(*endptr))
+               endptr++;
+             if (*endptr == '%')
+               {
+                  fmt->linerelgap = val / 100.0;
+                  fmt->linegap = 0;
+                  if (fmt->linerelgap < 0.0) fmt->linerelgap = 0.0;
+               }
+          }
+     }
+   else if (cmd == itemstr)
+     {
+        // itemstr == replacement object items in textblock - inline imges
+        // for example
+     }
+   else if (cmd == linefillstr)
+     {
+        char *endptr = NULL;
+        double val = strtod(tmp_param, &endptr);
+        if (endptr)
+          {
+             while (*endptr && _is_white(*endptr))
+               endptr++;
+             if (*endptr == '%')
+               {
+                  fmt->linefill = val / 100.0;
+                  if (fmt->linefill < 0.0) fmt->linefill = 0.0;
+               }
           }
      }
 
    if (new_font)
      {
-       void *of;
-       char *buf = NULL;
+        void *of;
+        char *buf = NULL;
 
-       of = fmt->font.font;
-       if ((fmt->font.name) && (fmt->font.fallbacks))
-         {
-            buf = malloc(strlen(fmt->font.name) + 1 + strlen(fmt->font.fallbacks) + 1);
-            strcpy(buf, fmt->font.name);
-            strcat(buf, ",");
-            strcat(buf, fmt->font.fallbacks);
-         }
-       else if (fmt->font.name)
-         buf = strdup(fmt->font.name);
+        of = fmt->font.font;
+        if ((fmt->font.name) && (fmt->font.fallbacks))
+          {
+             buf = malloc(strlen(fmt->font.name) + 1 + strlen(fmt->font.fallbacks) + 1);
+             strcpy(buf, fmt->font.name);
+             strcat(buf, ",");
+             strcat(buf, fmt->font.fallbacks);
+          }
+        else if (fmt->font.name)
+          buf = strdup(fmt->font.name);
 
-       fmt->font.font = evas_font_load(obj->layer->evas,
-                                       buf, fmt->font.source,
-                                       (int)(((double)fmt->font.size) * obj->cur.scale));
-       if (buf) free(buf);
-       if (of) evas_font_free(obj->layer->evas, of);
+        fmt->font.font = evas_font_load(obj->layer->evas,
+              buf, fmt->font.source,
+              (int)(((double)fmt->font.size) * obj->cur.scale));
+        if (buf) free(buf);
+        if (of) evas_font_free(obj->layer->evas, of);
      }
 }
 
-static int
-_format_is_param(char *item)
+/**
+ * @internal
+ * Returns #EINA_TRUE if the item is a format parameter, #EINA_FALSE otherwise.
+ *
+ * @param[in] item the item to check - Not NULL.
+ */
+static Eina_Bool
+_format_is_param(const char *item)
 {
-   if (strchr(item, '=')) return 1;
-   return 0;
+   if (strchr(item, '=')) return EINA_TRUE;
+   return EINA_FALSE;
 }
 
+/**
+ * @internal
+ * Parse the format item and populate key and val with the stringshares that
+ * corrospond to the formats parsed.
+ * It expects item to be of the structure:
+ * "key=val"
+ *
+ * @param[in] item the item to parse - Not NULL.
+ * @param[out] key where to store the key at - Not NULL.
+ * @param[out] val where to store the value at - Not NULL.
+ */
 static void
-_format_param_parse(char *item, const char **key, const char **val)
+_format_param_parse(const char *item, const char **key, const char **val)
 {
-   char *p;
-   const char *k, *v;
+   const char *equal, *end;
 
-   p = strchr(item, '=');
-   *p = '\0';
-   k = eina_stringshare_add(item);
-   *key = k;
-   *p = '=';
-   p++;
-   v = eina_stringshare_add(p);
-   *val = v;
+   equal = strchr(item, '=');
+   *key = eina_stringshare_add_length(item, equal - item);
+   equal++; /* Advance after the '=' */
+   /* Null terminate before the spaces */
+   end = strchr(equal, ' ');
+   if (end)
+     {
+        *val = eina_stringshare_add_length(equal, end - equal);
+     }
+   else
+     {
+        *val = eina_stringshare_add(equal);
+     }
 }
 
-static char *
-_format_parse(char **s)
+/**
+ * @internal
+ * FIXME: comment.
+ */
+static const char *
+_format_parse(const char **s)
 {
-   char *p, *item;
-   char *s1 = NULL, *s2 = NULL;
+   const char *p, *item;
+   const char *s1 = NULL, *s2 = NULL;
 
    p = *s;
    if (*p == 0) return NULL;
    for (;;)
      {
-       if (!s1)
-         {
-            if (*p != ' ') s1 = p;
-            if (*p == 0) break;
-         }
-       else if (!s2)
-         {
-            if ((p > *s) && (p[-1] != '\\'))
-              {
-                 if (*p == ' ') s2 = p;
-              }
-            if (*p == 0) s2 = p;
-         }
-       p++;
-       if (s1 && s2)
-         {
-            item = s1;
+        if (!s1)
+          {
+             if (*p != ' ') s1 = p;
+             if (*p == 0) break;
+          }
+        else if (!s2)
+          {
+             if ((p > *s) && (p[-1] != '\\'))
+               {
+                  if (*p == ' ') s2 = p;
+               }
+             if (*p == 0) s2 = p;
+          }
+        p++;
+        if (s1 && s2)
+          {
+             item = s1;
 
-            *s = s2;
-            return item;
-         }
+             *s = s2;
+             return item;
+          }
      }
    *s = p;
    return NULL;
 }
 
+/**
+ * @internal
+ * Parse the format str and populate fmt with the formats found.
+ *
+ * @param obj The evas object - Not NULL.
+ * @param[out] fmt The format to populate - Not NULL.
+ * @param[in] str the string to parse.- Not NULL.
+ */
 static void
-_format_fill(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, char *str)
+_format_fill(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char *str)
 {
-   char *s;
-   char *item;
+   const char *s;
+   const char *item;
 
    s = str;
 
@@ -1247,27 +1604,32 @@ _format_fill(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, char *str)
 
    while ((item = _format_parse(&s)))
      {
-       char tmp_delim = *s;
-       *s = '\0';
-       if (_format_is_param(item))
-         {
-            const char *key = NULL, *val = NULL;
+        if (_format_is_param(item))
+          {
+             const char *key = NULL, *val = NULL;
 
-            _format_param_parse(item, &key, &val);
-            _format_command(obj, fmt, key, val);
-            eina_stringshare_del(key);
-            eina_stringshare_del(val);
-         }
-       else
-         {
-            /* immediate - not handled here */
-         }
-       *s = tmp_delim;
+             _format_param_parse(item, &key, &val);
+             _format_command(obj, fmt, key, val);
+             eina_stringshare_del(key);
+             eina_stringshare_del(val);
+          }
+        else
+          {
+             /* immediate - not handled here */
+          }
      }
 }
 
+/**
+ * @internal
+ * Duplicate a format and return the duplicate.
+ *
+ * @param obj The evas object - Not NULL.
+ * @param[in] fmt The format to duplicate - Not NULL.
+ * @return the copy of the format.
+ */
 static Evas_Object_Textblock_Format *
-_format_dup(Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
+_format_dup(Evas_Object *obj, const Evas_Object_Textblock_Format *fmt)
 {
    Evas_Object_Textblock_Format *fmt2;
    char *buf = NULL;
@@ -1281,16 +1643,16 @@ _format_dup(Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
 
    if ((fmt2->font.name) && (fmt2->font.fallbacks))
      {
-       buf = malloc(strlen(fmt2->font.name) + 1 + strlen(fmt2->font.fallbacks) + 1);
-       strcpy(buf, fmt2->font.name);
-       strcat(buf, ",");
-       strcat(buf, fmt2->font.fallbacks);
+        buf = malloc(strlen(fmt2->font.name) + 1 + strlen(fmt2->font.fallbacks) + 1);
+        strcpy(buf, fmt2->font.name);
+        strcat(buf, ",");
+        strcat(buf, fmt2->font.fallbacks);
      }
    else if (fmt2->font.name)
      buf = strdup(fmt2->font.name);
    fmt2->font.font = evas_font_load(obj->layer->evas,
-                                   buf, fmt2->font.source,
-                                   (int)(((double)fmt2->font.size) * obj->cur.scale));
+         buf, fmt2->font.source,
+         (int)(((double)fmt2->font.size) * obj->cur.scale));
    if (buf) free(buf);
    return fmt2;
 }
@@ -1298,12 +1660,13 @@ _format_dup(Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
 
 
 
-
-
-
-
-
-
+/**
+ * @internal
+ * @typedef Ctxt
+ *
+ * A pack of information that needed to be passed around in the layout engine,
+ * packed for easier access.
+ */
 typedef struct _Ctxt Ctxt;
 
 struct _Ctxt
@@ -1311,7 +1674,8 @@ struct _Ctxt
    Evas_Object *obj;
    Evas_Object_Textblock *o;
 
-   Evas_Object_Textblock_Line *lines;
+   Evas_Object_Textblock_Paragraph *paragraphs;
+   Evas_Object_Textblock_Paragraph *par;
    Evas_Object_Textblock_Line *ln;
 
    Eina_List *format_stack;
@@ -1325,8 +1689,16 @@ struct _Ctxt
    int underline_extend;
    int have_underline, have_underline2;
    double align;
+   Eina_Bool align_auto;
 };
 
+/**
+ * @internal
+ * Adjust the ascent/descent of the format and context.
+ *
+ * @param c The context to work on - Not NUL.
+ * @param fmt The format to adjust - NOT NULL.
+ */
 static void
 _layout_format_ascent_descent_adjust(Ctxt *c, Evas_Object_Textblock_Format *fmt)
 {
@@ -1334,10 +1706,10 @@ _layout_format_ascent_descent_adjust(Ctxt *c, Evas_Object_Textblock_Format *fmt)
 
    if (fmt->font.font)
      {
-//     ascent = c->ENFN->font_max_ascent_get(c->ENDT, fmt->font.font);
-//     descent = c->ENFN->font_max_descent_get(c->ENDT, fmt->font.font);
+        //     ascent = c->ENFN->font_max_ascent_get(c->ENDT, fmt->font.font);
+        //     descent = c->ENFN->font_max_descent_get(c->ENDT, fmt->font.font);
         ascent = c->ENFN->font_ascent_get(c->ENDT, fmt->font.font);
-       descent = c->ENFN->font_descent_get(c->ENDT, fmt->font.font);
+        descent = c->ENFN->font_descent_get(c->ENDT, fmt->font.font);
         if (fmt->linesize > 0)
           {
              if ((ascent + descent) < fmt->linesize)
@@ -1353,42 +1725,126 @@ _layout_format_ascent_descent_adjust(Ctxt *c, Evas_Object_Textblock_Format *fmt)
           }
         c->maxdescent += fmt->linegap;
         c->maxdescent += ((ascent + descent) * fmt->linerelgap);
-       if (c->maxascent < ascent) c->maxascent = ascent;
-       if (c->maxdescent < descent) c->maxdescent = descent;
+        if (c->maxascent < ascent) c->maxascent = ascent;
+        if (c->maxdescent < descent) c->maxdescent = descent;
+        if (fmt->linefill > 0.0)
+          {
+             int dh;
+
+             dh = c->obj->cur.geometry.h - (c->maxascent + c->maxdescent);
+             if (dh < 0) dh = 0;
+             dh = fmt->linefill * dh;
+             c->maxdescent += dh / 2;
+             c->maxascent += dh - (dh / 2);
+             // FIXME: set flag that says "if heigh changes - reformat"
+          }
      }
 }
 
+/**
+ * @internal
+ * Create a new line using the info from the format and update the format
+ * and context.
+ *
+ * @param c The context to work on - Not NULL.
+ * @param fmt The format to use info from - NOT NULL.
+ */
 static void
 _layout_line_new(Ctxt *c, Evas_Object_Textblock_Format *fmt)
 {
    c->ln = calloc(1, sizeof(Evas_Object_Textblock_Line));
    c->align = fmt->halign;
+   c->align_auto = fmt->halign_auto;
    c->marginl = fmt->margin.l;
    c->marginr = fmt->margin.r;
-   c->lines = (Evas_Object_Textblock_Line *)eina_inlist_append(EINA_INLIST_GET(c->lines), EINA_INLIST_GET(c->ln));
+   c->par->lines = (Evas_Object_Textblock_Line *)eina_inlist_append(EINA_INLIST_GET(c->par->lines), EINA_INLIST_GET(c->ln));
    c->x = 0;
    c->maxascent = c->maxdescent = 0;
    c->ln->line_no = -1;
    _layout_format_ascent_descent_adjust(c, fmt);
 }
 
+/**
+ * @internal
+ * Create a new layout paragraph.
+ *
+ * @param c The context to work on - Not NULL.
+ */
+static void
+_layout_paragraph_new(Ctxt *c)
+{
+   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;
+}
+
+/**
+ * @internal
+ * Free the layout paragraph and all of it's lines.
+ */
+static void
+_paragraph_free(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *par)
+{
+   while (par->lines)
+     {
+        Evas_Object_Textblock_Line *ln;
+
+        ln = (Evas_Object_Textblock_Line *) par->lines;
+        par->lines = (Evas_Object_Textblock_Line *)eina_inlist_remove(EINA_INLIST_GET(par->lines), EINA_INLIST_GET(par->lines));
+        _line_free(obj, ln);
+     }
+   free(par);
+}
+
+/**
+ * @internal
+ * Clear all the paragraphs from the inlist pars.
+ *
+ * @param obj the evas object - Not NULL.
+ * @param pars the paragraphs to clean - Not NULL.
+ */
+static void
+_paragraphs_clear(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *pars)
+{
+   Evas_Object_Textblock *o;
+   o = (Evas_Object_Textblock *)(obj->object_data);
+   while (pars)
+     {
+        Evas_Object_Textblock_Paragraph *par;
+
+        par = (Evas_Object_Textblock_Paragraph *) pars;
+        pars = (Evas_Object_Textblock_Paragraph *)eina_inlist_remove(EINA_INLIST_GET(pars), EINA_INLIST_GET(par));
+        _paragraph_free(obj, par);
+     }
+}
+
+/**
+ * @internal
+ * Push fmt to the format stack, if fmt is NULL, will fush a default item.
+ *
+ * @param c the context to work on - Not NULL.
+ * @param fmt the format to push.
+ * @see _layout_format_pop()
+ */
 static Evas_Object_Textblock_Format *
 _layout_format_push(Ctxt *c, Evas_Object_Textblock_Format *fmt)
 {
    if (fmt)
      {
-       fmt = _format_dup(c->obj, fmt);
-       c->format_stack  = eina_list_prepend(c->format_stack, fmt);
+        fmt = _format_dup(c->obj, fmt);
+        c->format_stack  = eina_list_prepend(c->format_stack, fmt);
      }
    else
      {
-       fmt = calloc(1, sizeof(Evas_Object_Textblock_Format));
-       c->format_stack  = eina_list_prepend(c->format_stack, fmt);
-       fmt->ref = 1;
-       fmt->halign = 0.0;
-       fmt->valign = -1.0;
-       fmt->style = EVAS_TEXT_STYLE_PLAIN;
-       fmt->tabstops = 32;
+        fmt = calloc(1, sizeof(Evas_Object_Textblock_Format));
+        c->format_stack  = eina_list_prepend(c->format_stack, fmt);
+        fmt->ref = 1;
+        fmt->halign = 0.0;
+        fmt->halign_auto = EINA_TRUE;
+        fmt->valign = -1.0;
+        fmt->style = EVAS_TEXT_STYLE_PLAIN;
+        fmt->tabstops = 32;
         fmt->linesize = 0;
         fmt->linerelsize = 0.0;
         fmt->linegap = 0;
@@ -1397,28 +1853,49 @@ _layout_format_push(Ctxt *c, Evas_Object_Textblock_Format *fmt)
    return fmt;
 }
 
+/**
+ * @internal
+ * Pop fmt to the format stack, if there's something in the stack free fmt
+ * and set it to point to the next item instead, else return fmt.
+ *
+ * @param c the context to work on - Not NULL.
+ * @param fmt the format to free.
+ * @return the next format in the stack, or format if there's none.
+ * @see _layout_format_pop()
+ */
 static Evas_Object_Textblock_Format *
 _layout_format_pop(Ctxt *c, Evas_Object_Textblock_Format *fmt)
 {
    if ((c->format_stack) && (c->format_stack->next))
      {
-       _format_free(c->obj, fmt);
-       c->format_stack = eina_list_remove_list(c->format_stack, c->format_stack);
-       fmt = c->format_stack->data;
+        _format_unref_free(c->obj, fmt);
+        c->format_stack = eina_list_remove_list(c->format_stack, c->format_stack);
+        fmt = c->format_stack->data;
      }
    return fmt;
 }
 
+/**
+ * @internal
+ * Parse item and fill fmt with the item.
+ *
+ * @param c the context to work on - Not NULL.
+ * @param fmt the format to fill - not null.
+ */
 static void
-_layout_format_value_handle(Ctxt *c, Evas_Object_Textblock_Format *fmt, char *item)
+_layout_format_value_handle(Ctxt *c, Evas_Object_Textblock_Format *fmt, const char *item)
 {
    const char *key = NULL, *val = NULL;
+   char *tmp;
+   tmp = alloca(strlen(item) + 1);
+   strcpy(tmp, item);
 
-   _format_param_parse(item, &key, &val);
+   _format_param_parse(tmp, &key, &val);
    if ((key) && (val)) _format_command(c->obj, fmt, key, val);
    if (key) eina_stringshare_del(key);
    if (val) eina_stringshare_del(val);
    c->align = fmt->halign;
+   c->align_auto = fmt->halign_auto;
    c->marginl = fmt->margin.l;
    c->marginr = fmt->margin.r;
 }
@@ -1430,6 +1907,42 @@ _layout_format_value_handle(Ctxt *c, Evas_Object_Textblock_Format *fmt, char *it
 #define SIZE_ABS 1
 #define SIZE_REL 2
 
+/**
+ * @internal
+ * Get the current line's alignment from the context.
+ *
+ * @param c the context to work on - Not NULL.
+ */
+static inline double
+_layout_line_align_get(Ctxt *c)
+{
+#ifdef BIDI_SUPPORT
+   if (c->align_auto && c->ln && c->ln->items)
+     {
+        if (c->ln->items->source_node &&
+              EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(
+                 c->ln->items->source_node->bidi_props.direction))
+          {
+             /* Align right*/
+             return 1.0;
+          }
+        else
+          {
+             /* Align left */
+             return 0.0;
+          }
+     }
+#endif
+   return c->align;
+}
+
+/**
+ * @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.
+ */
 static void
 _layout_line_advance(Ctxt *c, Evas_Object_Textblock_Format *fmt)
 {
@@ -1441,62 +1954,62 @@ _layout_line_advance(Ctxt *c, Evas_Object_Textblock_Format *fmt)
      _layout_format_ascent_descent_adjust(c, fmt);
    EINA_INLIST_FOREACH(c->ln->items, it)
      {
-       int endx;
+        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;
+        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;
+        int endx;
 
         if (!fi->formatme) continue;
-       endx = fi->x + fi->w;
-       if (endx > c->ln->w) c->ln->w = endx;
+        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;
+           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;
           }
      }
    c->ln->y = c->y + c->o->style_pad.t;
@@ -1504,223 +2017,290 @@ _layout_line_advance(Ctxt *c, Evas_Object_Textblock_Format *fmt)
    c->ln->baseline = c->maxascent;
    if (c->have_underline2)
      {
-       if (c->maxdescent < 4) c->underline_extend = 4 - c->maxdescent;
+        if (c->maxdescent < 4) c->underline_extend = 4 - c->maxdescent;
      }
    else if (c->have_underline)
      {
-       if (c->maxdescent < 2) c->underline_extend = 2 - c->maxdescent;
+        if (c->maxdescent < 2) c->underline_extend = 2 - c->maxdescent;
      }
    c->ln->line_no = c->line_no;
    c->line_no++;
    c->y += c->maxascent + c->maxdescent;
    if (c->w >= 0)
      {
-       c->ln->x = c->marginl + c->o->style_pad.l +
-         ((c->w - c->ln->w -
-           c->o->style_pad.l - c->o->style_pad.r -
-           c->marginl - c->marginr) * c->align);
-       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;
+        c->ln->x = c->marginl + c->o->style_pad.l +
+           ((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;
      }
    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;
+        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;
      }
    _layout_line_new(c, fmt);
 }
 
+/**
+ * @internal
+ * Create a new 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_Textblock_Item *
-_layout_item_new(Ctxt *c __UNUSED__, Evas_Object_Textblock_Format *fmt, char *str)
+_layout_item_new(Ctxt *c __UNUSED__, Evas_Object_Textblock_Format *fmt, const Eina_Unicode *str)
 {
    Evas_Object_Textblock_Item *it;
 
    it = calloc(1, sizeof(Evas_Object_Textblock_Item));
    it->format = fmt;
    it->format->ref++;
-   it->text = strdup(str);
+   it->text = eina_unicode_strdup(str);
    return it;
 }
 
+/**
+ * @internal
+ * Return the cutoff of the text in the text item.
+ *
+ * @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.
+ */
 static int
 _layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textblock_Item *it)
 {
-
    if (fmt->font.font)
-     return c->ENFN->font_last_up_to_pos(c->ENDT, fmt->font.font, it->text,
-                                            c->w -
-                                            c->o->style_pad.l -
-                                            c->o->style_pad.r -
-                                            c->marginl -
-                                            c->marginr -
-                                            c->x,
-                                            0);
+     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);
    return -1;
 }
 
+/**
+ * @internal
+ * Cut the text in the item up until cut.
+ *
+ * @param c the context to work on - Not NULL.
+ * @param it the item to cut - not null.
+ * @param cut the cut index.
+ */
 static void
 _layout_item_text_cutoff(Ctxt *c __UNUSED__, Evas_Object_Textblock_Item *it, int cut)
 {
-   char *ts;
+   Eina_Unicode *ts;
 
    ts = it->text;
    ts[cut] = 0;
-   it->text = strdup(ts);
+   it->text = eina_unicode_strdup(ts);
    free(ts);
 }
 
+/**
+ * @internal
+ * Return the start of the last word up until start.
+ *
+ * @param str the string to work on.
+ * @param start the start of where to look at.
+ * @return the start of the last word up until start.
+ */
 static int
-_layout_word_start(char *str, int start)
+_layout_word_start(const Eina_Unicode *str, int start)
 {
    int p, tp, chr = 0;
 
    p = start;
-   chr = evas_common_font_utf8_get_next((unsigned char *)(str), &p);
+   chr = GET_NEXT(str, p);
    if (_is_white(chr))
      {
-       tp = p;
-       while (_is_white(chr) && (p >= 0))
-         {
-            tp = p;
-            chr = evas_common_font_utf8_get_next((unsigned char *)(str), &p);
-         }
-       return tp;
+        tp = p;
+        while (_is_white(chr) && (p >= 0))
+          {
+             tp = p;
+             chr = GET_NEXT(str, p);
+          }
+        return tp;
      }
    p = start;
    tp = p;
    while (p > 0)
      {
-       chr = evas_common_font_utf8_get_prev((unsigned char *)(str), &p);
-       if (_is_white(chr)) break;
-       tp = p;
+        chr = GET_PREV(str, p);
+        if (_is_white(chr)) break;
+        tp = p;
      }
    if (p < 0) p = 0;
    if ((p >= 0) && (_is_white(chr)))
-     evas_common_font_utf8_get_next((unsigned char *)(str), &p);
+     {
+        GET_NEXT(str, p);
+     }
    return p;
 }
 
-static int
-_layout_ends_with_space(char *str)
+/**
+ * @internal
+ * Checks if the string ends with whitespace
+ *
+ * @param str the string to work on.
+ * @return #EINA_TRUE if it does, #EINA_FALSE otherwise.
+ */
+static Eina_Bool
+_str_ends_with_whitespace(const Eina_Unicode *str)
 {
    int p, chr;
 
-   p = evas_common_font_utf8_get_last((unsigned char *)(str), strlen(str));
-   if (p < 0) return 0;
-   chr = evas_common_font_utf8_get_next((unsigned char *)(str), &p);
+   p = eina_unicode_strlen(str) - 1;
+   if (p < 0) return EINA_FALSE;
+   chr = GET_NEXT(str, p);
    return _is_white(chr);
 }
 
-static int
+/**
+ * @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 = evas_common_font_utf8_get_last((unsigned char *)(it->text), strlen(it->text));
+   p = eina_unicode_strlen(it->text) - 1;
    tp = p;
    if (p >= 0)
      {
-       chr = evas_common_font_utf8_get_prev((unsigned char *)(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);
-            tw = th = 0;
-            if (it->format->font.font)
-              c->ENFN->font_string_size_get(c->ENDT, it->format->font.font, it->text, &tw, &th);
-            it->w = tw;
-            it->h = th;
-            c->x = it->x + adv;
-            return 1;
-         }
+        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 0;
+   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_free(c->obj, it->format);
+   _format_unref_free(c->obj, it->format);
+#ifdef BIDI_SUPPORT
+   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);
+        it = (Evas_Object_Textblock_Item *)(EINA_INLIST_GET(c->ln->items))->last;
+        return _layout_strip_trailing_whitespace(c, fmt, it);
      }
    return 0;
 }
 
-#if 0
-static char *
-_layout_next_char_jump(Ctxt *c, Evas_Object_Textblock_Item *it, char *str)
-{
-   int index;
-
-   index = 0;
-   evas_common_font_utf8_get_next((unsigned char *)str, &index);
-   if (index >= 0)
-     {
-       str = str + index;
-       _layout_item_text_cutoff(c, it, index);
-     }
-   else
-     str = NULL;
-   return str;
-}
-#endif
-
-static int
-_layout_last_item_ends_in_whitespace(Ctxt *c)
+/**
+ * @internal
+ * checks if the last item ends with a whitespace.
+ *
+ * @param c the context to work with - NOT NULL.
+ *
+ * @return #EINA_TRUE if it stripped, #EINA_FALSE otherwise.
+ */
+static Eina_Bool
+_layout_last_item_ends_with_whitespace(Ctxt *c)
 {
    Evas_Object_Textblock_Item *it;
 
-   if (!c->ln->items) return 1;
+   if (!c->ln->items) return EINA_TRUE;
    it = (Evas_Object_Textblock_Item *)(EINA_INLIST_GET(c->ln->items))->last;
-   return _layout_ends_with_space(it->text);
+   return _str_ends_with_whitespace(it->text);
 }
 
+/**
+ * @internal
+ * returns the index of the words end starting from p
+ *
+ * @param str the str to work on - NOT NULL.
+ * @param p start position - must be within strings range..
+ *
+ * @return the position of the end of the word. -1 on error.
+ */
 static int
-_layout_word_end(char *str, int p)
+_layout_word_end(const Eina_Unicode *str, int p)
 {
    int ch, tp;
 
    tp = p;
-   ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp);
+   ch = GET_NEXT(str, tp);
    while ((!_is_white(ch)) && (tp >= 0) && (ch != 0))
      {
-       p = tp;
-       ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp);
+        p = tp;
+        ch = GET_NEXT(str, tp);
      }
    if (ch == 0) return -1;
    return p;
 }
 
+/**
+ * @internal
+ * returns the index of the start of the next word.
+ *
+ * @param str the str to work on - NOT NULL.
+ * @param p start position - must be within strings range..
+ *
+ * @return the position of the start of the next word. -1 on error.
+ */
 static int
-_layout_word_next(char *str, int p)
+_layout_word_next(Eina_Unicode *str, int p)
 {
    int ch, tp;
 
    tp = p;
-   ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp);
+   ch = GET_NEXT(str, tp);
    while ((!_is_white(ch)) && (tp >= 0) && (ch != 0))
      {
-       p = tp;
-       ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp);
+        p = tp;
+        ch = GET_NEXT(str, tp);
      }
    if (ch == 0) return -1;
    while ((_is_white(ch)) && (tp >= 0) && (ch != 0))
      {
-       p = tp;
-       ch = evas_common_font_utf8_get_next((unsigned char *)str, &tp);
+        p = tp;
+        ch = GET_NEXT(str, tp);
      }
    if (ch == 0) return -1;
    return p;
 }
 
+/**
+ * FIXME: doc
+ */
 static void
 _layout_walk_back_to_item_word_redo(Ctxt *c, Evas_Object_Textblock_Item *it)
 {
@@ -1732,334 +2312,392 @@ _layout_walk_back_to_item_word_redo(Ctxt *c, Evas_Object_Textblock_Item *it)
    /* it is not appended yet */
    EINA_INLIST_REVERSE_FOREACH((EINA_INLIST_GET(c->ln->items)), pit)
      {
-       if (_layout_ends_with_space(pit->text))
-         {
-            break;
-         }
-       index = evas_common_font_utf8_get_last((unsigned char *)(pit->text), strlen(pit->text));
-       index = _layout_word_start(pit->text, index);
-       if (index == 0)
-         remove_items = eina_list_prepend(remove_items, pit);
-       else
-         {
-            new_it = _layout_item_new(c, pit->format, pit->text + index);
-            new_it->source_node = pit->source_node;
-            new_it->source_pos = pit->source_pos + index;
-            _layout_item_text_cutoff(c, pit, index);
-            _layout_strip_trailing_whitespace(c, pit->format, pit);
-            break;
-         }
+        if (_str_ends_with_whitespace(pit->text))
+          {
+             break;
+          }
+        index = eina_unicode_strlen(pit->text) - 1;
+        if (index < 0) index = 0;
+        index = _layout_word_start(pit->text, index);
+        if (index == 0)
+          remove_items = eina_list_prepend(remove_items, pit);
+        else
+          {
+             new_it = _layout_item_new(c, pit->format, pit->text + index);
+             new_it->source_node = pit->source_node;
+             new_it->source_pos = pit->source_pos + index;
+             new_it->bidi_props.start = new_it->source_pos;
+             new_it->bidi_props.props = &new_it->source_node->bidi_props;
+# ifdef BIDI_SUPPORT
+             evas_bidi_shape_string(new_it->text, &new_it->bidi_props,
+                   eina_unicode_strlen(new_it->text));
+# endif
+             _layout_item_text_cutoff(c, pit, index);
+             _layout_strip_trailing_whitespace(c, pit->format, pit);
+             break;
+          }
      }
    EINA_LIST_FOREACH(remove_items, l, data)
-     c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_remove(EINA_INLIST_GET(c->ln->items), data);
+      c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_remove(EINA_INLIST_GET(c->ln->items), data);
    /* new line now */
    if (remove_items)
      {
-       pit = remove_items->data;
-       _layout_line_advance(c, pit->format);
+        pit = remove_items->data;
+        _layout_line_advance(c, pit->format);
      }
    else
      {
-       _layout_line_advance(c, it->format);
+        _layout_line_advance(c, it->format);
      }
    if (new_it)
      {
-       /* append new_it */
-       tw = th = 0;
-       if (new_it->format->font.font)
-         c->ENFN->font_string_size_get(c->ENDT, new_it->format->font.font, new_it->text, &tw, &th);
-       new_it->w = tw;
-       new_it->h = th;
-       inset = 0;
-       if (new_it->format->font.font)
-         inset = c->ENFN->font_inset_get(c->ENDT, new_it->format->font.font, new_it->text);
-       new_it->inset = inset;
-       new_it->x = c->x;
-       adv = 0;
-       if (new_it->format->font.font)
-         adv = c->ENFN->font_h_advance_get(c->ENDT, new_it->format->font.font, new_it->text);
-       c->x += adv;
-       c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(new_it));
+        /* append new_it */
+        tw = th = 0;
+        if (new_it->format->font.font)
+          c->ENFN->font_string_size_get(c->ENDT, new_it->format->font.font, new_it->text, &it->bidi_props, &tw, &th);
+        new_it->w = tw;
+        new_it->h = th;
+        inset = 0;
+        if (new_it->format->font.font)
+          inset = c->ENFN->font_inset_get(c->ENDT, new_it->format->font.font, new_it->text);
+        new_it->inset = inset;
+        new_it->x = c->x;
+        adv = 0;
+        if (new_it->format->font.font)
+          adv = c->ENFN->font_h_advance_get(c->ENDT, new_it->format->font.font, new_it->text, &new_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(new_it));
      }
    while (remove_items)
      {
-       pit = remove_items->data;
-       remove_items = eina_list_remove_list(remove_items, remove_items);
-       /* append pit */
-       pit->x = c->x;
-       adv = c->ENFN->font_h_advance_get(c->ENDT, pit->format->font.font, pit->text);
-       c->x += adv;
-       c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(pit));
+        pit = remove_items->data;
+        remove_items = eina_list_remove_list(remove_items, remove_items);
+        /* append pit */
+        pit->x = c->x;
+        adv = c->ENFN->font_h_advance_get(c->ENDT, pit->format->font.font, pit->text, &pit->bidi_props);
+        c->x += adv;
+        c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(pit));
      }
    if (it)
      {
-       /* append it */
-       it->x = c->x;
-       adv = 0;
-       if (it->format->font.font)
-         adv = c->ENFN->font_h_advance_get(c->ENDT, it->format->font.font, it->text);
-       c->x += adv;
-       c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(it));
+        /* append it */
+        it->x = c->x;
+        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);
+        c->x += adv;
+        c->ln->items = (Evas_Object_Textblock_Item *)eina_inlist_append(EINA_INLIST_GET(c->ln->items), EINA_INLIST_GET(it));
      }
 }
 
+/**
+ * @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.
+ * @param n the text node. - Not null.
+ * @param start the start position. - in range.
+ * @param off the offset - start + offset in range. if offset is -1, it'll add everything to the end of the string if offset = 0 it'll return with doing nothing.
+ * @param repch TBD.
+ */
 static void
-_layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textblock_Node *n, const char *repch)
+_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;
-   char *str;
-   const char *tbase;
+   Eina_Unicode *alloc_str = NULL;
+   const Eina_Unicode *str = EINA_UNICODE_EMPTY_STRING;
+   const Eina_Unicode *tbase;
    Evas_Object_Textblock_Item *it;
 
+   /* FIXME: explain the algorithm. */
+
    if (n)
      {
-        if ((repch) && (eina_strbuf_length_get(n->text)))
+        if ((repch) && (eina_ustrbuf_length_get(n->unicode)))
           {
-             int i, len, chlen;
-             char *ptr;
-             
-             len = evas_common_font_utf8_get_len((unsigned char *) eina_strbuf_string_get(n->text));
-             chlen = strlen(repch);
-             str = alloca((len * chlen) + 1);
+             int i, len, ind;
+             Eina_Unicode *ptr;
+             Eina_Unicode urepch;
+
+             len = eina_ustrbuf_length_get(n->unicode);
+             str = alloca((len + 1) * sizeof(Eina_Unicode));
              tbase = str;
-             for (i = 0, ptr = str; i < len; ptr += chlen, i++)
-               memcpy(ptr, repch, chlen);
+             ind = 0;
+             urepch = evas_common_encoding_utf8_get_next(repch, &ind);
+             for (i = 0, ptr = (Eina_Unicode *)tbase; i < len; ptr++, i++)
+               *ptr = urepch;
              *ptr = 0;
           }
         else
           {
-             str = (char *)eina_strbuf_string_get(n->text);
-             tbase = str;
+             int len;
+             int orig_off = off;
+             len = eina_ustrbuf_length_get(n->unicode);
+             if (off == 0) return;
+             else if (off < 0) off = len - start;
+
+             if (start < 0)
+               {
+                  start = 0;
+               }
+             else if ((start == 0) && (off == 0) && (orig_off == -1))
+               {
+                  /* Special case that means that we need to add an empty
+                   * item */
+                  str = EINA_UNICODE_EMPTY_STRING;
+                  goto skip;
+               }
+             else if ((start >= len) || (off > len))
+               {
+                  return;
+               }
+             str = eina_ustrbuf_string_get(n->unicode);
+             alloc_str = eina_unicode_strdup(str + start);
+
+             if (off > 0)
+               {
+                  alloc_str[off] = 0;
+               }
+             str = alloc_str;
           }
      }
-   else
-     {
-        str = "";
-        tbase = str;
-     }
-//   printf("add: wrap: %i|%i, width: %i '%s'\n", fmt->wrap_word, fmt->wrap_char, c->w, str);
+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;
-/*
-       if (!c->ln->items)
-         {
-            twrap = wrap;
-            ch = evas_common_font_utf8_get_next((unsigned char *)str, &wrap);
-            while (_is_white(ch))
-              {
-                 twrap = wrap;
-                 ch = evas_common_font_utf8_get_next((unsigned char *)str, &wrap);
-              }
-            str = str + twrap;
-         }
- */
-       it = _layout_item_new(c, fmt, str);
-       it->source_node = n;
-       it->source_pos = str - tbase;
-       tw = th = 0;
-       if (fmt->font.font)
-         c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, it->text, &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)))
-         {
-            wrap = _layout_text_cutoff_get(c, fmt, it);
+        /* 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)))
+          {
+             wrap = _layout_text_cutoff_get(c, fmt, it);
              if (wrap == 0)
-               evas_common_font_utf8_get_next((unsigned char *)str, &wrap);
-            if (wrap > 0)
-              {
-                 if (fmt->wrap_word)
-                   {
-                      index = wrap;
-                      ch = evas_common_font_utf8_get_next((unsigned char *)str, &index);
-                      if (!_is_white(ch))
-                        wrap = _layout_word_start(str, wrap);
-                      if (wrap > 0)
-                        {
-                           twrap = wrap;
-                           ch = evas_common_font_utf8_get_prev((unsigned char *)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 = str + twrap;
-                             }
-                           /* intersects a word */
-                           else
-                             {
-                                /* walk back to start of word */
-                                twrap = _layout_word_start(str, wrap);
-                                if (twrap != 0)
-                                  {
-                                     wrap = twrap;
-                                     ch = evas_common_font_utf8_get_prev((unsigned char *)str, &twrap);
-                                     _layout_item_text_cutoff(c, it, twrap);
-                                     str = str + wrap;
-                                  }
-                                else
-                                  {
-                                     empty_item = 1;
-                                     if (it->text) free(it->text);
-                                     _format_free(c->obj, it->format);
-                                     free(it);
+               GET_NEXT(str, 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 = evas_common_font_utf8_get_next((unsigned char *)str, &twrap);
-                                               str = str + twrap;
-                                            }
-                                          else
-                                            str = NULL;
+                                           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 = evas_common_font_utf8_get_next((unsigned char *)str, &index);
-                           if (!_is_white(ch) &&
-                               (!_layout_last_item_ends_in_whitespace(c)))
-                             {
-                                _layout_walk_back_to_item_word_redo(c, it);
-                                return;
-                             }
-                           if (c->ln->items != NULL)
-                             {
-                                white_stripped = _layout_item_abort(c, fmt, it);
-                                empty_item = 1;
-                             }
-                           else
-                             {
-                                if (wrap <= 0)
-                                  {
-                                     wrap = 0;
-                                     twrap = _layout_word_end(it->text, wrap);
-                                     wrap = twrap;
-                                     if (twrap >= 0)
-                                       {
-                                          ch = evas_common_font_utf8_get_next((unsigned char *)str, &wrap);
-                                          _layout_item_text_cutoff(c, it, twrap);
-                                       }
-                                     if (wrap > 0)
-                                       str = str + wrap;
-                                     else
-                                       str = NULL;
-                                  }
-                                else
-                                  str = NULL;
-                             }
-                        }
-                   }
-                 else if (fmt->wrap_char)
-                   {
-                      _layout_item_text_cutoff(c, it, wrap);
-                      str = str + wrap;
-                   }
-                 new_line = 1;
-              }
-            else
-              {
-                 /* wrap now is the index of the word START */
-                 if (wrap <= 0)
-                   {
-                      if (wrap < 0) wrap = 0;
-                      index = wrap;
-                      ch = evas_common_font_utf8_get_next((unsigned char *)str, &index);
-                      if (!_is_white(ch) &&
-                          (!_layout_last_item_ends_in_whitespace(c)))
-                        {
-                           _layout_walk_back_to_item_word_redo(c, it);
-                           return;
-                        }
-                   }
-                 if (c->ln->items != NULL)
-                   {
-                      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 = 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, &tw, &th);
-              }
-         }
-       else
-         str = NULL;
-       if (empty_item) empty_item = 0;
-       else
-         {
-            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);
-            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)
-              {
-                 if (!white_stripped)
-                   {
-                      index = 0;
-                      ch = evas_common_font_utf8_get_next((unsigned char *)str, &index);
-                      if (_is_white(ch)) str += index;
-                   }
-              }
-            new_line = 0;
-            _layout_line_advance(c, fmt);
-         }
+                                   }
+                              }
+                         }
+                       else
+                         {
+                            /* wrap now is the index of the word START */
+                            index = wrap;
+                            ch = GET_NEXT(str, index);
+                            if (!_is_white(ch) &&
+                                  (!_layout_last_item_ends_with_whitespace(c)))
+                              {
+                                 _layout_walk_back_to_item_word_redo(c, it);
+                                 goto end;
+                              }
+                            if (c->ln->items != NULL)
+                              {
+                                 white_stripped = _layout_item_abort(c, fmt, it);
+                                 empty_item = 1;
+                              }
+                            else
+                              {
+                                 if (wrap <= 0)
+                                   {
+                                      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;
+                                   }
+                                 else
+                                   str = NULL;
+                              }
+                         }
+                    }
+                  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)
+                    {
+                       if (wrap < 0) wrap = 0;
+                       index = wrap;
+                       ch = GET_NEXT(str, index);
+                       if (!_is_white(ch) &&
+                             (!_layout_last_item_ends_with_whitespace(c)))
+                         {
+                            _layout_walk_back_to_item_word_redo(c, it);
+                            goto end;
+                         }
+                    }
+                  if (c->ln->items != NULL)
+                    {
+                       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
+          {
+             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)
+               {
+                  if (!white_stripped)
+                    {
+                       index = 0;
+                       ch = GET_NEXT(str, index);
+                       if (_is_white(ch)) str += index;
+                    }
+               }
+             new_line = 0;
+             _layout_line_advance(c, fmt);
+          }
      }
+end:
+   if (alloc_str) free(alloc_str);
 }
 
+/**
+ * @internal
+ * Add a format item from the format node n and the item item.
+ *
+ * @param c the current context- NOT NULL.
+ * @param n the source format node - not null.
+ * @param item the format text - not null.
+ *
+ * @return the new format item.
+ */
 static Evas_Object_Textblock_Format_Item *
-_layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node *n, char *item)
+_layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node_Format *n, const char *item)
 {
    Evas_Object_Textblock_Format_Item *fi;
 
@@ -2067,17 +2705,254 @@ _layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node *n, char *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));
+         EINA_INLIST_GET(fi));
    return fi;
 }
 
+/**
+ * @internal
+ * Returns true if the item is a line spearator, false otherwise
+ * @def _IS_LINE_SEPARATOR(item)
+ */
+#define _IS_LINE_SEPARATOR(item)                                             \
+   (!strcmp(item, "\n") || !strcmp(item, "\\n"))
+/**
+ * @internal
+ * 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 */
+
+/**
+ * @internal
+ * Handles a format by proccessing a format node. It returns the relevant format
+ * through _fmt and updates the padding throught style_pad_*. If needed,
+ * it creates a format item.
+ *
+ * @param obj the evas object - NOT NULL.
+ * @param c the current context- NOT NULL.
+ * @param _fmt the format that holds the result.
+ * @param n the source format node - not null.
+ * @param style_pad_l the pad to update.
+ * @param style_pad_r the pad to update.
+ * @param style_pad_t the pad to update.
+ * @param style_pad_b the pad to update.
+ */
+static void
+_layout_do_format(const Evas_Object *obj, Ctxt *c,
+      Evas_Object_Textblock_Format **_fmt, Evas_Object_Textblock_Node_Format *n,
+      int *style_pad_l, int *style_pad_r, int *style_pad_t, int *style_pad_b)
+{
+   Evas_Object_Textblock_Format *fmt = *_fmt;
+   /* FIXME: comment the algo */
+
+   const char *s;
+   const char *item;
+   int handled = 0;
+
+   s = eina_strbuf_string_get(n->format);
+   if (!strncmp(s, "+ item ", 7))
+     {
+        // one of:
+        //   item size=20x10 href=name
+        //   item relsize=20x10 href=name
+        //   item abssize=20x10 href=name
+        // 
+        // optional arguments:
+        //   vsize=full
+        //   vsize=ascent
+        // 
+        // size == item size (modifies line size) - can be multiplied by
+        //   scale factor
+        // relsize == relative size (height is current font height, width
+        //   modified accordingly keeping aspect)
+        // abssize == absolute size (modifies line size) - never mulitplied by
+        //   scale factor
+        // 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 vsize = 0, size = 0;
+        char *p;
+
+        // don't care
+        //href = strstr(s, " href=");
+        p = strstr(s, " vsize=");
+        if (p)
+          {
+             p += 7;
+             if (!strncmp(p, "full", 4)) vsize = VSIZE_FULL;
+             else if (!strncmp(p, "ascent", 6)) vsize = VSIZE_ASCENT;
+          }
+        p = strstr(s, " size=");
+        if (p)
+          {
+             p += 6;
+             if (sscanf(p, "%ix%i", &w, &h) == 2)
+               {
+                  w = w * obj->cur.scale;
+                  h = h * obj->cur.scale;
+                  size = SIZE;
+               }
+          }
+        else
+          {
+             p = strstr(s, " absize=");
+             if (p)
+               {
+                  p += 8;
+                  if (sscanf(p, "%ix%i", &w, &h) == 2)
+                    {
+                       size = SIZE_ABS;
+                    }
+               }
+             else
+               {
+                  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;
+                         }
+                    }
+               }
+          }
+
+        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->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;
+        handled = 1;
+     }
+   if (!handled)
+     {
+        if (s[0] == '+')
+          {
+             fmt = _layout_format_push(c, fmt);
+             s++;
+          }
+        else if (s[0] == '-')
+          {
+             fmt = _layout_format_pop(c, fmt);
+             s++;
+          }
+        while ((item = _format_parse(&s)))
+          {
+             char *tmp = alloca(s - item + 1);
+             strncpy(tmp, item, s - item);
+             tmp[s - item] = '\0';
+             if (_format_is_param(item))
+               {
+                  _layout_format_value_handle(c, fmt, item);
+               }
+             else
+               {
+                  if (_IS_PARAGRAPH_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);
+                    }
+                  else if ((!strcmp(item, "\t")) || (!strcmp(item, "\\t")))
+                    {
+                       Evas_Object_Textblock_Format_Item *fi;
+                       int x2;
+
+                       x2 = (fmt->tabstops * ((c->x + fmt->tabstops) / fmt->tabstops));
+                       if (x2 >
+                             (c->w - c->o->style_pad.l -
+                              c->o->style_pad.r -
+                              c->marginl - c->marginr))
+                         {
+                            _layout_line_advance(c, fmt);
+                            x2 = (fmt->tabstops * ((c->x + fmt->tabstops) / 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;
+                       c->x = x2;
+                    }
+               }
+          }
+     }
+
+   evas_text_style_pad_get(fmt->style, style_pad_l, style_pad_r, style_pad_t, style_pad_b);
+
+   if (fmt->underline2)
+     c->have_underline2 = 1;
+   else if (fmt->underline)
+     c->have_underline = 1;
+   *_fmt = fmt;
+}
+
+/**
+ * @internal
+ * Create the layout from the nodes.
+ *
+ * @param obj the evas object - NOT NULL.
+ * @param calc_only true if should only calc sizes false if should also create the layout..
+ * @param w the object's w.
+ * @param h the object's h.
+ * @param w_ret the object's calculated w.
+ * @param h_ret the object's calculated h.
+ */
 static void
 _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_ret)
 {
    Evas_Object_Textblock *o;
    Ctxt ctxt, *c;
    Evas_Object_Textblock_Line *ln;
-   Evas_Object_Textblock_Node *n;
+   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;
@@ -2087,7 +2962,7 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_
    c = &ctxt;
    c->obj = (Evas_Object *)obj;
    c->o = o;
-   c->lines = c->ln = NULL;
+   c->paragraphs = c->par = NULL;
    c->format_stack = NULL;
    c->x = c->y = 0;
    c->w = w;
@@ -2100,397 +2975,257 @@ _layout(const Evas_Object *obj, int calc_only, int w, int h, int *w_ret, int *h_
    c->underline_extend = 0;
    c->line_no = 0;
    c->align = 0.0;
+   c->align_auto = EINA_TRUE;
+   c->ln = NULL;
 
-   _format_command_init();
    /* setup default base style */
    if ((c->o->style) && (c->o->style->default_tag))
      {
-       fmt = _layout_format_push(c, NULL);
-       _format_fill(c->obj, fmt, c->o->style->default_tag);
+        fmt = _layout_format_push(c, NULL);
+        _format_fill(c->obj, fmt, c->o->style->default_tag);
      }
    if (!fmt)
      {
-       _format_command_shutdown();
-       if (w_ret) *w_ret = 0;
-       if (h_ret) *h_ret = 0;
-       return;
+        if (w_ret) *w_ret = 0;
+        if (h_ret) *h_ret = 0;
+        return;
      }
    /* run through all text and format nodes generating lines */
-   if (!c->o->nodes)
+   if (!c->o->text_nodes && !c->o->format_nodes)
      {
-        if (!c->ln)
+        /* If there are no nodes and lines, do the inital creation. */
+        if (!c->par && !c->ln)
           {
+             _layout_paragraph_new(c);
              _layout_line_new(c, fmt);
-             _layout_text_append(c, fmt, NULL, NULL);
+             _layout_text_append(c, fmt, NULL, 0, 0, NULL);
              _layout_line_advance(c, fmt);
-//             printf("bl:%i | %ix%i\n", c->ln->baseline, c->ln->w, c->ln->h);
-             /*
-             tw = th = 0;
-             if (fmt->font.font)
-               {
-                  c->ENFN->font_string_size_get(c->ENDT, fmt->font.font, "", &tw, &th);
-                  c->ln->x = 0;
-                  c->ln->y = 0;
-                  c->ln->w = tw;
-                  c->ln->h = th;
-                  c->wmax = tw;
-                  c->hmax = th;
-                  _layout_format_ascent_descent_adjust(c, fmt);
-               }
-              */
           }
      }
-   EINA_INLIST_FOREACH(c->o->nodes, n)
+
+   /* Go through all the text nodes to create the layout from */
+   EINA_INLIST_FOREACH(c->o->text_nodes, n)
      {
-       if (!c->ln) _layout_line_new(c, fmt);
-       if ((n->type == NODE_FORMAT) && eina_strbuf_length_get(n->text))
-         {
-            char *s;
-            char *item;
-             int handled = 0;
+        Evas_Object_Textblock_Node_Format *fnode;
+        size_t start;
+        int off;
 
-            s = (char *)eina_strbuf_string_get(n->text);
-             if (!strncmp(s, "+ item ", 7))
+        /*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))
+          {
+             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))
                {
-                  // one of:
-                  //   item size=20x10 href=name
-                  //   item relsize=20x10 href=name
-                  //   item abssize=20x10 href=name
-                  // 
-                  // optional arguments:
-                  //   vsize=full
-                  //   vsize=ascent
-                  // 
-                  // size == item size (modifies line size) - can be multiplied by
-                  //   scale factor
-                  // relsize == relative size (height is current font height, width
-                  //   modified accordingly keeping aspect)
-                  // abssize == absolute size (modifies line size) - never mulitplied by
-                  //   scale factor
-                  // 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 vsize = 0, size = 0;
-                  char *p;
-                  
-                  // don't care
-                  //href = strstr(s, " href=");
-                  p = strstr(s, " vsize=");
-                  if (p)
-                    {
-                       p += 7;
-                       if (!strncmp(p, "full", 4)) vsize = VSIZE_FULL;
-                       else if (!strncmp(p, "ascent", 6)) vsize = VSIZE_ASCENT;
-                    }
-                  p = strstr(s, " size=");
-                  if (p)
-                    {
-                       p += 6;
-                       if (sscanf(p, "%ix%i", &w, &h) == 2)
-                         {
-                            w = w * obj->cur.scale;
-                            h = h * obj->cur.scale;
-                            size = SIZE;
-                         }
-                    }
-                  else
-                    {
-                       p = strstr(s, " absize=");
-                       if (p)
-                         {
-                            p += 8;
-                            if (sscanf(p, "%ix%i", &w, &h) == 2)
-                              {
-                                 size = SIZE_ABS;
-                              }
-                         }
-                       else
-                         {
-                            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;
-                                   }
-                              }
-                         }
-                    }
-
-                  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, item);
-                  fi->x = c->x;
-                  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;
-                  handled = 1;
+                  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;
                }
-             if (!handled)
+             start += off;
+             if (fnode->visible)
                {
-                  if (s[0] == '+')
-                    {
-                       fmt = _layout_format_push(c, fmt);
-                       s++;
-                    }
-                  else if (s[0] == '-')
-                    {
-                       fmt = _layout_format_pop(c, fmt);
-                       s++;
-                    }
-                  while ((item = _format_parse(&s)))
-                    {
-                       char tmp_delim = *s;
-                       *s = '\0';
-                       if (_format_is_param(item))
-                         {
-                            _layout_format_value_handle(c, fmt, item);
-                         }
-                       else
-                         {
-                            if ((!strcmp(item, "\n")) || (!strcmp(item, "\\n")))
-                              {
-                                 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 ((!strcmp(item, "\t")) || (!strcmp(item, "\\t")))
-                              {
-                                 Evas_Object_Textblock_Format_Item *fi;
-                                 int x2;
-                                 
-                                 x2 = (fmt->tabstops * ((c->x + fmt->tabstops) / fmt->tabstops));
-                                 if (x2 >
-                                     (c->w - c->o->style_pad.l -
-                                      c->o->style_pad.r -
-                                      c->marginl - c->marginr))
-                                   {
-                                      _layout_line_advance(c, fmt);
-                                      x2 = (fmt->tabstops * ((c->x + fmt->tabstops) / 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;
-                                 c->x = x2;
-                              }
-                         }
-                       *s = tmp_delim;
-                    }
+                  off = -1;
+                  start++;
                }
-             
-            evas_text_style_pad_get(fmt->style, &style_pad_l, &style_pad_r, &style_pad_t, &style_pad_b);
-
-            if (fmt->underline2)
-              c->have_underline2 = 1;
-            else if (fmt->underline)
-              c->have_underline = 1;
-         }
-       else if ((n->type == NODE_TEXT) && eina_strbuf_length_get(n->text))
-         {
-            _layout_text_append(c, fmt, n, o->repch);
-            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;
-              }
-         }
+             else
+               {
+                  off = 0;
+               }
+             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) && (fmt))
      _layout_line_advance(c, fmt);
+
+   /* Clean the rest of the format stack */
    while (c->format_stack)
      {
-       fmt = c->format_stack->data;
-       c->format_stack = eina_list_remove_list(c->format_stack, c->format_stack);
-       _format_free(c->obj, fmt);
+        fmt = c->format_stack->data;
+        c->format_stack = eina_list_remove_list(c->format_stack, c->format_stack);
+        _format_unref_free(c->obj, fmt);
      }
-   EINA_INLIST_FOREACH(c->lines, ln)
+   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;
-         }
+        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)
      {
-       ln = removes->data;
-       c->lines = (Evas_Object_Textblock_Line *)eina_inlist_remove(EINA_INLIST_GET(c->lines), EINA_INLIST_GET(ln));
-       removes = eina_list_remove_list(removes, removes);
-       _line_free(obj, ln);
+        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);
      }
 
    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))
+         (o->style_pad.t != style_pad_t) || (o->style_pad.b != style_pad_b))
      {
-       Evas_Object_Textblock_Line *lines;
+        Evas_Object_Textblock_Line *lines;
 
-       lines = c->lines;
-       c->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;
-       _layout(obj, calc_only, w, h, w_ret, h_ret);
-        _lines_clear(obj, lines);
-       _format_command_shutdown();
-       return;
+        lines = c->par->lines;
+        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;
+        _layout(obj, calc_only, w, h, w_ret, h_ret);
+        _paragraphs_clear(obj, c->paragraphs);
+        return;
      }
    if (!calc_only)
      {
-       o->lines = c->lines;
-       _format_command_shutdown();
-       return;
+        o->paragraphs = c->paragraphs;
+        return;
      }
-   if (c->lines) _lines_clear(obj, c->lines);
-   _format_command_shutdown();
+   if (c->paragraphs) _paragraphs_clear(obj, c->paragraphs);
 }
 
+/**
+ * FIXME: doc
+ */
 static void
 _relayout(const Evas_Object *obj)
 {
    Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Line *lines;
+   Evas_Object_Textblock_Paragraph *paragraphs;
 
    o = (Evas_Object_Textblock *)(obj->object_data);
-   lines = o->lines;
-   o->lines = NULL;
+   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);
+         0,
+         obj->cur.geometry.w, obj->cur.geometry.h,
+         &o->formatted.w, &o->formatted.h);
    o->formatted.valid = 1;
-   if (lines) _lines_clear(obj, lines);
+   if (paragraphs) _paragraphs_clear(obj, paragraphs);
    o->last_w = obj->cur.geometry.w;
    o->changed = 0;
    o->redraw = 1;
 }
 
+/**
+ * @internal
+ * Find the layout item and line that match the text node and position passed.
+ *
+ * @param obj the evas object - NOT NULL.
+ * @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.
+ * @see _find_layout_format_item_line_match()
+ */
 static void
-_find_layout_item_line_match(Evas_Object *obj, Evas_Object_Textblock_Node *n, int pos, int eol, Evas_Object_Textblock_Line **lnr, Evas_Object_Textblock_Item **itr)
+_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_Line *ln;
-/*    Evas_Object_Textblock_Node *nn; */
    Evas_Object_Textblock *o;
 
    o = (Evas_Object_Textblock *)(obj->object_data);
-/*    EINA_INLIST_FOREACH(o->nodes, nn) */
-/*      ; */
-   if ((eol) && (n->type == NODE_TEXT))
-     {
-        int pos2 = pos;
-
-        evas_common_font_utf8_get_prev((unsigned char *) eina_strbuf_string_get(n->text), &pos2);
-        if (pos2 < pos) pos = pos2;
-     }
-   EINA_INLIST_FOREACH(o->lines, ln)
+   if (!o->formatted.valid) _relayout(obj);
+   EINA_INLIST_FOREACH(o->paragraphs->lines, ln)
      {
-       Evas_Object_Textblock_Format_Item *fit;
-       Evas_Object_Textblock_Item *it;
+        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)
-         {
-            if (it->source_node == n)
-              {
+        EINA_INLIST_FOREACH(ln->items, it)
+          {
+             if (it->source_node == n)
+               {
                   Evas_Object_Textblock_Item *itn;
                   int p;
 
                   itn = (Evas_Object_Textblock_Item *)(((Eina_Inlist *)it)->next);
-                  p = (int)(it->source_pos + strlen(it->text));
-                 if ((p >= pos) ||
-                      ((p == pos) && (!lnn) &&
-                       ((!itn)  |
-                        ((itn) && (itn->source_node != n)))))
-                   {
-                      *lnr = ln;
-                      *itr = it;
-                      return;
-                   }
-              }
-         }
-       EINA_INLIST_FOREACH(ln->format_items, fit)
-         {
-            if (fit->source_node == n)
-              {
-                 *lnr = ln;
-                 /* FIXME: Is that really what we want ? */
-                 *itr = (Evas_Object_Textblock_Item *)fit;
-                 return;
-              }
-         }
+                  p = (int)(it->source_pos + eina_unicode_strlen(it->text));
+                  if ((p > pos) ||
+                        ((p == pos) && (!lnn) &&
+                         ((!itn) ||
+                          ((itn) && (itn->source_node != n)))))
+                    {
+                       *lnr = ln;
+                       *itr = it;
+                       return;
+                    }
+               }
+          }
      }
 }
 
+/**
+ * @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 *n, Evas_Object_Textblock_Line **lnr, Evas_Object_Textblock_Format_Item **fir)
+_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);
-   EINA_INLIST_FOREACH(o->lines, ln)
+   if (!o->formatted.valid) _relayout(obj);
+   EINA_INLIST_FOREACH(o->paragraphs->lines, ln)
      {
-       Evas_Object_Textblock_Format_Item *fi;
+        Evas_Object_Textblock_Format_Item *fi;
 
-       EINA_INLIST_FOREACH(ln->format_items, fi)
-         {
-            if (fi->source_node == n)
-              {
-                 *lnr = ln;
-                 *fir = fi;
-                 return;
-              }
-         }
+        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.
+ * @param line the line to find
+ * @return the line of line number or NULL if no line found.
+ */
 static Evas_Object_Textblock_Line *
 _find_layout_line_num(const Evas_Object *obj, int line)
 {
@@ -2498,9 +3233,9 @@ _find_layout_line_num(const Evas_Object *obj, int line)
    Evas_Object_Textblock *o;
 
    o = (Evas_Object_Textblock *)(obj->object_data);
-   EINA_INLIST_FOREACH(o->lines, ln)
+   EINA_INLIST_FOREACH(o->paragraphs->lines, ln)
      {
-       if (ln->line_no == line) return ln;
+        if (ln->line_no == line) return ln;
      }
    return NULL;
 }
@@ -2547,17 +3282,19 @@ evas_textblock_style_free(Evas_Textblock_Style *ts)
    if (!ts) return;
    if (ts->objects)
      {
-       ts->delete_me = 1;
-       return;
+        ts->delete_me = 1;
+        return;
      }
    _style_clear(ts);
    free(ts);
 }
 
 /**
- * to be documented.
- * @param ts  to be documented.
- * @param text  to be documented.
+ * Sets the style ts to the style passed as text by text.
+ * Expected a string consisting of many (or none) tag='format' pairs.
+ *
+ * @param ts  the style to set.
+ * @param text the text to parse - NOT NULL.
  * @return Returns no value.
  */
 EAPI void
@@ -2570,15 +3307,15 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
 
    EINA_LIST_FOREACH(ts->objects, l, obj)
      {
-       Evas_Object_Textblock *o;
+        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);
-         }
+        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);
+          }
      }
 
    _style_clear(ts);
@@ -2586,113 +3323,113 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
 
    if (ts->style_text)
      {
-       // format MUST be KEY='VALUE'[KEY='VALUE']...
-       char *p;
-       char *key_start, *key_stop, *val_start, *val_stop;
+        // format MUST be KEY='VALUE'[KEY='VALUE']...
+        char *p;
+        char *key_start, *key_stop, *val_start, *val_stop;
 
-       key_start = key_stop = val_start = val_stop = NULL;
-       p = ts->style_text;
-       while (*p)
-         {
-            if (!key_start)
-              {
-                 if (!isspace(*p))
-                   key_start = p;
-              }
-            else if (!key_stop)
-              {
-                 if ((*p == '=') || (isspace(*p)))
-                   key_stop = p;
-              }
-            else if (!val_start)
-              {
-                 if (((*p) == '\'') && (*(p + 1)))
-                   val_start = p + 1;
-              }
-            else if (!val_stop)
-              {
-                 if (((*p) == '\'') && (p > ts->style_text) && (p[-1] != '\\'))
-                   val_stop = p;
-              }
-            if ((key_start) && (key_stop) && (val_start) && (val_stop))
-              {
-                 char *tags, *replaces;
-                 Evas_Object_Style_Tag *tag;
-                 size_t tag_len = key_stop - key_start;
-                 size_t replace_len = val_stop - val_start;
+        key_start = key_stop = val_start = val_stop = NULL;
+        p = ts->style_text;
+        while (*p)
+          {
+             if (!key_start)
+               {
+                  if (!isspace(*p))
+                    key_start = p;
+               }
+             else if (!key_stop)
+               {
+                  if ((*p == '=') || (isspace(*p)))
+                    key_stop = p;
+               }
+             else if (!val_start)
+               {
+                  if (((*p) == '\'') && (*(p + 1)))
+                    val_start = p + 1;
+               }
+             else if (!val_stop)
+               {
+                  if (((*p) == '\'') && (p > ts->style_text) && (p[-1] != '\\'))
+                    val_stop = p;
+               }
+             if ((key_start) && (key_stop) && (val_start) && (val_stop))
+               {
+                  char *tags, *replaces;
+                  Evas_Object_Style_Tag *tag;
+                  size_t tag_len = key_stop - key_start;
+                  size_t replace_len = val_stop - val_start;
 
-                 tags = malloc(tag_len + 1);
-                 if (tags)
-                   {
-                      memcpy(tags, key_start, tag_len);
-                      tags[tag_len] = 0;
-                   }
+                  tags = malloc(tag_len + 1);
+                  if (tags)
+                    {
+                       memcpy(tags, key_start, tag_len);
+                       tags[tag_len] = 0;
+                    }
 
-                 replaces = malloc(replace_len + 1);
-                 if (replaces)
-                   {
-                      memcpy(replaces, val_start, replace_len);
-                      replaces[replace_len] = 0;
-                   }
-                 if ((tags) && (replaces))
-                   {
-                      if (!strcmp(tags, "DEFAULT"))
-                        {
-                           ts->default_tag = replaces;
-                           free(tags);
-                        }
-                      else
-                        {
-                           tag = calloc(1, sizeof(Evas_Object_Style_Tag));
-                           if (tag)
-                             {
-                                tag->tag = tags;
-                                tag->replace = replaces;
-                                tag->tag_len = tag_len;
-                                tag->replace_len = replace_len;
-                                ts->tags = (Evas_Object_Style_Tag *)eina_inlist_append(EINA_INLIST_GET(ts->tags), EINA_INLIST_GET(tag));
-                             }
-                           else
-                             {
-                                free(tags);
-                                free(replaces);
-                             }
-                        }
-                   }
-                 else
-                   {
-                      if (tags) free(tags);
-                      if (replaces) free(replaces);
-                   }
-                 key_start = key_stop = val_start = val_stop = NULL;
-              }
-            p++;
-         }
+                  replaces = malloc(replace_len + 1);
+                  if (replaces)
+                    {
+                       memcpy(replaces, val_start, replace_len);
+                       replaces[replace_len] = 0;
+                    }
+                  if ((tags) && (replaces))
+                    {
+                       if (!strcmp(tags, "DEFAULT"))
+                         {
+                            ts->default_tag = replaces;
+                            free(tags);
+                         }
+                       else
+                         {
+                            tag = calloc(1, sizeof(Evas_Object_Style_Tag));
+                            if (tag)
+                              {
+                                 tag->tag = tags;
+                                 tag->replace = replaces;
+                                 tag->tag_len = tag_len;
+                                 tag->replace_len = replace_len;
+                                 ts->tags = (Evas_Object_Style_Tag *)eina_inlist_append(EINA_INLIST_GET(ts->tags), EINA_INLIST_GET(tag));
+                              }
+                            else
+                              {
+                                 free(tags);
+                                 free(replaces);
+                              }
+                         }
+                    }
+                  else
+                    {
+                       if (tags) free(tags);
+                       if (replaces) free(replaces);
+                    }
+                  key_start = key_stop = val_start = val_stop = NULL;
+               }
+             p++;
+          }
      }
 
    EINA_LIST_FOREACH(ts->objects, l, obj)
      {
-       Evas_Object_Textblock *o;
+        Evas_Object_Textblock *o;
 
-       o = (Evas_Object_Textblock *)(obj->object_data);
-       if (o->markup_text)
-         {
-            char *m;
+        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);
-              }
-         }
+             m = strdup(o->markup_text);
+             if (m)
+               {
+                  evas_object_textblock_text_markup_set(obj, m);
+                  free(m);
+               }
+          }
      }
 }
 
 /**
- * to be documented.
- * @param ts  to be documented.
- * @return to be documented.
+ * Return the text of the style ts.
+ * @param ts  the style to get it's text.
+ * @return the text of the style or null on error.
  */
 EAPI const char *
 evas_textblock_style_get(const Evas_Textblock_Style *ts)
@@ -2703,9 +3440,9 @@ evas_textblock_style_get(const Evas_Textblock_Style *ts)
 
 /* textblock styles */
 /**
- * to be documented.
- * @param obj to be documented.
- * @param ts  to be documented.
+ * Set the objects style to ts.
+ * @param obj the evas object to set the style to.
+ * @param ts  the style to set.
  * @return Returns no value.
  */
 EAPI void
@@ -2725,38 +3462,30 @@ evas_object_textblock_style_set(Evas_Object *obj, Evas_Textblock_Style *ts)
      }
    if (o->style)
      {
-       Evas_Textblock_Style *old_ts;
+        Evas_Textblock_Style *old_ts;
 
-       old_ts = o->style;
-       old_ts->objects = eina_list_remove(old_ts->objects, obj);
-       if ((old_ts->delete_me) && (!old_ts->objects))
-         evas_textblock_style_free(old_ts);
+        old_ts = o->style;
+        old_ts->objects = eina_list_remove(old_ts->objects, obj);
+        if ((old_ts->delete_me) && (!old_ts->objects))
+          evas_textblock_style_free(old_ts);
      }
    if (ts)
      {
-       ts->objects = eina_list_append(ts->objects, obj);
-       o->style = ts;
+        ts->objects = eina_list_append(ts->objects, obj);
+        o->style = ts;
      }
    else
      {
-       o->style = NULL;
+        o->style = NULL;
      }
 
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   if (o->markup_text)
-     {
-       free(o->markup_text);
-       o->markup_text = NULL;
-     }
-   evas_object_change(obj);
+    _evas_textblock_changed(o, obj);
 }
 
 /**
- * to be documented.
- * @param obj  to be documented.
- * @return to be documented.
+ * Return the style of an object.
+ * @param obj  the object to get the style from.
+ * @return the style of the object.
  */
 EAPI const Evas_Textblock_Style *
 evas_object_textblock_style_get(const Evas_Object *obj)
@@ -2778,15 +3507,7 @@ 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;
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   if (o->markup_text)
-     {
-       free(o->markup_text);
-       o->markup_text = NULL;
-     }
-   evas_object_change(obj);
+    _evas_textblock_changed(o, obj);
 }
 
 /**
@@ -2803,33 +3524,52 @@ evas_object_textblock_replace_char_get(Evas_Object *obj)
    return o->repch;
 }
 
-
+/**
+ * @internal
+ * Advance p_buff to point after the end of the string. It's used with the
+ * @ref escaped_strings[] variable.
+ *
+ * @param p_buff the pointer to the current string.
+ */
 static inline void
-_advance_after_end_of_string(const char **p_buf)
+_escaped_advance_after_end_of_string(const char **p_buf)
 {
    while (**p_buf != 0) (*p_buf)++;
    (*p_buf)++;
 }
 
+/**
+ * @internal
+ * Advance p_buff to point after the end of the string. It's used with the
+ * @ref escaped_strings[] variable. Also chec if matches.
+ * FIXME: doc.
+ *
+ * @param p_buff the pointer to the current string.
+ */
 static inline int
-_is_eq_and_advance(const char *s, const char *s_end,
-                  const char **p_m, const char *m_end)
+_escaped_is_eq_and_advance(const char *s, const char *s_end,
+      const char **p_m, const char *m_end)
 {
    for (;((s < s_end) && (*p_m < m_end)); s++, (*p_m)++)
      {
-       if (*s != **p_m)
-         {
-            _advance_after_end_of_string(p_m);
-            return 0;
-         }
+        if (*s != **p_m)
+          {
+             _escaped_advance_after_end_of_string(p_m);
+             return 0;
+          }
      }
 
    if (*p_m < m_end)
-     _advance_after_end_of_string(p_m);
+     _escaped_advance_after_end_of_string(p_m);
 
    return s == s_end;
 }
 
+/**
+ * @internal
+ *
+ * @param s the string to match
+ */
 static inline const char *
 _escaped_char_match(const char *s, int *adv)
 {
@@ -2840,33 +3580,39 @@ _escaped_char_match(const char *s, int *adv)
 
    while (map_itr < map_end)
      {
-       const char *escape;
-       int match;
+        const char *escape;
+        int match;
 
-       escape = map_itr;
-       _advance_after_end_of_string(&map_itr);
-       if (map_itr >= map_end) break;
+        escape = map_itr;
+        _escaped_advance_after_end_of_string(&map_itr);
+        if (map_itr >= map_end) break;
 
-       mc = map_itr;
-       sc = s;
-       match = 1;
-       while ((*mc) && (*sc))
-         {
-            if ((unsigned char)*sc < (unsigned char)*mc) return NULL;
-            if (*sc != *mc) match = 0;
-            mc++;
-            sc++;
-         }
-       if (match)
-         {
-            *adv = mc - map_itr;
-            return escape;
-         }
-       _advance_after_end_of_string(&map_itr);
+        mc = map_itr;
+        sc = s;
+        match = 1;
+        while ((*mc) && (*sc))
+          {
+             if ((unsigned char)*sc < (unsigned char)*mc) return NULL;
+             if (*sc != *mc) match = 0;
+             mc++;
+             sc++;
+          }
+        if (match)
+          {
+             *adv = mc - map_itr;
+             return escape;
+          }
+        _escaped_advance_after_end_of_string(&map_itr);
      }
    return NULL;
 }
 
+/**
+ * @internal
+ * FIXME: TBD.
+ *
+ * @param s the string to match
+ */
 static inline const char *
 _escaped_char_get(const char *s, const char *s_end)
 {
@@ -2877,18 +3623,18 @@ _escaped_char_get(const char *s, const char *s_end)
 
    while (map_itr < map_end)
      {
-       if (_is_eq_and_advance(s, s_end, &map_itr, map_end))
-         return map_itr;
-       if (map_itr < map_end)
-         _advance_after_end_of_string(&map_itr);
+        if (_escaped_is_eq_and_advance(s, s_end, &map_itr, map_end))
+          return map_itr;
+        if (map_itr < map_end)
+          _escaped_advance_after_end_of_string(&map_itr);
      }
    return NULL;
 }
 
 /**
- * to be documented.
- * @param escape to be documented.
- * @return to be documented.
+ * Returns the unescaped version of escape.
+ * @param escape the string to be escaped
+ * @return the unescaped version of escape
  */
 EAPI const char *
 evas_textblock_escape_string_get(const char *escape)
@@ -2898,10 +3644,11 @@ evas_textblock_escape_string_get(const char *escape)
 }
 
 /**
- * to be documented.
- * @param escape_start to be documented.
- * @param escape_end to be documented.
- * @return to be documented.
+ * Return the unescaped version of the string between start and end.
+ *
+ * @param escape_start the start of the string.
+ * @param escape_end the end of the string.
+ * @return the unescaped version of the range
  */
 EAPI const char *
 evas_textblock_escape_string_range_get(const char *escape_start, const char *escape_end)
@@ -2910,10 +3657,10 @@ evas_textblock_escape_string_range_get(const char *escape_start, const char *esc
 }
 
 /**
- * to be documented.
- * @param string to be documented.
- * @param len_ret to be documented.
- * @return to be documented.
+ * Returns the escaped version of the string.
+ * @param string to escape
+ * @param len_ret the len of the new escape
+ * @return the escaped string.
  */
 EAPI const char *
 evas_textblock_string_escape_get(const char *string, int *len_ret)
@@ -2922,9 +3669,17 @@ evas_textblock_string_escape_get(const char *string, int *len_ret)
    return _escaped_char_match(string, len_ret);
 }
 
+/**
+ * @internal
+ * Appends the escaped char beteewn s and s_end to the curosr
+ *
+ *
+ * @param s the start of the string
+ * @param s_end the end of the string.
+ */
 static inline void
 _append_escaped_char(Evas_Textblock_Cursor *cur, const char *s,
-                    const char *s_end)
+      const char *s_end)
 {
    const char *escape;
 
@@ -2933,9 +3688,17 @@ _append_escaped_char(Evas_Textblock_Cursor *cur, const char *s,
      evas_textblock_cursor_text_append(cur, escape);
 }
 
+/**
+ * @internal
+ * prepends the escaped char beteewn s and s_end to the curosr
+ *
+ *
+ * @param s the start of the string
+ * @param s_end the end of the string.
+ */
 static inline void
 _prepend_escaped_char(Evas_Textblock_Cursor *cur, const char *s,
-                    const char *s_end)
+      const char *s_end)
 {
    const char *escape;
 
@@ -2944,10 +3707,14 @@ _prepend_escaped_char(Evas_Textblock_Cursor *cur, const char *s,
      evas_textblock_cursor_text_prepend(cur, escape);
 }
 
+
 /**
- * to be documented.
- * @param obj  to be documented.
- * @param text to be documented.
+ * Sets the tetxblock's text to the markup text.
+ *
+ * @note assumes text does not include the unicode object replacement char (0xFFFC)
+ *
+ * @param obj  the textblock object.
+ * @param text the markup text to use.
  * @return Return no value.
  */
 EAPI void
@@ -2956,349 +3723,590 @@ evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text)
    TB_HEAD();
    if ((text != o->markup_text) && (o->markup_text))
      {
-       free(o->markup_text);
-       o->markup_text = NULL;
+        free(o->markup_text);
+        o->markup_text = NULL;
      }
    _nodes_clear(obj);
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   evas_object_change(obj);
    if (!o->style)
      {
-       if (text != o->markup_text)
-         {
-            if (text) o->markup_text = strdup(text);
-         }
-       return;
+        if (text != o->markup_text)
+          {
+             if (text) o->markup_text = strdup(text);
+          }
+        return;
      }
-   evas_textblock_cursor_node_first(o->cursor);
-   if (text)
-     {
-       char *s, *p;
-       char *tag_start, *tag_end, *esc_start, *esc_end;
+   evas_textblock_cursor_paragraph_first(o->cursor);
 
-       tag_start = tag_end = esc_start = esc_end = NULL;
-       p = (char *)text;
-       s = p;
-       for (;;)
-         {
-            if ((*p == 0) ||
-                (tag_end) || (esc_end) ||
-                (tag_start) || (esc_start))
-              {
-                 if (tag_end)
-                   {
-                      char *ttag;
-                      size_t ttag_len = tag_end - tag_start -1;
-
-                      ttag = malloc(ttag_len + 1);
-                      if (ttag)
-                        {
-                           const char *match;
-                           size_t replace_len;
-
-                           memcpy(ttag, tag_start + 1, ttag_len);
-                           ttag[ttag_len] = 0;
-                           match = _style_match_tag(o->style, ttag, ttag_len, &replace_len);
-                           if (match)
-                             evas_textblock_cursor_format_append(o->cursor, match);
-                           else
-                             {
-                                char *ttag2;
-
-                                ttag2 = malloc(ttag_len + 2 + 1);
-                                if (ttag2)
-                                  {
-                                     if (ttag[0] == '/')
-                                       {
-                                          strcpy(ttag2, "- ");
-                                          strcat(ttag2, ttag + 1);
-                                       }
-                                     else
-                                       {
-                                          strcpy(ttag2, "+ ");
-                                          strcat(ttag2, ttag);
-                                       }
-                                     evas_textblock_cursor_format_append(o->cursor, ttag2);
-                                     free(ttag2);
-                                  }
-                             }
-                           free(ttag);
-                        }
-                      tag_start = tag_end = NULL;
-                   }
-                 else if (esc_end)
-                   {
-                      _append_escaped_char(o->cursor, esc_start, esc_end);
-                      esc_start = esc_end = NULL;
-                   }
-                 else if (*p == 0)
-                   {
-                      _append_text_run(o, s, p);
-                      s = NULL;
-                   }
-                 if (*p == 0)
-                   break;
-              }
-            if (*p == '<')
-              {
-                 if (!esc_start)
-                   {
-                      tag_start = p;
-                      tag_end = NULL;
-                      _append_text_run(o, s, p);
-                      s = NULL;
-                   }
-              }
-            else if (*p == '>')
-              {
-                 if (tag_start)
-                   {
-                      tag_end = p;
-                      s = p + 1;
-                   }
-              }
-            else if (*p == '&')
-              {
-                 if (!tag_start)
-                   {
-                      esc_start = p;
-                      esc_end = NULL;
-                      _append_text_run(o, s, p);
-                      s = NULL;
-                   }
-              }
-            else if (*p == ';')
-              {
-                 if (esc_start)
-                   {
-                      esc_end = p;
-                      s = p + 1;
-                   }
-              }
-            p++;
-         }
-     }
+   evas_object_textblock_text_markup_prepend(o->cursor, text);
+   /* Point all the cursors to the starrt */
      {
-       Eina_List *l;
-       Evas_Textblock_Cursor *data;
+        Eina_List *l;
+        Evas_Textblock_Cursor *data;
 
-       evas_textblock_cursor_node_first(o->cursor);
-       EINA_LIST_FOREACH(o->cursors, l, data)
-         evas_textblock_cursor_node_first(data);
+        evas_textblock_cursor_paragraph_first(o->cursor);
+        EINA_LIST_FOREACH(o->cursors, l, data)
+           evas_textblock_cursor_paragraph_first(data);
      }
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
- * @param text to be documented.
+ * Prepends markup to the cursor cur.
+ *
+ * @note assumes text does not include the unicode object replacement char (0xFFFC)
+ *
+ * @param cur  the cursor to prepend to.
+ * @param text the markup text to prepend.
  * @return Return no value.
  */
 EAPI void
 evas_object_textblock_text_markup_prepend(Evas_Textblock_Cursor *cur, const char *text)
 {
-   Evas_Object_Textblock *o;
-
-   if (!cur) return;
-   o = (Evas_Object_Textblock *)(cur->obj->object_data);
-   if (o->markup_text)
-     {
-       free(o->markup_text);
-       o->markup_text = NULL;
-     }
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   evas_object_change(cur->obj);
-   if (!o->style) return;
+   Evas_Object *obj = cur->obj;
+   TB_HEAD();
    if (text)
      {
-       char *s, *p;
-       char *tag_start, *tag_end, *esc_start, *esc_end;
+        char *s, *p;
+        char *tag_start, *tag_end, *esc_start, *esc_end;
+
+        tag_start = tag_end = esc_start = esc_end = NULL;
+        p = (char *)text;
+        s = p;
+        /* This loop goes through all of the mark up text until it finds format
+         * tags, escape sequences or the terminating NULL. When it finds either
+         * of those, it appends the text found up until that point to the textblock
+         * proccesses whatever found. It repeats itself until the termainating
+         * NULL is reached. */
+        for (;;)
+          {
+             /* If we got to the end of string or just finished/started tag
+              * or escape sequence handling. */
+             if ((*p == 0) ||
+                   (tag_end) || (esc_end) ||
+                   (tag_start) || (esc_start))
+               {
+                  if (tag_end)
+                    {
+                       /* If we reached to a tag ending, analyze the tag */
+                       char *ttag;
+                       size_t ttag_len = tag_end - tag_start -1;
 
-       tag_start = tag_end = esc_start = esc_end = NULL;
-       p = (char *)text;
-       s = p;
-       for (;;)
-         {
-            if ((*p == 0) ||
-                (tag_end) || (esc_end) ||
-                (tag_start) || (esc_start))
-              {
-                 if (tag_end)
-                   {
-                      char *ttag;
-                      size_t ttag_len = tag_end - tag_start - 1;
-
-                      ttag = malloc(ttag_len + 1);
-                      if (ttag)
-                        {
-                           const char *match;
-                           size_t replace_len;
-
-                           strncpy(ttag, tag_start + 1, ttag_len);
-                           ttag[ttag_len] = 0;
-                           match = _style_match_tag(o->style, ttag, ttag_len, &replace_len);
-                           if (match)
-                             evas_textblock_cursor_format_prepend(cur, match);
-                           else
-                             {
-                                char *ttag2;
-
-                                ttag2 = malloc(ttag_len + 2 + 1);
-                                if (ttag2)
-                                  {
-                                     if (ttag[0] == '/')
-                                       {
-                                          strcpy(ttag2, "- ");
-                                          strcat(ttag2, ttag + 1);
-                                       }
-                                     else
-                                       {
-                                          strcpy(ttag2, "+ ");
-                                          strcat(ttag2, ttag);
-                                       }
-                                     evas_textblock_cursor_format_prepend(o->cursor, ttag2);
-                                     free(ttag2);
-                                  }
-                             }
-                           free(ttag);
-                        }
-                      tag_start = tag_end = NULL;
-                   }
-                 else if (esc_end)
-                   {
-                      _prepend_escaped_char(cur, esc_start, esc_end);
-                      esc_start = esc_end = NULL;
-                   }
-                 else if (*p == 0)
-                   {
-                      _prepend_text_run(o, s, p);
-                      s = NULL;
-                   }
-                 if (*p == 0)
-                   break;
-              }
-            if (*p == '<')
-              {
-                 if (!esc_start)
-                   {
-                      tag_start = p;
-                      tag_end = NULL;
-                      _prepend_text_run(o, s, p);
-                      s = NULL;
-                   }
-              }
-            else if (*p == '>')
-              {
-                 if (tag_start)
-                   {
-                      tag_end = p;
-                      s = p + 1;
-                   }
-              }
-            else if (*p == '&')
-              {
-                 if (!tag_start)
-                   {
-                      esc_start = p;
-                      esc_end = NULL;
-                      _prepend_text_run(o, s, p);
-                      s = NULL;
-                   }
-              }
-            else if (*p == ';')
-              {
-                 if (esc_start)
-                   {
-                      esc_end = p;
-                      s = p + 1;
-                   }
-              }
-            p++;
-         }
+
+                       ttag = malloc(ttag_len + 1);
+                       if (ttag)
+                         {
+                            const char *match;
+                            size_t replace_len;
+
+                            memcpy(ttag, tag_start + 1, ttag_len);
+                            ttag[ttag_len] = 0;
+                            match = _style_match_tag(o->style, ttag, ttag_len, &replace_len);
+                            if (match)
+                              {
+                                 evas_textblock_cursor_format_prepend(o->cursor, match);
+                              }
+                            else
+                              {
+                                 char *ttag2;
+
+                                 ttag2 = malloc(ttag_len + 2 + 1);
+                                 if (ttag2)
+                                   {
+                                      if (ttag[0] == '/')
+                                        {
+                                           strcpy(ttag2, "- ");
+                                           strcat(ttag2, ttag + 1);
+                                        }
+                                      else
+                                        {
+                                           strcpy(ttag2, "+ ");
+                                           strcat(ttag2, ttag);
+                                        }
+                                      evas_textblock_cursor_format_prepend(o->cursor, ttag2);
+                                      free(ttag2);
+                                   }
+                              }
+                            free(ttag);
+                         }
+                       tag_start = tag_end = NULL;
+                    }
+                  else if (esc_end)
+                    {
+                       _prepend_escaped_char(o->cursor, esc_start, esc_end);
+                       esc_start = esc_end = NULL;
+                    }
+                  else if (*p == 0)
+                    {
+                       _prepend_text_run(o, s, p);
+                       s = NULL;
+                    }
+                  if (*p == 0)
+                    break;
+               }
+             if (*p == '<')
+               {
+                  if (!esc_start)
+                    {
+                       /* Append the text prior to this to the textblock and mark
+                        * the start of the tag */
+                       tag_start = p;
+                       tag_end = NULL;
+                       _prepend_text_run(o, s, p);
+                       s = NULL;
+                    }
+               }
+             else if (*p == '>')
+               {
+                  if (tag_start)
+                    {
+                       tag_end = p;
+                       s = p + 1;
+                    }
+               }
+             else if (*p == '&')
+               {
+                  if (!tag_start)
+                    {
+                       /* Append the text prior to this to the textblock and mark
+                        * the start of the escape sequence */
+                       esc_start = p;
+                       esc_end = NULL;
+                       _prepend_text_run(o, s, p);
+                       s = NULL;
+                    }
+               }
+             else if (*p == ';')
+               {
+                  if (esc_start)
+                    {
+                       esc_end = p;
+                       s = p + 1;
+                    }
+               }
+             /* Unicode object replcament char */
+             else if (!strncmp("\xEF\xBF\xBC", p, 3))
+               {
+                  /*FIXME: currently just remove them, maybe do something
+                   * fancier in the future, atm it breaks if this char
+                   * is inside <> */
+                  _prepend_text_run(o, s, p);
+                  p += 2; /* it's also advanced later in this loop */
+                  s = NULL;
+               }
+             p++;
+          }
      }
+    _evas_textblock_changed(o, obj);
 }
 
+
 /**
- * to be documented.
- * @param obj  to be documented.
- * @return to be documented.
+ * @internal
+ * An helper function to markup get. Appends the format from fnode to the strbugf txt.
+ *
+ * @param o the textblock object.
+ * @param txt the strbuf to append to.
+ * @param fnode the format node to process.
+ */
+static void
+_markup_get_format_append(Evas_Object_Textblock *o, Eina_Strbuf *txt, Evas_Object_Textblock_Node_Format *fnode)
+{
+   size_t replace_len;
+   size_t tag_len;
+   const char *tag;
+   const char *replace;
+
+   replace_len = eina_strbuf_length_get(fnode->format);
+   replace = eina_strbuf_string_get(fnode->format);
+   tag = _style_match_replace(o->style, replace, replace_len, &tag_len);
+   eina_strbuf_append_char(txt, '<');
+   if (tag)
+     {
+        eina_strbuf_append_length(txt, tag, tag_len);
+     }
+   else
+     {
+        const char *s;
+        int push = 0;
+        int pop = 0;
+
+        // FIXME: need to escape
+        s = eina_strbuf_string_get(fnode->format);
+        if (*s == '+') push = 1;
+        if (*s == '-') pop = 1;
+        while ((*s == ' ') || (*s == '+') || (*s == '-')) s++;
+        if (pop) eina_strbuf_append_char(txt, '/');
+        eina_strbuf_append(txt, s);
+     }
+   eina_strbuf_append_char(txt, '>');
+}
+
+/**
+ * @internal
+ * An helper function to markup get. Appends the text in text.
+ *
+ * @param txt the strbuf to append to.
+ * @param text the text to process.
+ */
+static void
+_markup_get_text_append(Eina_Strbuf *txt, const Eina_Unicode *text)
+{
+   char *p = evas_common_encoding_unicode_to_utf8(text, NULL);
+   char *base = p;
+   while (*p)
+     {
+        const char *escape;
+        int adv;
+
+        escape = _escaped_char_match(p, &adv);
+        if (escape)
+          {
+             p += adv;
+             eina_strbuf_append(txt, escape);
+          }
+        else
+          {
+             eina_strbuf_append_char(txt, *p);
+             p++;
+          }
+     }
+   free(base);
+}
+/**
+ * Return the markup of the object.
+ *
+ * @param obj the evas object.
+ * @return the markup text of the object.
  */
 EAPI const char *
 evas_object_textblock_text_markup_get(const Evas_Object *obj)
 {
-   Evas_Object_Textblock_Node *n;
+   Evas_Object_Textblock_Node_Text *n;
    Eina_Strbuf *txt = NULL;
 
    TB_HEAD_RETURN(NULL);
    if (o->markup_text) return(o->markup_text);
    txt = eina_strbuf_new();
-   EINA_INLIST_FOREACH(o->nodes, n)
-     {
-       size_t replace_len = eina_strbuf_length_get(n->text);
-        if ((n->type == NODE_FORMAT) && replace_len)
-         {
-            size_t tag_len;
-            const char *tag = _style_match_replace(o->style, eina_strbuf_string_get(n->text), replace_len, &tag_len);
-            eina_strbuf_append_char(txt, '<');
-            if (tag)
-              {
-                 // FIXME: need to escape
-                 eina_strbuf_append_length(txt, tag, tag_len);
-              }
-            else
-              {
-                 const char *s;
-                 int push = 0;
-                 int pop = 0;
-
-                 // FIXME: need to escape
-                 s = eina_strbuf_string_get(n->text);
-                 if (*s == '+') push = 1;
-                 if (*s == '-') pop = 1;
-                 while ((*s == ' ') || (*s == '+') || (*s == '-')) s++;
-                 if (pop) eina_strbuf_append_char(txt, '/');
-                 if (push) eina_strbuf_append(txt, "+ ");
-                 eina_strbuf_append(txt, s);
-              }
-            eina_strbuf_append_char(txt, '>');
-         }
-       else if ((n->type == NODE_TEXT) && eina_strbuf_length_get(n->text))
-         {
-            const char *p = eina_strbuf_string_get(n->text);
+   EINA_INLIST_FOREACH(o->text_nodes, n)
+     {
+        Evas_Object_Textblock_Node_Format *fnode;
+        Eina_Unicode *text_base, *text;
+        int off;
+
+        /* 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. */
+        text_base = text =
+           eina_unicode_strdup(eina_ustrbuf_string_get(n->unicode));
+        fnode = n->format_node;
+        off = 0;
+        while (fnode && (fnode->text_node == n))
+          {
+             Eina_Unicode tmp_ch;
+             off += fnode->offset;
+             /* No need to skip on the first run */
+             tmp_ch = text[off];
+             text[off] = 0; /* Null terminate the part of the string */
+             _markup_get_text_append(txt, text);
+             _markup_get_format_append(o, txt, fnode);
+             text[off] = tmp_ch; /* Restore the char */
+             text += off;
+             if (fnode->visible)
+               {
+                  off = -1;
+                  text++;
+               }
+             else
+               {
+                  off = 0;
+               }
+             fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
+          }
+        /* Add the rest, skip replacement */
+        _markup_get_text_append(txt, text);
+        free(text_base);
+     }
 
-            while (*p)
-              {
-                 const char *escape;
-                 int adv;
 
-                 escape = _escaped_char_match(p, &adv);
-                 if (escape)
-                   {
-                      p += adv;
-                      eina_strbuf_append(txt, escape);
-                   }
-                 else
-                   {
-                      eina_strbuf_append_char(txt, *p);
-                      p++;
-                   }
-              }
-         }
-     }
    o->markup_text = eina_strbuf_string_steal(txt);
    eina_strbuf_free(txt);
    return o->markup_text;
 }
 
 /* cursors */
+
 /**
- * to be documented.
- * @param obj  to be documented.
- * @return to be documented.
+ * @internal
+ * Merge the current node with the next, no need to remove PS, already
+ * not there.
+ *
+ * @param o the text block object.
+ * @param to merge into to.
+ * @param from merge from from.
+ */
+static void
+_evas_textblock_nodes_merge(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *to,
+      Evas_Object_Textblock_Node_Text *from)
+{
+   Evas_Object_Textblock_Node_Format *itr;
+   Evas_Object_Textblock_Node_Format *pnode;
+   const Eina_Unicode *text;
+   int to_len, len;
+
+   if (!to || !from) return;
+
+   to_len = eina_ustrbuf_length_get(to->unicode);
+   text = eina_ustrbuf_string_get(from->unicode);
+   len = eina_ustrbuf_length_get(from->unicode);
+   eina_ustrbuf_append_length(to->unicode, text, len);
+
+   itr = from->format_node;
+   if (itr && (itr->text_node == from))
+     {
+        pnode = _NODE_FORMAT(EINA_INLIST_GET(itr)->prev);
+        if (pnode && (pnode->text_node == to))
+          {
+             itr->offset += to_len - _evas_textblock_node_format_pos_get(pnode);
+             itr->offset -= (pnode->visible) ? 1 : 0;
+          }
+        else
+          {
+             itr->offset += to_len;
+          }
+     }
+
+   while (itr && (itr->text_node == from))
+     {
+        itr->text_node = to;
+        itr = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
+     }
+   if (!to->format_node || (to->format_node->text_node != to))
+     {
+        to->format_node = from->format_node;
+     }
+
+   _evas_textblock_cursors_set_node(o, from, to);
+   o->text_nodes = _NODE_TEXT(eina_inlist_remove(
+            EINA_INLIST_GET(o->text_nodes), EINA_INLIST_GET(from)));
+   _evas_textblock_node_text_free(from);
+}
+
+/**
+ * @internal
+ * Merge the current node with the next, no need to remove PS, already
+ * not there.
+ *
+ * @param cur the cursor that points to the current node
+ */
+static void
+_evas_textblock_cursor_nodes_merge(Evas_Textblock_Cursor *cur)
+{
+   Evas_Object_Textblock_Node_Text *nnode;
+   Evas_Object_Textblock *o;
+   int len;
+
+   len = eina_ustrbuf_length_get(cur->node->unicode);
+
+   if (!cur) return;
+   o = (Evas_Object_Textblock *)(cur->obj->object_data);
+   nnode = _NODE_TEXT(EINA_INLIST_GET(cur->node)->next);
+   _evas_textblock_nodes_merge(o, cur->node, nnode);
+   _evas_textblock_cursors_update_offset(o->cursor, nnode, 0, len);
+   if (nnode == o->cursor->node)
+     {
+        o->cursor->node = cur->node;
+        o->cursor->pos += len;
+     }
+}
+
+/**
+ * @internal
+ * Return the format at a specific position.
+ *
+ * @param cur the cursor to the position.
+ * @return the format node at the specific postion or NULL if not found.
+ */
+static Evas_Object_Textblock_Node_Format *
+_evas_textblock_cursor_node_format_at_pos_get(const Evas_Textblock_Cursor *cur)
+{
+   Evas_Object_Textblock_Node_Format *node;
+   Evas_Object_Textblock_Node_Format *itr;
+   int position = 0;
+
+   if (!cur->node) return NULL;
+
+   node = cur->node->format_node;
+   if (!node) return NULL;
+   /* If there is no exclusive format node to this paragraph return the
+    * previous's node */
+   /* Find the main format node */
+   EINA_INLIST_FOREACH(node, itr)
+     {
+        if (itr->text_node != cur->node)
+          {
+             return NULL;
+          }
+        if ((position + itr->offset) == cur->pos)
+          {
+             return itr;
+          }
+        position += itr->offset;
+     }
+   return NULL;
+}
+
+/**
+ * @internal
+ * Return the last format node at the position of the format node n.
+ *
+ * @param n a format node at the positon.
+ * @return the last format node at the position of n.
+ */
+static Evas_Object_Textblock_Node_Format *
+_evas_textblock_node_format_last_at_off(const Evas_Object_Textblock_Node_Format *n)
+{
+   const Evas_Object_Textblock_Node_Format *nnode;
+   if (!n) return NULL;
+   nnode = n;
+   do
+     {
+        n = nnode;
+        nnode = _NODE_FORMAT(EINA_INLIST_GET(nnode)->next);
+     }
+   while (nnode && (nnode->offset == 0));
+
+   return (Evas_Object_Textblock_Node_Format *) n;
+}
+
+/**
+ * @internal
+ * Returns the visible format at a specific location.
+ *
+ * @param n a format at the specific position.
+ * @return the format node at the specific postion or NULL if not found.
+ */
+static Evas_Object_Textblock_Node_Format *
+_evas_textblock_node_visible_at_pos_get(const Evas_Object_Textblock_Node_Format *n)
+{
+   const Evas_Object_Textblock_Node_Format *nnode;
+   if (!n) return NULL;
+   /* The visible format is the last one, because it inserts a replacement
+    * char that advances the next formats. */
+
+   nnode = n;
+   do
+     {
+        n = nnode;
+        if (n->visible) return (Evas_Object_Textblock_Node_Format *) n;
+        nnode = _NODE_FORMAT(EINA_INLIST_GET(nnode)->next);
+     }
+   while (nnode && (nnode->offset == 0));
+
+   return NULL;
+}
+
+/**
+ * @internal
+ * Return the last format that applies to a specific cursor or at the specific
+ * position the cursor points to. This means either a cursor at or before the
+ * position of the cursor in the text node is returned or the previous's text
+ * node's format node.
+ *
+ * @param cur teh position to look at.
+ * @return the format node found.
+ */
+static Evas_Object_Textblock_Node_Format *
+_evas_textblock_cursor_node_format_before_or_at_pos_get(const Evas_Textblock_Cursor *cur)
+{
+   Evas_Object_Textblock_Node_Format *node, *pitr = NULL;
+   Evas_Object_Textblock_Node_Format *itr;
+   size_t position = 0;
+
+   if (!cur->node) return NULL;
+
+   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)
+     {
+        return node;
+     }
+   else if (node->offset > cur->pos)
+     {
+        return _NODE_FORMAT(EINA_INLIST_GET(node)->prev);
+     }
+   /* Find the main format node */
+   pitr = _NODE_FORMAT(EINA_INLIST_GET(node)->prev);
+   EINA_INLIST_FOREACH(node, itr)
+     {
+        if ((itr->text_node != cur->node) ||
+            ((position + itr->offset) > cur->pos))
+          {
+             return pitr;
+          }
+        else if ((position + itr->offset) == cur->pos)
+          {
+             return itr;
+          }
+        pitr = itr;
+        position += itr->offset;
+     }
+   return pitr;
+}
+
+/**
+ * @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.
+ *
+ * @param cur teh position to look at.
+ * @return the format node found.
+ */
+static Evas_Object_Textblock_Node_Format *
+_evas_textblock_cursor_node_format_before_pos_get(const Evas_Textblock_Cursor *cur)
+{
+   Evas_Object_Textblock_Node_Format *node, *pitr = NULL;
+   Evas_Object_Textblock_Node_Format *itr;
+   size_t position = 0;
+
+   if (!cur->node) return NULL;
+
+   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)
+     {
+        return node;
+     }
+   else if (node->offset > cur->pos)
+     {
+        return _NODE_FORMAT(EINA_INLIST_GET(node)->prev);
+     }
+   /* Find the main format node */
+   pitr = _NODE_FORMAT(EINA_INLIST_GET(node)->prev);
+   EINA_INLIST_FOREACH(node, itr)
+     {
+        position += itr->offset;
+        if ((itr->text_node != cur->node) ||
+            (position >= cur->pos))
+          {
+             return pitr;
+          }
+        pitr = itr;
+     }
+   return pitr;
+}
+/**
+ * Return the object's main cursor.
+ *
+ * @param obj the object.
+ * @return the obj's main cursor.
  */
 EAPI const Evas_Textblock_Cursor *
 evas_object_textblock_cursor_get(const Evas_Object *obj)
@@ -3308,9 +4316,14 @@ evas_object_textblock_cursor_get(const Evas_Object *obj)
 }
 
 /**
- * to be documented.
- * @param obj  to be documented.
- * @return to be documented.
+ * Create a new cursor, associate it to the obj and init it to point
+ * to the start of the textblock. Association to the object means the cursor
+ * will be updated when the object will change.
+ *
+ * @note if you need speed and you know what you are doing, it's slightly faster to just allocate the cursor yourself and not associate it. (only people developing the actual object, and not users of the object).
+ *
+ * @param obj the object to associate to.
+ * @return the new cursor.
  */
 EAPI Evas_Textblock_Cursor *
 evas_object_textblock_cursor_new(Evas_Object *obj)
@@ -3320,16 +4333,18 @@ evas_object_textblock_cursor_new(Evas_Object *obj)
    TB_HEAD_RETURN(NULL);
    cur = calloc(1, sizeof(Evas_Textblock_Cursor));
    cur->obj = obj;
-   cur->node = o->nodes;
+   cur->node = o->text_nodes;
    cur->pos = 0;
-   cur->eol = 0;
+
    o->cursors = eina_list_append(o->cursors, cur);
    return cur;
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
+ * Free the cursor and unassociate it from the object.
+ * @note do not use it to free unassociated cursors.
+ *
+ * @param cur the cursor to free.
  * @return Returns no value.
  */
 EAPI void
@@ -3345,228 +4360,382 @@ evas_textblock_cursor_free(Evas_Textblock_Cursor *cur)
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
+ * Returns true if the cursor points to a format.
+ *
+ * @param cur the cursor to check.
+ * @return Returns #EINA_TRUE if a cursor points to a format #EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool
+evas_textblock_cursor_is_format(const Evas_Textblock_Cursor *cur)
+{
+   if (!cur || !cur->node) return EINA_FALSE;
+   if (evas_textblock_cursor_format_is_visible_get(cur)) return EINA_TRUE;
+   return (_evas_textblock_cursor_node_format_at_pos_get(cur)) ?
+      EINA_TRUE : EINA_FALSE;
+}
+
+/**
+ * Returns the first format node.
+ *
+ * @param obj The evas, must not be NULL.
+ * @return Returns the first format node, may be null if there are none.
+ */
+EAPI const Evas_Object_Textblock_Node_Format *
+evas_textblock_node_format_first_get(const Evas_Object *obj)
+{
+   TB_HEAD_RETURN(NULL);
+   return o->format_nodes;
+}
+/**
+ * Returns the last format node.
+ *
+ * @param obj The evas textblock, must not be NULL.
+ * @return Returns the first format node, may be null if there are none.
+ */
+EAPI const Evas_Object_Textblock_Node_Format *
+evas_textblock_node_format_last_get(const Evas_Object *obj)
+{
+   TB_HEAD_RETURN(NULL);
+   if (o->format_nodes)
+     {
+        return _NODE_FORMAT(EINA_INLIST_GET(o->format_nodes)->last);
+     }
+   return NULL;
+}
+
+/**
+ * Returns the next format node (after n)
+ *
+ * @param n the current format node - not null.
+ * @return Returns the next format node, may be null.
+ */
+EAPI const Evas_Object_Textblock_Node_Format *
+evas_textblock_node_format_next_get(const Evas_Object_Textblock_Node_Format *n)
+{
+   return _NODE_FORMAT(EINA_INLIST_GET(n)->next);
+}
+
+/**
+ * Returns the prev format node (after n)
+ *
+ * @param n the current format node - not null.
+ * @return Returns the prev format node, may be null.
+ */
+EAPI const Evas_Object_Textblock_Node_Format *
+evas_textblock_node_format_prev_get(const Evas_Object_Textblock_Node_Format *n)
+{
+   return _NODE_FORMAT(EINA_INLIST_GET(n)->prev);
+}
+
+/**
+ * Sets the cursor to the start of the first text node.
+ *
+ * @param cur the cursor to update.
  * @return Returns no value.
  */
 EAPI void
-evas_textblock_cursor_node_first(Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_paragraph_first(Evas_Textblock_Cursor *cur)
 {
    Evas_Object_Textblock *o;
-
    if (!cur) return;
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
-   cur->node = o->nodes;
+   cur->node = o->text_nodes;
    cur->pos = 0;
-   cur->eol = 0;
+
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
+ * sets the cursor to the end of the last text node.
+ *
+ * @param cur the cursor to set.
  * @return Returns no value.
  */
 EAPI void
-evas_textblock_cursor_node_last(Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_paragraph_last(Evas_Textblock_Cursor *cur)
 {
    Evas_Object_Textblock *o;
+   Evas_Object_Textblock_Node_Text *node;
 
    if (!cur) return;
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
-   if (o->nodes)
+   node = o->text_nodes;
+   if (node)
      {
-       cur->node = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(o->nodes))->last);
+        node = _NODE_TEXT(EINA_INLIST_GET(node)->last);
+        cur->node = node;
        cur->pos = 0;
-        cur->eol = 0;  // 1
-       evas_textblock_cursor_char_last(cur);
+
+       evas_textblock_cursor_paragraph_char_last(cur);
      }
    else
      {
        cur->node = NULL;
        cur->pos = 0;
-        cur->eol = 0; // 1
+
      }
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
- * @return to be documented.
+ * Advances to the the start of the next text node
+ *
+ * @param cur the cursor to update
+ * @return #EINA_TRUE if it managed to advance a paragraph, #EINA_FALSE otherwise.
  */
 EAPI Eina_Bool
-evas_textblock_cursor_node_next(Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_paragraph_next(Evas_Textblock_Cursor *cur)
 {
    if (!cur) return EINA_FALSE;
    if (!cur->node) return EINA_FALSE;
-   if ((EINA_INLIST_GET(cur->node))->next)
+   /* If there is a current text node, return the next text node (if exists)
+    * otherwise, just return False. */
+   if (cur->node)
      {
-       cur->node = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(cur->node))->next);
-       cur->pos = 0;
-        cur->eol = 0;
-       return EINA_TRUE;
+        Evas_Object_Textblock_Node_Text *nnode;
+        nnode = _NODE_TEXT(EINA_INLIST_GET(cur->node)->next);
+        if (nnode)
+          {
+             cur->node = nnode;
+             cur->pos = 0;
+
+             return EINA_TRUE;
+          }
      }
    return EINA_FALSE;
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
- * @return to be documented.
+ * Advances to the the end of the next text node
+ *
+ * @param cur the cursor to update
+ * @return #EINA_TRUE if it managed to advance a paragraph, #EINA_FALSE otherwise.
  */
 EAPI Eina_Bool
-evas_textblock_cursor_node_prev(Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_paragraph_prev(Evas_Textblock_Cursor *cur)
 {
+   Evas_Object_Textblock_Node_Text *node;
    if (!cur) return EINA_FALSE;
    if (!cur->node) return EINA_FALSE;
-   if ((EINA_INLIST_GET(cur->node))->prev)
-     {
-       cur->node = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(cur->node))->prev);
-       evas_textblock_cursor_char_last(cur);
-       return EINA_TRUE;
+   /* If the current node is a text node, just get the prev if any,
+    * if it's a format, get the current text node out of the format and return
+    * the prev text node if any. */
+   node = cur->node;
+   /* If there is a current text node, return the prev text node
+    * (if exists) otherwise, just return False. */
+   if (node)
+     {
+        Evas_Object_Textblock_Node_Text *pnode;
+        pnode = _NODE_TEXT(EINA_INLIST_GET(cur->node)->prev);
+        if (pnode)
+          {
+             cur->node = pnode;
+             evas_textblock_cursor_paragraph_char_last(cur);
+             return EINA_TRUE;
+          }
      }
    return EINA_FALSE;
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
- * @return to be documented.
+ * Sets the cursor to point to the place where format points to.
+ *
+ * @param cur the cursor to update.
+ * @param n the format node to update according.
+ */
+EAPI void
+evas_textblock_cursor_set_at_format(Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Format *n)
+{
+   if (!cur || !n) return;
+   cur->node = n->text_node;
+   cur->pos = _evas_textblock_node_format_pos_get(n);
+}
+
+/**
+ * Advances to the next format node
+ *
+ * @param cur the cursor to be updated.
+ * @return #EINA_TRUE on success #EINA_FALSE otherwise.
  */
 EAPI Eina_Bool
-evas_textblock_cursor_char_next(Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_format_next(Evas_Textblock_Cursor *cur)
 {
-   int index, ch;
+   Evas_Object_Textblock_Node_Format *node;
 
    if (!cur) return EINA_FALSE;
    if (!cur->node) return EINA_FALSE;
-   if (cur->node->type == NODE_FORMAT) return EINA_FALSE;
-   if (!eina_strbuf_length_get(cur->node->text)) return EINA_FALSE;
-   index = cur->pos;
+   /* If the current node is a format node, just get the next if any,
+    * if it's a text, get the current format node out of the text and return
+    * the next format node if any. */
+   node = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
+   node = _evas_textblock_node_format_last_at_off(node);
+   if (!node)
+     {
+        if (cur->node->format_node)
+          {
+             cur->node = cur->node;
+             cur->pos = _evas_textblock_node_format_pos_get(node);
 
-   if (cur->node->type == NODE_TEXT)
+             return EINA_TRUE;
+          }
+     }
+   /* If there is a current text node, return the next format node (if exists)
+    * otherwise, just return False. */
+   else
      {
-        Evas_Object_Textblock_Line *ln = NULL;
-        Evas_Object_Textblock_Item *it = NULL;
-        int pos;
+        Evas_Object_Textblock_Node_Format *nnode;
+        nnode = _NODE_FORMAT(EINA_INLIST_GET(node)->next);
+        if (nnode)
+          {
+             cur->node = nnode->text_node;
+             cur->pos = _evas_textblock_node_format_pos_get(nnode);
+
+             return EINA_TRUE;
+          }
+     }
+   return EINA_FALSE;
+}
 
-       _find_layout_item_line_match(cur->obj, cur->node, cur->pos, cur->eol, &ln, &it);
-        if (it)
+/**
+ * Advances to the previous format node.
+ *
+ * @param cur the cursor to update.
+ * @return #EINA_TRUE on success #EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool
+evas_textblock_cursor_format_prev(Evas_Textblock_Cursor *cur)
+{
+   Evas_Object_Textblock_Node_Format *node;
+   if (!cur) return EINA_FALSE;
+   if (!cur->node) return EINA_FALSE;
+   /* If the current node is a format node, just get the next if any,
+    * if it's a text, get the current format node out of the text and return
+    * the next format node if any. */
+   node = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
+   if (evas_textblock_cursor_is_format(cur))
+     {
+        if (node)
           {
-             pos = cur->pos - it->source_pos;
-             if (pos <= 0) index -= pos;
+             cur->pos = _evas_textblock_node_format_pos_get(node);
+
+             return EINA_TRUE;
           }
-        else
-          printf("TB: 'it' not found\n");
      }
+   /* If there is a current text node, return the next text node (if exists)
+    * otherwise, just return False. */
+   if (node)
+     {
+        Evas_Object_Textblock_Node_Format *pnode;
+        pnode = _NODE_FORMAT(EINA_INLIST_GET(node)->prev);
+        if (pnode)
+          {
+             cur->node = pnode->text_node;
+             cur->pos = _evas_textblock_node_format_pos_get(node);
 
-   ch = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(cur->node->text), &index);
-   if ((ch == 0) || (index < 0)) return EINA_FALSE;
-   if (eina_strbuf_string_get(cur->node->text)[index] == 0) return EINA_FALSE;
-   cur->pos = index;
-   cur->eol = 0; // 1
-   return EINA_TRUE;
+             return EINA_TRUE;
+          }
+     }
+   return EINA_FALSE;
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
- * @return to be documented.
+ * Advances 1 char forward.
+ *
+ * @param cur the cursor to advance.
+ * @return #EINA_TRUE on success #EINA_FALSE otherwise.
  */
 EAPI Eina_Bool
-evas_textblock_cursor_char_prev(Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_char_next(Evas_Textblock_Cursor *cur)
 {
    int index;
-   int at_end_of_line = 0;
-   int at_start_of_line = 0;
+   const Eina_Unicode *text;
 
    if (!cur) return EINA_FALSE;
    if (!cur->node) return EINA_FALSE;
-   if (cur->node->type == NODE_FORMAT) return EINA_FALSE;
-   if (!eina_strbuf_length_get(cur->node->text)) return EINA_FALSE;
-   index = cur->pos;
-   if (index == 0) return EINA_FALSE;
 
-   // XXX: FIXME: determine at_end_of_line and at_start_of_line
-
-   if (cur->node->type == NODE_TEXT)
+   index = cur->pos;
+   text = eina_ustrbuf_string_get(cur->node->unicode);
+   GET_NEXT(text, index);
+   /* Only allow pointing a null if it's the last paragraph.
+    * because we don't have a PS there. */
+   if (text[index])
      {
-        Evas_Object_Textblock_Line *ln = NULL;
-        Evas_Object_Textblock_Item *it = NULL;
-        int pos;
-
-       _find_layout_item_line_match(cur->obj, cur->node, cur->pos, cur->eol, &ln, &it);
-        if (it)
+        cur->pos = index;
+        return EINA_TRUE;
+     }
+   else
+     {
+        if (!evas_textblock_cursor_paragraph_next(cur))
           {
-             pos = cur->pos - it->source_pos;
-             if (pos <= 0) at_start_of_line = 1;
-             if (it->text)
-               {
-                  int plast;
-
-                  plast = evas_common_font_utf8_get_last((unsigned char *) it->text, strlen(it->text));
-                  if ((index - it->source_pos) == plast) at_end_of_line = 1;
-               }
+             cur->pos = index;
+             return EINA_TRUE;
+          }
+        else
+          {
+             return EINA_FALSE;
           }
      }
+}
 
-   if ((cur->eol) && (at_end_of_line))
+/**
+ * Advances 1 char backward.
+ *
+ * @param cur the cursor to advance.
+ * @return #EINA_TRUE on success #EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool
+evas_textblock_cursor_char_prev(Evas_Textblock_Cursor *cur)
+{
+   if (!cur) return EINA_FALSE;
+   if (!cur->node) return EINA_FALSE;
+
+   if (cur->pos != 0)
      {
-        cur->eol = 0;
+        cur->pos--;
         return EINA_TRUE;
      }
-   evas_common_font_utf8_get_prev((unsigned char *)eina_strbuf_string_get(cur->node->text), &index);
-   if (/*(ch == 0) || */(index < 0)) return EINA_FALSE;
-   cur->pos = index;
-   if (at_start_of_line)
-     cur->eol =1;
-   else
-     cur->eol = 0;
-   return EINA_TRUE;
+   return evas_textblock_cursor_paragraph_prev(cur);
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
+ * Go to the first char in the node the cursor is pointing on.
+ *
+ * @param cur the cursor to update.
  * @return Returns no value.
  */
 EAPI void
-evas_textblock_cursor_char_first(Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_paragraph_char_first(Evas_Textblock_Cursor *cur)
 {
    if (!cur) return;
    cur->pos = 0;
-   cur->eol = 0;
+
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
+ * Go to the last char in a text node.
+ *
+ * @param cur the cursor to update.
  * @return Returns no value.
  */
 EAPI void
-evas_textblock_cursor_char_last(Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_paragraph_char_last(Evas_Textblock_Cursor *cur)
 {
    int index;
 
    if (!cur) return;
    if (!cur->node) return;
-   if (cur->node->type == NODE_FORMAT)
-     {
-       cur->pos = 0;
-       return;
-     }
-   index = evas_common_font_utf8_get_last((unsigned char *)eina_strbuf_string_get(cur->node->text), eina_strbuf_length_get(cur->node->text));
+   index = eina_ustrbuf_length_get(cur->node->unicode) - 1;
    if (index < 0) cur->pos = 0;
    cur->pos = index;
-   cur->eol = 0; // 1
+
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
+ * Go to the start of the current line
+ *
+ * @param cur the cursor to update.
  * @return Returns no value.
  */
 EAPI void
-evas_textblock_cursor_line_first(Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_line_char_first(Evas_Textblock_Cursor *cur)
 {
    Evas_Object_Textblock *o;
    Evas_Object_Textblock_Line *ln = NULL;
@@ -3577,12 +4746,20 @@ evas_textblock_cursor_line_first(Evas_Textblock_Cursor *cur)
    if (!cur->node) return;
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
    if (!o->formatted.valid) _relayout(cur->obj);
-   if (cur->node->type == NODE_FORMAT)
-     _find_layout_format_item_line_match(cur->obj, cur->node, &ln, &fi);
+   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
-     _find_layout_item_line_match(cur->obj, cur->node, cur->pos, cur->eol, &ln, &it);
+     {
+        _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it);
+     }
+
    if (!ln) return;
-   cur->eol = 0;
+
    it = (Evas_Object_Textblock_Item *)ln->items;
    fi = (Evas_Object_Textblock_Format_Item *)ln->format_items;
    if ((it) && (fi))
@@ -3595,73 +4772,398 @@ evas_textblock_cursor_line_first(Evas_Textblock_Cursor *cur)
        cur->pos = it->source_pos;
        cur->node = it->source_node;
      }
-   else if (fi)
-     {
-       cur->pos = 0;
-       cur->node = fi->source_node;
+   else if (fi)
+     {
+       cur->node = fi->source_node->text_node;
+       cur->pos = _evas_textblock_node_format_pos_get(fi->source_node);
+     }
+}
+
+/**
+ * Go to the end of the current line.
+ *
+ * @param cur the cursor to update.
+ * @return Returns no value.
+ */
+EAPI void
+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;
+
+   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   
+
+   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
+     {
+        _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &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;
+     }
+   if (it)
+     {
+       int index;
+
+       cur->pos = it->source_pos;
+       cur->node = it->source_node;
+       index = eina_unicode_strlen(it->text) - 1;
+        if (index < 0) index = 0;
+        if (index >= 0) GET_NEXT(it->text, index);
+       if (index >= 0) cur->pos += index;
+     }
+   else if (fi)
+     {
+       cur->node = fi->source_node->text_node;
+       cur->pos = _evas_textblock_node_format_pos_get(fi->source_node);
+     }
+}
+
+/**
+ * @internal
+ * checks if a format (as a string) is visible.
+ *
+ * @param the string.
+ * @return #EINA_TRUE if it represents a visible format #EINA_FALSE otherwise.
+ */
+static Eina_Bool
+_evas_textblock_format_is_visible(const char *s)
+{
+   if (!s) return EINA_FALSE;
+   const char *item;
+   Eina_Bool is_opener = EINA_TRUE;
+
+   if (s[0] == '+' || s[0] == '-')
+     {
+        is_opener = (s[0] == '+') ? EINA_TRUE : EINA_FALSE;
+        s++;
+     }
+   while ((item = _format_parse(&s)))
+     {
+        char *tmp;
+        tmp = alloca(s - item + 1);
+        strncpy(tmp, item, s - item);
+        tmp[s - item] = '\0';
+        /* We care about all of the formats even after a - except for
+         * item which we don't care after a - because it's just a standard
+         * closing */
+        if (((!strcmp(item, "\n")) || (!strcmp(item, "\\n"))) ||
+              ((!strcmp(item, "\t")) || (!strcmp(item, "\\t"))) ||
+              (!strcmp(item, "ps")) ||
+              (!strncmp(item, "item", 4) && is_opener)) /*FIXME: formats like item2 will break it. */
+          return EINA_TRUE;
+     }
+   return EINA_FALSE;
+}
+
+/**
+ * Sets the cursor to the position of where the fmt points to.
+ *
+ * @param cur the cursor to update.
+ * @param fmt the format to set according to.
+ * @return nothing.
+ */
+static void __UNUSED__
+_evas_textblock_cursor_node_text_at_format(Evas_Textblock_Cursor *cur, Evas_Object_Textblock_Node_Format *fmt)
+{
+   Evas_Object_Textblock_Node_Text *text;
+   Evas_Object_Textblock_Node_Format *base_format;
+   Evas_Object_Textblock_Node_Format *itr;
+   size_t position = 0;
+
+   if (!cur || !fmt) return;
+   /* Find the main format node */
+   text = fmt->text_node;
+   cur->node = text;
+   base_format = text->format_node;
+   EINA_INLIST_FOREACH(base_format, itr)
+     {
+        if (itr == fmt)
+          {
+             break;
+          }
+        position += itr->offset;
+     }
+   cur->pos = position;
+
+}
+/**
+ * @internal
+ * Add the offset (may be negative) to the first node after fmt which is
+ * pointing to the text node tnode or to o->format_nodes if fmt is null
+ * and it points to tnode.
+ *
+ * @param o the textblock object.
+ * @param tnode the text node the format should point to.
+ * @param fmt the current format.
+ * @param offset the offest to add (may be negative).
+ */
+static void
+_evas_textblock_node_format_adjust_offset(Evas_Object_Textblock *o,
+      Evas_Object_Textblock_Node_Text *tnode,
+      Evas_Object_Textblock_Node_Format *fmt, int offset)
+{
+   if (fmt)
+     {
+        fmt = _NODE_FORMAT(EINA_INLIST_GET(fmt)->next);
+     }
+   else
+     {
+        fmt = o->format_nodes;
+     }
+   if (fmt && (tnode == fmt->text_node))
+     {
+        fmt->offset += offset;
+     }
+}
+
+/**
+ * @internal
+ * Removes a format node updating the offset of the next format node and the
+ * text nodes pointing to this node.
+ *
+ * @param o the textblock object.
+ * @param n the fromat node to remove
+ */
+static void
+_evas_textblock_node_format_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Format *n, int visible_adjustment)
+{
+   /* Update the text nodes about the change */
+     {
+        Evas_Object_Textblock_Node_Format *nnode;
+        nnode = _NODE_FORMAT(EINA_INLIST_GET(n)->next);
+        /* If there's a next node that belongs to the same text node
+         * and the curret node was the main one, advance the format node */
+        if (nnode && (nnode->text_node == n->text_node))
+          {
+             if (nnode->text_node->format_node == n)
+               {
+                  nnode->text_node->format_node = nnode;
+               }
+          }
+        else
+          {
+             Evas_Object_Textblock_Node_Text *tnode;
+             /* If there's no next one update the text nodes */
+             nnode = _NODE_FORMAT(EINA_INLIST_GET(n)->prev);
+             tnode = n->text_node;
+             while (tnode && (tnode->format_node == n))
+               {
+                  tnode->format_node = nnode;
+                  tnode = _NODE_TEXT(EINA_INLIST_GET(tnode)->next);
+               }
+          }
+     }
+   _evas_textblock_node_format_adjust_offset(o, n->text_node, n,
+         n->offset - visible_adjustment);
+
+   o->format_nodes = _NODE_FORMAT(eina_inlist_remove(
+           EINA_INLIST_GET(o->format_nodes), EINA_INLIST_GET(n)));
+}
+
+/**
+ * @internal
+ * Removes all the format nodes at a location strating from n.
+ * This function updates the offset of the next format node and the
+ * text nodes pointing to it.
+ *
+ * @param o the textblock object.
+ * @param n the fromat node to remove from.
+ */
+static void
+_evas_textblock_node_format_remove_all_at_pos(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Format *n)
+{
+   Evas_Object_Textblock_Node_Format *nnode;
+   Evas_Object_Textblock_Node_Text *tnode;
+
+   nnode = n;
+   tnode = n->text_node;
+   do
+     {
+        Evas_Object_Textblock_Node_Format *curnode;
+        curnode = nnode;
+        nnode = _NODE_FORMAT(EINA_INLIST_GET(nnode)->next);
+
+        _evas_textblock_node_format_remove(o, curnode, curnode->visible);
+     }
+   while (nnode && (nnode->text_node == tnode) && (nnode->offset == 0));
+}
+
+/**
+ * @internal
+ * Removes all the format nodes between start and end in the text node n.
+ * This function updates the offset of the next format node and the
+ * text nodes pointing to it. if end == -1 end means the end of the string.
+ *
+ * @param o the textblock object.
+ * @param n the text node the positinos refer to.
+ * @param start the start of where to delete from.
+ * @param end the end of the section to delete, if end == -1 it means the end of the string.
+ */
+static void
+_evas_textblock_node_text_remove_formats_between(Evas_Object_Textblock *o,
+      Evas_Object_Textblock_Node_Text *n, int start, int end)
+{
+   Evas_Object_Textblock_Node_Format *itr;
+   int use_end = 1;
+   int offset = end - start;
+   itr = n->format_node;
+
+   if (itr)
+     start -= itr->offset;
+   if (offset < 0) offset = 0;
+   while (itr && (itr->text_node == n))
+     {
+        Evas_Object_Textblock_Node_Format *nnode;
+        int tmp_offset = 0;
+
+        /* start is negative when this gets relevant */
+        if ((offset + start <= 0) && use_end)
+          {
+             break;
+          }
+        nnode = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
+        if (nnode)
+          {
+             tmp_offset = nnode->offset;
+          }
+        if (start <= 0)
+          {
+             /* Don't do visible adjustments because we are removing the visual
+              * chars anyway and taking those into account */
+             _evas_textblock_node_format_remove(o, itr, 0);
+          }
+        start -= tmp_offset;
+        itr = nnode;
+     }
+}
+
+/**
+ * @internal
+ * Returns the first format in the range between start and end in the textblock
+ * n.
+ *
+ * @param o the textblock object.
+ * @param n the text node the positinos refer to.
+ * @param start the start of where to delete from.
+ * @param end the end of the section to delete, if end == -1 it means the end of the string.
+ */
+static Evas_Object_Textblock_Node_Format *
+_evas_textblock_node_text_get_first_format_between(
+      Evas_Object_Textblock_Node_Text *n, int start, int end)
+{
+   Evas_Object_Textblock_Node_Format *itr;
+   int use_end = 1;
+   itr = n->format_node;
+   if (end < 0) use_end = 0;
+   while (itr && (itr->text_node == n))
+     {
+        start -= itr->offset;
+        end -= itr->offset;
+        if ((end <= 0) && use_end)
+          {
+             break;
+          }
+        if (start <= 0)
+          {
+             return itr;
+          }
+        itr = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
      }
+   return NULL;
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
- * @return Returns no value.
+ * Removes a text node and the corresponding format nodes.
+ *
+ * @param o the textblock objec.t
+ * @param n the node to remove.
  */
-EAPI void
-evas_textblock_cursor_line_last(Evas_Textblock_Cursor *cur)
+static void
+_evas_textblock_node_text_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *n)
 {
-   Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Line *ln = NULL;
-   Evas_Object_Textblock_Item *it = NULL;
-   Evas_Object_Textblock_Format_Item *fi = NULL;
-
-   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->eol = 1;
-   if (cur->node->type == NODE_FORMAT)
-     _find_layout_format_item_line_match(cur->obj, cur->node, &ln, &fi);
-   else
-     _find_layout_item_line_match(cur->obj, cur->node, cur->pos, cur->eol, &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))
+   Evas_Object_Textblock_Node_Format *fnode;
+   Evas_Object_Textblock_Node_Text *tnode;
+   fnode = n->format_node;
+   /* We want to get the last format node that will exist so if
+    * it's a node to be deleted get the previous one */
+   if (fnode && (fnode->text_node == n))
      {
-       if ((it->x + it->w) > (fi->x + fi->w)) fi = NULL;
-       else it = NULL;
+        fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->prev);
      }
-   if (it)
+   /* Update all the text node -> format node links
+    * go through all the text nodes starting from ours and update
+    * all the ones pointing to a format node that belongs to n */
+   tnode = _NODE_TEXT(EINA_INLIST_GET(n)->next);
+   while (tnode && tnode->format_node && (tnode->format_node->text_node = n))
      {
-       int index;
-
-       cur->pos = it->source_pos;
-       cur->node = it->source_node;
-       index = evas_common_font_utf8_get_last((unsigned char *)it->text, strlen(it->text));
-        if ((index >= 0) && (it->text[0] != 0))
-          evas_common_font_utf8_get_next((unsigned char *)(it->text), &index);
-       if (index >= 0) cur->pos += index;
+        tnode->format_node = fnode;
+        tnode = _NODE_TEXT(EINA_INLIST_GET(tnode)->next);
      }
-   else if (fi)
+   _evas_textblock_node_text_remove_formats_between(o, n, 0, -1);
+   o->text_nodes = _NODE_TEXT(eina_inlist_remove(
+           EINA_INLIST_GET(o->text_nodes), EINA_INLIST_GET(n)));
+}
+
+/**
+ * @internal
+ * Return the position where the formats starts at.
+ *
+ * @param fmt the format to return the position of.
+ * @return the position of the format in the text node it points to.
+ */
+static size_t
+_evas_textblock_node_format_pos_get(const Evas_Object_Textblock_Node_Format *fmt)
+{
+   Evas_Object_Textblock_Node_Text *text;
+   Evas_Object_Textblock_Node_Format *base_format;
+   Evas_Object_Textblock_Node_Format *itr;
+   size_t position = 0;
+
+   if (!fmt) return 0;
+   /* Find the main format node */
+   text = fmt->text_node;
+   base_format = text->format_node;
+   EINA_INLIST_FOREACH(base_format, itr)
      {
-       cur->pos = 0;
-        cur->eol = 0;
-       cur->node = fi->source_node;
+        if (itr == fmt)
+          {
+             break;
+          }
+        position += itr->offset;
      }
+   return position + fmt->offset;
 }
 
 /**
- * to be documented.
- * @param cur  to be documented.
- * @return to be documented.
+ * Return the current cursor pos.
+ *
+ * @param cur the cursor to take the position from.
+ * @return the position or -1 on error
  */
 EAPI int
 evas_textblock_cursor_pos_get(const Evas_Textblock_Cursor *cur)
@@ -3671,30 +5173,42 @@ evas_textblock_cursor_pos_get(const Evas_Textblock_Cursor *cur)
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @param pos to be documented.
+ * Set the cursor pos.
+ *
+ * @param cur the cursor to be set.
+ * @param pos the pos to set.
  */
 EAPI void
-evas_textblock_cursor_pos_set(Evas_Textblock_Cursor *cur, int pos)
+evas_textblock_cursor_pos_set(Evas_Textblock_Cursor *cur, int _pos)
 {
-   unsigned int len;
+   size_t len, pos;
 
    if (!cur) return;
    if (!cur->node) return;
-   if (cur->node->type == NODE_FORMAT) pos = 0;
-   len = eina_strbuf_length_get(cur->node->text);
-   if (pos < 0) pos = 0;
-   else if (pos > len) pos = len;
+   len = eina_ustrbuf_length_get(cur->node->unicode);
+   if (_pos < 0)
+     {
+        pos = 0;
+     }
+   else
+     {
+        pos = (size_t) _pos;
+     }
+
+   if (pos > len)
+     {
+        pos = len;
+     }
    cur->pos = pos;
-   cur->eol = 0;
+
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @param line to be documented.
- * @return to be documented.
+ * Go to the start of the line passed
+ *
+ * @param cur cursor to update.
+ * @param line numer to set.
+ * @return #EINA_TRUE on success, #EINA_FALSE on error.
  */
 EAPI Eina_Bool
 evas_textblock_cursor_line_set(Evas_Textblock_Cursor *cur, int line)
@@ -3720,29 +5234,29 @@ evas_textblock_cursor_line_set(Evas_Textblock_Cursor *cur, int line)
    if (it)
      {
        cur->pos = it->source_pos;
-        cur->eol = 0;
+
        cur->node = it->source_node;
      }
    else if (fi)
      {
-       cur->pos = 0;
-        cur->eol = 0;
-       cur->node = fi->source_node;
+       cur->node = fi->source_node->text_node;
+       cur->pos = _evas_textblock_node_format_pos_get(fi->source_node);
      }
    else
      {
         cur->pos = 0;
-        cur->eol = 0;
-        cur->node = o->nodes;
+
+        cur->node = o->text_nodes;
      }
    return EINA_TRUE;
 }
 
 /**
- * to be documented.
- * @param cur1 to be documented.
- * @param cur2 to be documented.
- * @return to be documented.
+ * Compare two cursors.
+ *
+ * @param cur1 the first cursor.
+ * @param cur2 the second cursor.
+ * @return -1 if cur1 < cur2, 0 if cur1 == cur2 and 1 otherwise.
  */
 EAPI int
 evas_textblock_cursor_compare(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2)
@@ -3757,9 +5271,7 @@ evas_textblock_cursor_compare(const Evas_Textblock_Cursor *cur1, const Evas_Text
      {
        if (cur1->pos < cur2->pos) return -1; /* cur1 < cur2 */
        else if (cur1->pos > cur2->pos) return 1; /* cur2 < cur1 */
-        if ((cur1->eol) == (cur1->eol)) return 0; /* cur1 == cur2 */
-        if (cur1->eol) return 1; /* cur2 < cur1 */
-       return -1; /* cur1 < cur2 */
+       return 0;
      }
    for (l1 = EINA_INLIST_GET(cur1->node),
         l2 = EINA_INLIST_GET(cur1->node); (l1) || (l2);)
@@ -3768,16 +5280,18 @@ evas_textblock_cursor_compare(const Evas_Textblock_Cursor *cur1, const Evas_Text
        else if (l2 == EINA_INLIST_GET(cur2->node)) return -1; /* cur1 < cur 2 */
        else if (!l1) return -1; /* cur1 < cur 2 */
        else if (!l2) return 1; /* cur2 < cur 1 */
-       if (l1) l1 = l1->prev;
-       if (l2) l2 = l2->next;
+       l1 = l1->prev;
+       l2 = l2->next;
      }
    return 0;
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @param cur_dest to be documented.
+ * Make cur_dest point to the same place as cur. Does not work if they don't
+ * point to the same object.
+ *
+ * @param cur the source cursor.
+ * @param cur_dest destination cursor.
  * @return Returns no value.
  */
 EAPI void
@@ -3788,336 +5302,213 @@ evas_textblock_cursor_copy(const Evas_Textblock_Cursor *cur, Evas_Textblock_Curs
    if (cur->obj != cur_dest->obj) return;
    cur_dest->pos = cur->pos;
    cur_dest->node = cur->node;
-   cur_dest->eol = cur->eol;
+
 }
 
 
 /* text controls */
 /**
- * to be documented.
- * @param cur to be documented.
- * @param text to be documented.
- * @return Returns no value.
+ * @internal
+ * Free a text node.
+ *
+ * @param n the text node to free
  */
-EAPI void
-evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text)
+static void
+_evas_textblock_node_text_free(Evas_Object_Textblock_Node_Text *n)
 {
-   Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n, *nrel;
-   int index, ch;
+   if (!n) return;
+   eina_ustrbuf_free(n->unicode);
+   if (n->utf8)
+     free(n->utf8);
+   free(n);
+}
 
-   if (!cur) return;
-   o = (Evas_Object_Textblock *)(cur->obj->object_data);
-   if (text)
-     {
-       Eina_List *l;
-       Evas_Textblock_Cursor *data;
+/**
+ * @internal
+ * Create a new text node
+ *
+ * @return the new text node.
+ */
+static Evas_Object_Textblock_Node_Text *
+_evas_textblock_node_text_new(void)
+{
+   Evas_Object_Textblock_Node_Text *n;
 
-       if (cur != o->cursor)
-         {
-            if (cur->node == o->cursor->node)
-              {
-                 if (o->cursor->pos > cur->pos)
-                    {
-                       o->cursor->pos += strlen(text);
-                    }
-              }
-         }
-       EINA_LIST_FOREACH(o->cursors, l, data)
-         {
-            if (data != cur)
-              {
-                 if (cur->node == data->node)
-                   {
-                      if (data->pos > cur->pos)
-                         {
-                            data->pos += strlen(text);
-                         }
-                   }
-              }
-         }
-     }
-   n = cur->node;
-   if ((!n) || (n->type == NODE_FORMAT))
-     {
-       nrel = n;
-       n = calloc(1, sizeof(Evas_Object_Textblock_Node));
-       n->type = NODE_TEXT;
-       n->text = eina_strbuf_new();
-       if (nrel)
-         o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes),
-                                                                              EINA_INLIST_GET(n),
-                                                                              EINA_INLIST_GET(nrel));
-       else
-         o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n));
-     }
-   cur->node = n;
-   index = cur->pos;
-   if (eina_strbuf_length_get(n->text))
-     {
-       ch = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n->text), &index);
-       if (ch != 0)
-          {
-             cur->pos = index;
-          }
-     }
-   if (cur->pos >= (eina_strbuf_length_get(n->text) - 1))
-     eina_strbuf_append(n->text, (char *)text);
-   else
-     eina_strbuf_insert(n->text, (char *)text, cur->pos);
-// XXX: This makes no sense?
-   if (text)
-     {
-        cur->pos += strlen(text);
-     }
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   if (o->markup_text)
-     {
-       free(o->markup_text);
-       o->markup_text = NULL;
-     }
-   _nodes_adjacent_merge(cur->obj, n);
-   evas_object_change(cur->obj);
+   n = calloc(1, sizeof(Evas_Object_Textblock_Node_Text));
+   n->unicode = eina_ustrbuf_new();
+#ifdef BIDI_SUPPORT
+   n->bidi_props.direction = EVAS_BIDI_PARAGRAPH_NATURAL;
+#endif
+
+   return n;
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @param text to be documented.
+ * @internal
+ * Break a paragraph. This does not add a PS but only splits the paragraph
+ * where a ps was just added!
+ *
+ * @param cur the cursor to break at.
+ * @param fnode the format node of the PS just added.
  * @return Returns no value.
  */
-EAPI void
-evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text)
+static void
+_evas_textblock_cursor_break_paragraph(Evas_Textblock_Cursor *cur,
+                              Evas_Object_Textblock_Node_Format *fnode)
 {
    Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n, *nrel;
+   Evas_Object_Textblock_Node_Text *n;
 
    if (!cur) return;
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
-     {
-       Eina_List *l;
-       Evas_Textblock_Cursor *data;
 
-       if (cur != o->cursor)
-         {
-            if (cur->node == o->cursor->node)
-              {
-                 if ((o->cursor->node) &&
-                     (o->cursor->node->type == NODE_TEXT) &&
-                     (o->cursor->pos >= cur->pos))
-                    {
-                       o->cursor->pos += strlen(text);
-                    }
-              }
-         }
-       EINA_LIST_FOREACH(o->cursors, l, data)
-         {
-            if (data != cur)
-              {
-                 if (cur->node == data->node)
-                   {
-                      if (data->node &&
-                          (data->node->type == NODE_TEXT) &&
-                          (data->pos >= cur->pos))
-                         {
-                            data->pos += strlen(text);
-                         }
-                   }
-              }
-         }
-     }
-   n = cur->node;
-   if ((!n) || (n->type == NODE_FORMAT))
-     {
-       nrel = n;
-       n = calloc(1, sizeof(Evas_Object_Textblock_Node));
-       n->type = NODE_TEXT;
-       n->text = eina_strbuf_new();
-       if (nrel)
-         o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_prepend_relative(EINA_INLIST_GET(o->nodes),
-                                                                               EINA_INLIST_GET(n),
-                                                                               EINA_INLIST_GET(nrel));
-       else
-         o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_prepend(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n));
-     }
-   if (!n->text) n->text = eina_strbuf_new();
-   cur->node = n;
-   
-   if (text)
-     {
-        if (cur->pos > (eina_strbuf_length_get(n->text) - 1))
+   n = _evas_textblock_node_text_new();
+   o->text_nodes = _NODE_TEXT(eina_inlist_append_relative(
+                   EINA_INLIST_GET(o->text_nodes),
+                   EINA_INLIST_GET(n),
+                   EINA_INLIST_GET(cur->node)));
+   /* Handle text and format changes. */
+   if (cur->node)
+     {
+        Evas_Object_Textblock_Node_Format *nnode;
+        size_t len, start;
+        const Eina_Unicode *text;
+
+        /* If there was a format node in the delete range,
+         * make it our format and update the text_node fields,
+         * otherwise, use the paragraph separator
+         * of the previous paragraph. */
+        nnode  = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
+        if (nnode && (nnode->text_node == cur->node))
           {
-             eina_strbuf_append(n->text, (char *)text);
+             n->format_node = nnode;
+             nnode->offset--; /* We don't have to take the replacement char
+                                 into account anymore */
+             while (nnode && (nnode->text_node == cur->node))
+               {
+                  nnode->text_node = n;
+                  nnode = _NODE_FORMAT(EINA_INLIST_GET(nnode)->next);
+               }
           }
         else
           {
-             eina_strbuf_insert(n->text, (char *)text, cur->pos);
+             n->format_node = fnode;
           }
-        cur->pos += strlen(text);
+
+        /* cur->pos now points to the PS, move after. */
+        start = cur->pos + 1;
+        text = eina_ustrbuf_string_get(cur->node->unicode);
+        len = eina_ustrbuf_length_get(cur->node->unicode) - start;
+        eina_ustrbuf_append_length(n->unicode, text + start, len);
+        eina_ustrbuf_remove(cur->node->unicode, start, start + len);
      }
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   if (o->markup_text)
+   else
      {
-       free(o->markup_text);
-       o->markup_text = NULL;
+        Evas_Object_Textblock_Node_Format *fnode;
+        fnode = o->format_nodes;
+        if (fnode)
+          {
+             fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->last);
+          }
+        n->format_node = fnode;
      }
-   _nodes_adjacent_merge(cur->obj, n);
-   evas_object_change(cur->obj);
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @param format to be documented.
- * @return Returns no value.
+ * @internal
+ * Set the node and offset of all the curs after cur.
+ *
+ * @param cur the cursor.
+ * @param n the current textblock node.
+ * @param new_node the new node to set.
  */
-EAPI void
-evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *format)
+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)
 {
-   Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n, *nc, *n2;
+   Eina_List *l;
+   Evas_Textblock_Cursor *data;
 
-   if (!cur) return;
-   if ((!format) || (format[0] == 0)) return;
-   o = (Evas_Object_Textblock *)(cur->obj->object_data);
-   nc = cur->node;
-   n = calloc(1, sizeof(Evas_Object_Textblock_Node));
-   n->type = NODE_FORMAT;
-   n->text = eina_strbuf_new();
-   eina_strbuf_append(n->text, format);
-   if (!nc)
+   if (n == o->cursor->node)
      {
-        o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n));
+        o->cursor->pos = 0;
+        o->cursor->node = new_node;
      }
-   else if (nc->type == NODE_FORMAT)
+   EINA_LIST_FOREACH(o->cursors, l, data)
      {
-        o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes),
-                                                                            EINA_INLIST_GET(n),
-                                                                            EINA_INLIST_GET(nc));
-     }
-   else if (nc->type == NODE_TEXT)
-     {
-       int index, ch = 0;
-
-       index = cur->pos;
-       if (eina_strbuf_length_get(nc->text))
-         {
-            ch = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(nc->text), &index);
-            if (ch != 0)
-              cur->pos = index;
-         }
-       o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes),
-                                                                            EINA_INLIST_GET(n),
-                                                                            EINA_INLIST_GET(nc));
-       if ((ch != 0) && (cur->pos < eina_strbuf_length_get(nc->text)))
-         {
-            n2 = calloc(1, sizeof(Evas_Object_Textblock_Node));
-            n2->type = NODE_TEXT;
-            n2->text = eina_strbuf_new();
-            eina_strbuf_append(n2->text, (eina_strbuf_string_get(nc->text) + cur->pos));
-            o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes),
-                                                                                 EINA_INLIST_GET(n2),
-                                                                                 EINA_INLIST_GET(n));
-
-            eina_strbuf_remove(nc->text, cur->pos, eina_strbuf_length_get(nc->text));
-         }
-     }
-   cur->node = n;
-// XXX: This makes no sense
-   cur->pos = 0;
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   if (o->markup_text)
-     {
-       free(o->markup_text);
-       o->markup_text = NULL;
+        if (n == data->node)
+          {
+             data->pos = 0;
+             data->node = new_node;
+          }
      }
-   evas_object_change(cur->obj);
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @param format to be documented.
- * @return Returns no value.
+ * @internal
+ * Update the offset of all the cursors after cur.
+ *
+ * @param cur the cursor.
+ * @param n the current textblock node.
+ * @param start the starting pos.
+ * @param offset how much to adjust (can be negative).
  */
-EAPI void
-evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *format)
+static void
+_evas_textblock_cursors_update_offset(const Evas_Textblock_Cursor *cur,
+      const Evas_Object_Textblock_Node_Text *n,
+      size_t start, int offset)
 {
+   Eina_List *l;
+   Evas_Textblock_Cursor *data;
    Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n, *nc, *n2;
-
-   if (!cur) return;
-   if ((!format) || (format[0] == 0)) return;
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
-   nc = cur->node;
-   n = calloc(1, sizeof(Evas_Object_Textblock_Node));
-   n->type = NODE_FORMAT;
-   n->text = eina_strbuf_new();
-   eina_strbuf_append(n->text, format);
-   if (!nc)
-     {
-       o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_prepend(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n));
-       cur->node = n;
-       cur->pos = 0;
-     }
-   else if (nc->type == NODE_FORMAT)
+
+   if (cur != o->cursor)
      {
-        o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_prepend_relative(EINA_INLIST_GET(o->nodes),
-                                                                             EINA_INLIST_GET(n),
-                                                                             EINA_INLIST_GET(nc));
-       cur->node = nc;
-       cur->pos = 0;
+        if ((n == o->cursor->node) &&
+              (o->cursor->pos > start))
+          {
+             if ((offset < 0) && (o->cursor->pos <= (size_t) (-1 * offset)))
+               {
+                  o->cursor->pos = 0;
+               }
+             else
+               {
+                  o->cursor->pos += offset;
+               }
+          }
      }
-   else if (nc->type == NODE_TEXT)
+   EINA_LIST_FOREACH(o->cursors, l, data)
      {
-        int len;
-
-        len = eina_strbuf_length_get(nc->text);
-       if (cur->pos == 0)
-         o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_prepend_relative(EINA_INLIST_GET(o->nodes),
-                                                                               EINA_INLIST_GET(n),
-                                                                               EINA_INLIST_GET(nc));
-       else
-         o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes),
-                                                                              EINA_INLIST_GET(n),
-                                                                              EINA_INLIST_GET(nc));
-       if ((cur->pos < len) && (cur->pos != 0))
-         {
-            n2 = calloc(1, sizeof(Evas_Object_Textblock_Node));
-            n2->type = NODE_TEXT;
-            n2->text = eina_strbuf_new();
-            eina_strbuf_append(n2->text, 
-                                (eina_strbuf_string_get(nc->text) + cur->pos));
-            o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_append_relative(EINA_INLIST_GET(o->nodes),
-                                                                                 EINA_INLIST_GET(n2),
-                                                                                 EINA_INLIST_GET(n));
-            eina_strbuf_remove(nc->text, cur->pos, eina_strbuf_length_get(nc->text));
-            cur->node = n2;
-            cur->pos = 0;
-//             cur->eol = 0;
-         }
-       else if (cur->pos == len)
-         {
-             if (EINA_INLIST_GET(n)->next)
-               cur->node = EINA_INLIST_GET(n)->next;
-             else
-               cur->node = n;
-             cur->pos = 0;
-//             cur->eol = 0;
-         }
-       else
-         {
-            cur->node = nc;
-            cur->pos = 0;
-//             cur->eol = 0;
-         }
+        if (data != cur)
+          {
+             if ((n == data->node) &&
+                   (data->pos > start))
+               {
+                  if ((offset < 0) && (data->pos <= (size_t) (-1 * offset)))
+                    {
+                       data->pos = 0;
+                    }
+                  else
+                    {
+                       data->pos += offset;
+                    }
+               }
+          }
      }
+}
+
+/**
+ * @internal
+ * Mark and notifiy that the textblock has changed.
+ *
+ * @param o the textblock object.
+ * @param obj the evas object.
+ */
+static void
+_evas_textblock_changed(Evas_Object_Textblock *o, Evas_Object *obj)
+{
    o->formatted.valid = 0;
    o->native.valid = 0;
    o->changed = 1;
@@ -4126,179 +5517,387 @@ evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *for
        free(o->markup_text);
        o->markup_text = NULL;
      }
-   evas_object_change(cur->obj);
+
+   evas_object_change(obj);
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @return Returns no value.
+ * Adds text to the current cursor position and set the cursor to *before*
+ * the start of the text just added.
+ *
+ * @param cur the cursor to where to add text at.
+ * @param _text the text to add.
+ * @return Returns the len of the text added.
+ * @see evas_textblock_cursor_text_prepend()
  */
-EAPI void
-evas_textblock_cursor_node_delete(Evas_Textblock_Cursor *cur)
+EAPI size_t
+evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *_text)
 {
    Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n, *n2;
+   Evas_Object_Textblock_Node_Text *n;
+   Evas_Object_Textblock_Node_Format *fnode = NULL;
+   Eina_Unicode *text;
+   int len = 0;
 
-   if (!cur) return;
+   if (!cur) return 0;
+   text = evas_common_encoding_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);
+
    n = cur->node;
-   if (eina_strbuf_length_get(n->text) && (!strcmp(eina_strbuf_string_get(n->text), "\n")) &&
-       (!(EINA_INLIST_GET(n))->next)) return;
-   n2 = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(n))->next);
-   if (n2)
+   if (n)
      {
-       cur->node = n2;
-       cur->pos = 0;
+        Evas_Object_Textblock_Node_Format *nnode;
+        if (evas_textblock_cursor_format_is_visible_get(cur))
+          {
+             fnode = _evas_textblock_cursor_node_format_before_pos_get(cur);
+          }
+        else
+          {
+             fnode = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
+             fnode = _evas_textblock_node_format_last_at_off(fnode);
+          }
+        /* find the node after the current in the same paragraph
+         * either we find one and then take the next, or we try to get
+         * the first for the paragraph which must be after our position  */
+        if (fnode)
+          {
+             nnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
+             if (nnode && (nnode->text_node == n))
+               {
+                  fnode = nnode;
+               }
+             else
+               {
+                  fnode = NULL;
+               }
+          }
+        else
+          {
+             fnode = n->format_node;
+          }
      }
    else
      {
-       n2 = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(n))->prev);
-       cur->node = n2;
+        n = _evas_textblock_node_text_new();
+        o->text_nodes = _NODE_TEXT(eina_inlist_append(
+                   EINA_INLIST_GET(o->text_nodes),
+                   EINA_INLIST_GET(n)));
+        cur->node = n;
+     }
+
+   eina_ustrbuf_insert_length(n->unicode, text, len, cur->pos);
+   /* Advance the formats */
+   if (fnode && (fnode->text_node == cur->node))
+     fnode->offset += len;
+#ifdef BIDI_SUPPORT
+   /* Reset paragraph direction */
+   n->bidi_props.direction = EVAS_BIDI_PARAGRAPH_NATURAL;
+   evas_bidi_update_props(eina_ustrbuf_string_get(n->unicode), &n->bidi_props);
+#endif
+   _evas_textblock_changed(o, cur->obj);
+   free(text);
+   return len;
+}
+
+/**
+ * Adds text to the current cursor position and set the cursor to *after*
+ * the start of the text just added.
+ *
+ * @param cur the cursor to where to add text at.
+ * @param _text the text to add.
+ * @return Returns the len of the text added.
+ * @see evas_textblock_cursor_text_append()
+ */
+EAPI size_t
+evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *_text)
+{
+   size_t len;
+   /*append is essentially prepend without advancing */
+   len = evas_textblock_cursor_text_append(cur, _text);
+   cur->pos += len; /*Advance */
+   return len;
+}
+
+/**
+ * @internal
+ * Free a format node
+ *
+ * @prama n the format node to free
+ */
+static void
+_evas_textblock_node_format_free(Evas_Object_Textblock_Node_Format *n)
+{
+   if (!n) return;
+   eina_strbuf_free(n->format);
+   free(n);
+}
+
+/**
+ * @internal
+ * Create a new format node.
+ *
+ * @param format the text to create the format node from.
+ * @return Returns the new format node
+ */
+   static Evas_Object_Textblock_Node_Format *
+_evas_textblock_node_format_new(const char *format)
+{
+   Evas_Object_Textblock_Node_Format *n;
+
+   n = calloc(1, sizeof(Evas_Object_Textblock_Node_Format));
+   n->format = eina_strbuf_new();
+   eina_strbuf_append(n->format, format);
+   n->visible = _evas_textblock_format_is_visible(format);
+
+   return n;
+}
+
+/**
+ * Adds format to the current cursor position. If the format being added is a
+ * visible format, add it *before* the cursor position, otherwise, add it after.
+ * This behavior is because visible formats are like characters and invisible
+ * should be stacked in a way that the last one is added last.
+ *
+ * @param cur the cursor to where to add format at.
+ * @param format the format to add.
+ * @return Returns true if a visible format was added, false otherwise.
+ * @see evas_textblock_cursor_format_prepend()
+ */
+EAPI Eina_Bool
+evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *format)
+{
+   Evas_Object_Textblock *o;
+   Evas_Object_Textblock_Node_Format *n;
+   Eina_Bool is_visible;
+
+   if (!cur) return EINA_FALSE;
+   if ((!format) || (format[0] == 0)) return EINA_FALSE;
+   o = (Evas_Object_Textblock *)(cur->obj->object_data);
+   /* We should always have at least one text node */
+   if (!o->text_nodes)
+     {
+        evas_textblock_cursor_text_prepend(cur, "");
+     }
+
+   n = _evas_textblock_node_format_new(format);
+   is_visible = n->visible;
+   if (!cur->node)
+     {
+       o->format_nodes = _NODE_FORMAT(eina_inlist_append(
+                 EINA_INLIST_GET(o->format_nodes),
+                 EINA_INLIST_GET(n)));
        cur->pos = 0;
-       evas_textblock_cursor_char_last(cur);
+        n->text_node = (EINA_INLIST_GET(n)->prev) ?
+           _NODE_FORMAT(EINA_INLIST_GET(n)->prev)->text_node :
+           o->text_nodes;
+       cur->node = n->text_node;
      }
+   else
+     {
+        Evas_Object_Textblock_Node_Format *fmt;
+        fmt = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
+        n->text_node = cur->node;
+        if (!fmt)
+          {
+             o->format_nodes = _NODE_FORMAT(eina_inlist_prepend(
+                      EINA_INLIST_GET(o->format_nodes),
+                      EINA_INLIST_GET(n)));
+             n->offset = cur->pos;
+          }
+        else
+          {
+             if (evas_textblock_cursor_format_is_visible_get(cur))
+               {
+                  o->format_nodes = _NODE_FORMAT(eina_inlist_prepend_relative(
+                           EINA_INLIST_GET(o->format_nodes),
+                           EINA_INLIST_GET(n),
+                           EINA_INLIST_GET(fmt)
+                           ));
+                  n->offset = fmt->offset;
+                  if (fmt->text_node->format_node == fmt)
+                    {
+                       fmt->text_node->format_node = n;
+                    }
+               }
+             else
+               {
+                  fmt = _evas_textblock_node_format_last_at_off(fmt);
+                  o->format_nodes = _NODE_FORMAT(eina_inlist_append_relative(
+                           EINA_INLIST_GET(o->format_nodes),
+                           EINA_INLIST_GET(n),
+                           EINA_INLIST_GET(fmt)
+                           ));
+                  if (fmt->text_node != cur->node)
+                    {
+                       n->offset = cur->pos;
+                    }
+                  else
+                    {
+                       n->offset = cur->pos -
+                          _evas_textblock_node_format_pos_get(fmt);
+                    }
+               }
+          }
+        /* Adjust differently if we insert a format char */
+        if (is_visible)
+          {
+             _evas_textblock_node_format_adjust_offset(o, cur->node, n, -(n->offset - 1));
+          }
+        else
+          {
+             _evas_textblock_node_format_adjust_offset(o, cur->node, n, -n->offset);
+          }
 
+        if (!fmt || (fmt->text_node != cur->node))
+          {
+             cur->node->format_node = n;
+          }
+     }
+   if (is_visible)
      {
-       Eina_List *l;
-       Evas_Textblock_Cursor *data;
+        eina_ustrbuf_insert_char(cur->node->unicode,
+              EVAS_TEXTBLOCK_REPLACEMENT_CHAR, cur->pos);
 
-       if (cur != o->cursor)
-         {
-            if (n == o->cursor->node)
-              {
-                 o->cursor->node = cur->node;
-                 o->cursor->pos = cur->pos;
-                  o->cursor->eol = cur->eol;
-              }
-         }
-       EINA_LIST_FOREACH(o->cursors, l, data)
-         {
-            if (data != cur)
-              {
-                 if (n == data->node)
-                   {
-                      data->node = cur->node;
-                      data->pos = cur->pos;
-                       data->eol = cur->eol;
-                   }
-              }
-         }
+        /* Advance all the cursors after our cursor */
+        _evas_textblock_cursors_update_offset(cur, cur->node, cur->pos, 1);
      }
 
-   o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n));
-   if (n->text) eina_strbuf_free(n->text);
-   free(n);
+   if (_IS_PARAGRAPH_SEPARATOR(format))
+     {
+        _evas_textblock_cursor_break_paragraph(cur, n);
+     }
 
-   if (n2) _nodes_adjacent_merge(cur->obj, n2);
+    _evas_textblock_changed(o, cur->obj);
 
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   if (o->markup_text)
+   return is_visible;
+}
+
+/**
+ * Adds format to the current cursor position. If the format being added is a
+ * visible format, add it *before* the cursor position, otherwise, add it after.
+ * This behavior is because visible formats are like characters and invisible
+ * should be stacked in a way that the last one is added last.
+ * If the format is visible the cursor is advanced after it.
+ *
+ * @param cur the cursor to where to add format at.
+ * @param format the format to add.
+ * @return Returns true if a visible format was added, false otherwise.
+ * @see evas_textblock_cursor_format_prepend()
+ */
+EAPI Eina_Bool
+evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *format)
+{
+   Eina_Bool is_visible;
+   /* append is essentially prepend without advancing */
+   is_visible = evas_textblock_cursor_format_append(cur, format);
+   if (is_visible)
      {
-       free(o->markup_text);
-       o->markup_text = NULL;
+        /* Advance after the replacement char */
+        evas_textblock_cursor_char_next(cur);
      }
-   evas_object_change(cur->obj);
+
+   return is_visible;
 }
 
+
 /**
- * to be documented.
- * @param cur to be documented.
+ * Delete the character at the location of the cursor. If there's a format
+ * pointing to this position, delete it as well.
+ *
+ * @param cur the cursor pointing to the current location.
  * @return Returns no value.
  */
 EAPI void
 evas_textblock_cursor_char_delete(Evas_Textblock_Cursor *cur)
 {
    Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n, *n2;
+   Evas_Object_Textblock_Node_Text *n, *n2;
+   int merge_nodes = 0;
+   const Eina_Unicode *text;
    int chr, index, ppos;
 
    if (!cur) return;
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
    n = cur->node;
-   if (n->type == NODE_FORMAT)
-     {
-       evas_textblock_cursor_node_delete(cur);
-       return;
-     }
+
+   text = eina_ustrbuf_string_get(n->unicode);
    index = cur->pos;
-   chr = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n->text), &index);
+   chr = GET_NEXT(text, index);
    if (chr == 0) return;
    ppos = cur->pos;
-   eina_strbuf_remove(n->text, cur->pos, index);
-   if (!eina_strbuf_length_get(n->text))
+   /* Remove a format node if needed, and remove the char only if the
+    * fmt node is not visible */
      {
-       evas_textblock_cursor_node_delete(cur);
-       return;
+        Evas_Object_Textblock_Node_Format *fmt;
+        fmt = _evas_textblock_cursor_node_format_at_pos_get(cur);
+        if (fmt)
+          {
+             const char *format = NULL;
+             Evas_Object_Textblock_Node_Format *itr;
+             itr = fmt;
+             do
+               {
+                  format = eina_strbuf_string_get(fmt->format);
+                  if (format && _IS_PARAGRAPH_SEPARATOR(format))
+                    {
+                       merge_nodes = 1;
+                    }
+                  itr = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
+               }
+             while (itr && (itr->text_node == fmt->text_node) &&
+                   (itr->offset == 0));
+             _evas_textblock_node_format_remove_all_at_pos(o, fmt);
+          }
+        /* If the format node is not visible (because visible nodes adjust
+         * automatically when removing them) adjust */
+        if (!evas_textblock_cursor_format_is_visible_get(cur))
+          {
+             fmt = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
+             fmt = _evas_textblock_node_format_last_at_off(fmt);
+             _evas_textblock_node_format_adjust_offset(o, cur->node, fmt,
+                   -(index - cur->pos));
+          }
      }
-   if (cur->pos == eina_strbuf_length_get(n->text))
+   eina_ustrbuf_remove(n->unicode, cur->pos, index);
+   /* If it was a paragraph separator, we should merge the current with the
+    * next, there must be a next. */
+   if (merge_nodes)
      {
-       n2 = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(n))->next);
-       if (n2)
-         {
-            cur->node = n2;
-            cur->pos = 0;
-         }
-       else
-         {
-            cur->pos = 0;
-            evas_textblock_cursor_char_last(cur);
-         }
+        _evas_textblock_cursor_nodes_merge(cur);
      }
 
+   if (cur->pos == eina_ustrbuf_length_get(n->unicode))
      {
-       Eina_List *l;
-       Evas_Textblock_Cursor *data;
-
-       if (cur != o->cursor)
-         {
-            if ((n == o->cursor->node) &&
-                (o->cursor->pos > ppos))
-              {
-                 o->cursor->pos -= (index - ppos);
-              }
-         }
-       EINA_LIST_FOREACH(o->cursors, l, data)
+       n2 = _NODE_TEXT(EINA_INLIST_GET(n)->next);
+       if (n2)
          {
-            if (data != cur)
-              {
-                 if ((n == data->node) &&
-                     (data->pos > ppos))
-                   {
-                      data->pos -= (index - ppos);
-                   }
-              }
+            cur->node = n2;
+            cur->pos = 0;
          }
      }
 
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   if (o->markup_text)
-     {
-       free(o->markup_text);
-       o->markup_text = NULL;
-     }
-   evas_object_change(cur->obj);
+   _evas_textblock_cursors_update_offset(cur, n, ppos, -(index - ppos));
+   _evas_textblock_changed(o, cur->obj);
 }
 
 /**
- * to be documented.
- * @param cur1 to be documented.
- * @param cur2 to be documented.
+ * Delete the range between cur1 and cur2.
+ *
+ * @param cur1 one side of the range.
+ * @param cur2 the second side of the range
  * @return Returns no value.
  */
 EAPI void
 evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_Cursor *cur2)
 {
    Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n1, *n2, *n, *tn;
-   int chr, index;
+   Evas_Object_Textblock_Node_Text *n1, *n2, *n;
+   Evas_Object_Textblock_Node_Format *fnode = NULL;
 
-   if (!cur1) return;
-   if (!cur2) return;
+   if (!cur1 || !cur1->node) return;
+   if (!cur2 || !cur2->node) return;
    if (cur1->obj != cur2->obj) return;
    o = (Evas_Object_Textblock *)(cur1->obj->object_data);
    if (evas_textblock_cursor_compare(cur1, cur2) > 0)
@@ -4311,508 +5910,321 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C
      }
    n1 = cur1->node;
    n2 = cur2->node;
-   if ((!n1) || (!n2)) return;
-   index = cur2->pos;
-   chr = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n2->text), &index);
-// XXX: why was this added? this stops sel to end and 
-//   if (chr == 0) return;
+   cur2->pos++; /* Also remove the marked char */
+
+   /* Find the first format node after cur2 */
+   fnode = _evas_textblock_cursor_node_format_before_pos_get(cur2);
+     {
+        if (fnode)
+          {
+             fnode = _evas_textblock_node_format_last_at_off(fnode);
+             Evas_Object_Textblock_Node_Text *tnode;
+             tnode = fnode->text_node;
+             fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
+             if (fnode && (tnode != fnode->text_node))
+               {
+                  fnode = NULL;
+               }
+          }
+        else
+          {
+             fnode = cur2->node->format_node;
+             if (fnode && (cur2->node != fnode->text_node))
+               {
+                  fnode = NULL;
+               }
+          }
+     }
    if (n1 == n2)
      {
-        if (n1->type == NODE_TEXT)
-         {
-           if (cur1->pos == cur2->pos)
-              {
-                 evas_textblock_cursor_char_delete(cur1);
-                 evas_textblock_cursor_copy(cur1, cur2);
-                 return;
-              }
-            eina_strbuf_remove(n1->text, cur1->pos, index);
-            if (!eina_strbuf_length_get(n1->text))
-              {
-                 evas_textblock_cursor_node_delete(cur1);
-                 evas_textblock_cursor_copy(cur1, cur2);
-                 return;
-              }
-            if (cur1->pos >= eina_strbuf_length_get(n1->text))
-              {
-                 n2 = (Evas_Object_Textblock_Node *)((EINA_INLIST_GET(n1))->next);
-                 if (n2)
-                   {
-                      cur1->node = n2;
-                      cur1->pos = 0;
-                   }
-                 else
-                   {
-                      cur1->pos = 0;
-                      evas_textblock_cursor_char_last(cur1);
-                   }
-              }
-         }
-       else
-         evas_textblock_cursor_node_delete(cur1);
-       evas_textblock_cursor_copy(cur1, cur2);
+        _evas_textblock_node_text_remove_formats_between(o, n1, cur1->pos,
+              cur2->pos);
+        eina_ustrbuf_remove(n1->unicode, cur1->pos, cur2->pos);
+        if (fnode && (fnode->text_node == n1))
+          {
+             fnode->offset -= cur2->pos - cur1->pos;
+          }
+        _evas_textblock_cursors_update_offset(cur1, cur1->node, cur1->pos, - (cur2->pos - cur1->pos));
      }
    else
      {
-       Eina_List *removes, *format_hump = NULL;
-       Evas_Textblock_Cursor tcur;
-       Eina_Inlist *l;
+        int len;
+        n = _NODE_TEXT(EINA_INLIST_GET(n1)->next);
+        /* Remove all the text nodes between */
+        while (n && (n != n2))
+          {
+             Evas_Object_Textblock_Node_Text *nnode;
 
-       tcur.node = n2;
-       tcur.pos = 0;
-       index = cur2->pos;
-       chr = evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n2->text), &index);
-       if ((chr == 0) || (index >= eina_strbuf_length_get(n2->text)))
-         {
-            tcur.node = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n2))->next;
-            tcur.pos = 0;
-            if (!tcur.node)
-              {
-                 if (cur1->pos != 0)
-                   {
-                      tcur.node = n1;
-                      index = cur1->pos;
-                      chr = evas_common_font_utf8_get_prev((unsigned char *)eina_strbuf_string_get(n2->text), &index);
-                      tcur.pos = index;
-                   }
-                 else
-                   {
-                      tcur.node = (Evas_Object_Textblock_Node *)(EINA_INLIST_GET(n1))->prev;
-                      if ((tcur.node) && (tcur.node->type == NODE_TEXT))
-                        tcur.pos = evas_common_font_utf8_get_last((unsigned char *)eina_strbuf_string_get(tcur.node->text), eina_strbuf_length_get(tcur.node->text));
-                      else
-                        tcur.pos = 0;
-                   }
-              }
-         }
-       eina_strbuf_remove(n1->text, cur1->pos, eina_strbuf_length_get(n1->text));
-       removes = NULL;
-       for (l = (EINA_INLIST_GET(n1))->next; l != EINA_INLIST_GET(n2); l = l->next)
-         removes = eina_list_append(removes, l);
-       format_hump = NULL;
-       if (n1->type == NODE_TEXT)
-         {
-            if (!eina_strbuf_length_get(n1->text))
-              evas_textblock_cursor_node_delete(cur1);
-         }
-       else
-         {
-            if (eina_strbuf_length_get(n1->text) && (eina_strbuf_string_get(n1->text)[0] == '+'))
-              format_hump = eina_list_append(format_hump, n1);
-            else
-              {
-                  o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n1));
-                 if (n1->text) eina_strbuf_free(n1->text);
-                 free(n1);
-              }
-         }
-       while (removes)
-         {
-            n = removes->data;
-            if (n->type == NODE_TEXT)
-              {
-                 o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes), EINA_INLIST_GET(n));
-                 if (n->text) eina_strbuf_free(n->text);
-                 free(n);
-              }
-            else
-              {
-                 if (eina_strbuf_string_get(n->text)[0] == '+')
-                   {
-                      format_hump = eina_list_append(format_hump, n);
-                   }
-                 else if (eina_strbuf_string_get(n->text)[0] == '-')
-                   {
-                      tn = eina_list_data_get(eina_list_last(format_hump));
-                      if (tn)
-                        {
-                           format_hump = eina_list_remove_list(format_hump, eina_list_last(format_hump));
-                           o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes),
-                                                                                       EINA_INLIST_GET(tn));
-                           if (tn->text) eina_strbuf_free(tn->text);
-                           free(tn);
-                           o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes),
-                                                                                       EINA_INLIST_GET(n));
-                           if (n->text) eina_strbuf_free(n->text);
-                           free(n);
-                        }
-                   }
-                 else
-                   {
-                      o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes),
-                                                                                  EINA_INLIST_GET(n));
-                      if (n->text) eina_strbuf_free(n->text);
-                      free(n);
-                   }
-              }
-            removes = eina_list_remove_list(removes, removes);
-         }
-        if (n2->type == NODE_TEXT)
-         {
-            eina_strbuf_remove(n2->text, 0, index);
-            if (!eina_strbuf_length_get(n2->text))
-              evas_textblock_cursor_node_delete(cur2);
-         }
-       else
-         {
-            if (tcur.node == n2)
-              {
-                 if ((EINA_INLIST_GET(n2))->next)
-                   {
-                      tcur.node = (Evas_Object_Textblock_Node *) (EINA_INLIST_GET(n2))->next;
-                      tcur.pos = 0;
-                   }
-                 else
-                   {
-                      tcur.node = (Evas_Object_Textblock_Node *) (EINA_INLIST_GET(n2))->next;
-                      if (tcur.node)
-                        {
-                           if (tcur.node->type == NODE_TEXT)
-                             tcur.pos = evas_common_font_utf8_get_last((unsigned char *)eina_strbuf_string_get(tcur.node->text), eina_strbuf_length_get(tcur.node->text));
-                           else
-                             tcur.pos = 0;
-                        }
-                   }
-              }
-            if (eina_strbuf_string_get(n2->text)[0] == '-')
-              {
-                 o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes),
-                                                                             EINA_INLIST_GET(n2));
-                 if (n2->text) eina_strbuf_free(n2->text);
-                 free(n2);
-                 n = eina_list_data_get(eina_list_last(format_hump));
-                 if (n)
-                   {
-                      if (tcur.node == n)
-                        {
-                           if ((EINA_INLIST_GET(n))->next)
-                             {
-                                tcur.node = (Evas_Object_Textblock_Node *) (EINA_INLIST_GET(n))->next;
-                                tcur.pos = 0;
-                             }
-                           else
-                             {
-                                tcur.node = (Evas_Object_Textblock_Node *) (EINA_INLIST_GET(n))->next;
-                                if (tcur.node)
-                                  {
-                                     if (tcur.node->type == NODE_TEXT)
-                                       tcur.pos = evas_common_font_utf8_get_last((unsigned char *)eina_strbuf_string_get(tcur.node->text), eina_strbuf_length_get(tcur.node->text));
-                                     else
-                                       tcur.pos = 0;
-                                  }
-                             }
-                        }
-                      o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes),
-                                                                                  EINA_INLIST_GET(n));
-                      if (n->text) eina_strbuf_free(n->text);
-                      free(n);
-                   }
-              }
-            else
-              {
-                 o->nodes = (Evas_Object_Textblock_Node *)eina_inlist_remove(EINA_INLIST_GET(o->nodes),
-                                                                             EINA_INLIST_GET(n2));
-                 if (n2->text) eina_strbuf_free(n2->text);
-                 free(n2);
-              }
-         }
-       if (format_hump) eina_list_free(format_hump);
-       cur1->node = tcur.node;
-       cur1->pos = tcur.pos;
-       cur2->node = tcur.node;
-       cur2->pos = tcur.pos;
-     }
+             nnode = _NODE_TEXT(EINA_INLIST_GET(n)->next);
+             _evas_textblock_node_text_remove(o, n);
+             n = nnode;
+          }
 
-   /* FIXME: adjust cursors that are affected by the change */
-   /* this is temporary just avoiding segv's - it sets all other cursors to
-    * the same pos as cur1 and cur2
-    */
+        /* Remove the formats and the strings in the first and last nodes */
+        len = eina_ustrbuf_length_get(n1->unicode);
+        _evas_textblock_node_text_remove_formats_between(o, n1, cur1->pos,
+              len);
+        _evas_textblock_node_text_remove_formats_between(o, n2, 0, cur2->pos);
+        eina_ustrbuf_remove(n1->unicode, cur1->pos, len);
+        eina_ustrbuf_remove(n2->unicode, 0, cur2->pos);
+        if (fnode && (fnode->text_node == n2))
+          {
+             fnode->offset -= cur2->pos;
+          }
+        /* Merge the nodes because we removed the PS */
+        _evas_textblock_nodes_merge(o, n1, n2);
+        _evas_textblock_cursors_update_offset(cur1, cur1->node, cur1->pos, - cur1->pos);
+        _evas_textblock_cursors_update_offset(cur2, cur2->node, 0, - cur2->pos);
+     }
+   evas_textblock_cursor_copy(cur1, cur2);
+   evas_textblock_cursor_copy(cur1, o->cursor);
+   _evas_textblock_changed(o, cur1->obj);
+}
+
+/**
+ * Return the text in the range between cur1 and cur2
+ *
+ * FIXME: format is currently unused, you always get markup back.
+ *
+ * @param cur1 one side of the range.
+ * @param cur2 the other side of the range
+ * @param format to be documented
+ * @return the text in the range
+ * @see elm_entry_markup_to_utf8()
+ */
+EAPI char *
+evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *_cur2, Evas_Textblock_Text_Type format __UNUSED__)
+{
+   Evas_Object_Textblock *o;
+   Evas_Object_Textblock_Node_Text *n1, *n2, *tnode;
+   Eina_Strbuf *buf;
+   Evas_Textblock_Cursor *cur2;
+   buf = eina_strbuf_new();
+
+   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 (evas_textblock_cursor_compare(cur1, _cur2) > 0)
      {
-       Eina_List *l;
-       Evas_Textblock_Cursor *data;
+       const Evas_Textblock_Cursor *tc;
 
-       if ((cur1 != o->cursor) && (cur2 != o->cursor))
-         {
-            evas_textblock_cursor_copy(cur1, o->cursor);
-         }
-       EINA_LIST_FOREACH(o->cursors, l, data)
-         {
-            if ((data != cur1) && (data != cur2))
-              {
-                 evas_textblock_cursor_copy(cur1, data);
-              }
-         }
+       tc = cur1;
+       cur1 = _cur2;
+       _cur2 = tc;
      }
-   if (cur1->node) _nodes_adjacent_merge(cur1->obj, cur1->node);
-   if (cur2->node) _nodes_adjacent_merge(cur2->obj, cur2->node);
-
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   if (o->markup_text)
+   n1 = cur1->node;
+   n2 = _cur2->node;
+   /* Work on a local copy of the cur */
+   cur2 = alloca(sizeof(Evas_Textblock_Cursor));
+   cur2->obj = _cur2->obj;
+   evas_textblock_cursor_copy(_cur2, cur2);
+   if (cur2->pos < eina_ustrbuf_length_get(cur2->node->unicode))
+     {
+        /* We want to also copy the pointed to char, only if it's not
+         * the terminating null. */
+        cur2->pos++;
+     }
+   /* Parse the text between the cursors. */
+   for (tnode = cur1->node ; tnode ;
+         tnode = _NODE_TEXT(EINA_INLIST_GET(tnode)->next))
+     {
+        Evas_Object_Textblock_Node_Format *fnode;
+        Eina_Unicode *text_base, *text;
+        int off;
+
+        text_base = text =
+           eina_unicode_strdup(eina_ustrbuf_string_get(tnode->unicode));
+        if (tnode == cur2->node)
+          {
+             fnode = _evas_textblock_node_text_get_first_format_between(tnode,
+                   cur1->pos, cur2->pos);
+          }
+        else if (tnode == cur1->node)
+          {
+             fnode = _evas_textblock_node_text_get_first_format_between(tnode,
+                   cur1->pos, -1);
+          }
+        else
+          {
+             fnode = _evas_textblock_node_text_get_first_format_between(tnode,
+                   0, -1);
+          }
+        /* Init the offset so the first one will count starting from cur1->pos
+         * and not the previous format node */
+        if ((tnode == cur1->node) && fnode)
+          {
+             off = _evas_textblock_node_format_pos_get(fnode) - cur1->pos - fnode->offset;
+             text += cur1->pos;
+          }
+        else
+          {
+             off = 0;
+          }
+        while (fnode && (fnode->text_node == tnode))
+          {
+             Eina_Unicode tmp_ch;
+             off += fnode->offset;
+             if ((tnode == cur2->node) && ((size_t) (text - text_base + off) >= cur2->pos))
+               {
+                  break;
+               }
+             /* No need to skip on the first run */
+             tmp_ch = text[off];
+             text[off] = 0; /* Null terminate the part of the string */
+             _markup_get_text_append(buf, text);
+             _markup_get_format_append(o, buf, fnode);
+             text[off] = tmp_ch; /* Restore the char */
+             text += off;
+             if (fnode->visible)
+               {
+                  off = -1;
+                  text++;
+               }
+             else
+               {
+                  off = 0;
+               }
+             fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
+          }
+        /* If we got to the last node, stop and add the rest outside */
+        if (cur2->node == tnode)
+          {
+             /* Add the rest, skip replacement */
+             /* Don't go past the second cursor pos */
+             text_base[cur2->pos] = '\0';
+             _markup_get_text_append(buf, text);
+             free(text_base);
+             break;
+          }
+        else
+          {
+             /* Add the rest, skip replacement */
+             _markup_get_text_append(buf, text);
+             free(text_base);
+          }
+     }
+   /* return the string */
      {
-       free(o->markup_text);
-       o->markup_text = NULL;
+        char *ret;
+        ret = eina_strbuf_string_steal(buf);
+        eina_strbuf_free(buf);
+        return ret;
      }
-   evas_object_change(cur1->obj);
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @return to be documented.
+ * Return the text of the paragraph cur points to - returns the text in markup..
+ *
+ * @param cur the cursor pointing to the paragraph.
+ * @return the text on success, NULL otherwise.
  */
 EAPI const char *
-evas_textblock_cursor_node_text_get(const Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_paragraph_text_get(const Evas_Textblock_Cursor *cur)
 {
+   Evas_Textblock_Cursor cur1, cur2;
    if (!cur) return NULL;
    if (!cur->node) return NULL;
-   if (cur->node->type == NODE_TEXT)
+   if (cur->node->utf8)
      {
-       return eina_strbuf_string_get(cur->node->text);
+        free(cur->node->utf8);
      }
-   return NULL;
+   cur1.obj = cur2.obj = cur->obj;
+   cur1.node = cur2.node = cur->node;
+   evas_textblock_cursor_paragraph_char_first(&cur1);
+   evas_textblock_cursor_paragraph_char_last(&cur2);
+
+   cur->node->utf8 = evas_textblock_cursor_range_text_get(&cur1, &cur2,
+         EVAS_TEXTBLOCK_TEXT_MARKUP);
+   return cur->node->utf8;
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @return to be documented.
+ * Return the length of the paragraph, cheaper the eina_unicode_strlen()
+ *
+ * @param cur the position of the paragraph.
+ * @return the length of the paragraph on success, -1 otehrwise.
  */
 EAPI int
-evas_textblock_cursor_node_text_length_get(const Evas_Textblock_Cursor *cur)
+evas_textblock_cursor_paragraph_text_length_get(const Evas_Textblock_Cursor *cur)
 {
-   if (!cur) return 0;
-   if (!cur->node) return 0;
-   if (cur->node->type == NODE_TEXT)
-     {
-       return eina_strbuf_length_get(cur->node->text);
-     }
-   return 0;
+   if (!cur) return -1;
+   if (!cur->node) return -1;
+   return eina_ustrbuf_length_get(cur->node->unicode);
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @return to be documented.
+ * Return the format node at the position pointed by cur.
+ *
+ * @param cur the position to look at.
+ * @return the format node if found, NULL otherwise.
+ * @see evas_textblock_cursor_format_is_visible_get()
  */
-EAPI const char *
-evas_textblock_cursor_node_format_get(const Evas_Textblock_Cursor *cur)
+EAPI const Evas_Object_Textblock_Node_Format *
+evas_textblock_cursor_format_get(const Evas_Textblock_Cursor *cur)
 {
    if (!cur) return NULL;
    if (!cur->node) return NULL;
-   if (cur->node->type == NODE_FORMAT)
-     {
-       return eina_strbuf_string_get(cur->node->text);
-     }
-   return NULL;
+   return _evas_textblock_cursor_node_format_at_pos_get(cur);
 }
-
 /**
- * to be documented.
- * @param cur to be documented.
- * @return to be documented.
+ * Get the text format representation of the format node.
+ *
+ * @param fmt the format node.
+ * @return the textual format of the format node.
  */
-EAPI Eina_Bool
-evas_textblock_cursor_node_format_is_visible_get(const Evas_Textblock_Cursor *cur)
+EAPI const char *
+evas_textblock_node_format_text_get(const Evas_Object_Textblock_Node_Format *fmt)
 {
-   Evas_Object_Textblock_Node *n;
-
-   if (!cur) return EINA_FALSE;
-   n = cur->node;
-   if (!n) return EINA_FALSE;
-   if (n->type != NODE_FORMAT) return EINA_FALSE;
-   if (!eina_strbuf_length_get(n->text)) return EINA_FALSE;
-     {
-       char *s;
-       char *item;
-       int visible = 0;
-
-       s = (char *)eina_strbuf_string_get(n->text);
-       if (s[0] == '+' || s[0] == '-')
-         {
-            s++;
-         }
-       while ((item = _format_parse(&s)))
-         {
-            char tmp_delim = *s;
-            *s = '\0';
-            if ((!strcmp(item, "\n")) || (!strcmp(item, "\\n")))
-              visible = 1;
-            else if ((!strcmp(item, "\t")) || (!strcmp(item, "\\t")))
-              visible = 1;
-            *s = tmp_delim;
-            if (visible) return EINA_TRUE;
-         }
-     }
-   return EINA_FALSE;
+   if (!fmt) return NULL;
+   return eina_strbuf_string_get(fmt->format);
 }
 
 /**
- * to be documented.
- * @param cur1 to be documented.
- * @param cur2 to be documented.
- * @param format to be documented.
- * @return to be documented.
+ * Set the cursor to point to the position of fmt.
+ *
+ * @param cur the cursor to update
+ * @param fmt the format to update according to.
  */
-EAPI char *
-evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2, Evas_Textblock_Text_Type format)
+EAPI void
+evas_textblock_cursor_at_format_set(Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Format *fmt)
 {
-   Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n1, *n2, *n;
-   Eina_Strbuf *txt;
-   char *s, *ret;
-   int index;
-
-   if (!cur1) return NULL;
-   if (!cur2) return NULL;
-   if (cur1->obj != cur2->obj) return NULL;
-   o = (Evas_Object_Textblock *)(cur1->obj->object_data);
-   if (evas_textblock_cursor_compare(cur1, cur2) > 0)
-     {
-       const Evas_Textblock_Cursor *tc;
+   if (!fmt || !cur) return;
+   cur->node = fmt->text_node;
+   cur->pos = _evas_textblock_node_format_pos_get(fmt);
+}
 
-       tc = cur1;
-       cur1 = cur2;
-       cur2 = tc;
-     }
-   n1 = cur1->node;
-   n2 = cur2->node;
-   index = cur2->pos;
-   if ((!n1) || (!n2)) return NULL;
-   if (n2->text)
-     evas_common_font_utf8_get_next((unsigned char *)eina_strbuf_string_get(n2->text), &index);
-   txt = eina_strbuf_new();
-   EINA_INLIST_FOREACH(n1, n)
-     {
-       if ((n->type == NODE_TEXT) && (n->text))
-         {
-            s = (char *)eina_strbuf_string_get(n->text);
-            if (format == EVAS_TEXTBLOCK_TEXT_MARKUP)
-              {
-                 const char *p, *ps, *pe;
+/**
+ * Check if the current cursor position is a visible format. This way is more
+ * efficient than evas_textblock_cursor_format_get() to check for the existence
+ * of a visible format.
+ *
+ * @param cur the cursor to look at.
+ * @return #EINA_TRUE if the cursor points to a visible format, #EINA_FALSE otherwise.
+ * @see evas_textblock_cursor_format_get()
+ */
+EAPI Eina_Bool
+evas_textblock_cursor_format_is_visible_get(const Evas_Textblock_Cursor *cur)
+{
+   const Eina_Unicode *text;
 
-                 if (eina_strbuf_length_get(n->text))
-                   {
-                      if ((n == n1) && (n == n2))
-                        {
-                           ps = eina_strbuf_string_get(n->text) + cur1->pos;
-                           pe = ps + index - cur1->pos;
-                        }
-                      else if (n == n1)
-                        {
-                           ps = eina_strbuf_string_get(n->text) + cur1->pos;
-                           pe = ps + strlen(ps);
-                        }
-                      else if (n == n2)
-                        {
-                           ps = eina_strbuf_string_get(n->text);
-                           pe = ps + cur2->pos + 1;
-                        }
-                      else
-                        {
-                           ps = eina_strbuf_string_get(n->text);
-                           pe = ps + strlen(ps);
-                        }
-                      p = ps;
-                      while (p < pe)
-                        {
-                           const char *escape;
-                           int adv;
-
-                            if (!*p) break;
-                           escape = _escaped_char_match(p, &adv);
-                           if (escape)
-                             {
-                                p += adv;
-                                eina_strbuf_append(txt, escape);
-                             }
-                           else
-                             {
-                                eina_strbuf_append_char(txt, *p);
-                                p++;
-                             }
-                        }
-                   }
-              }
-            else
-              {
-                 if ((n == n1) && (n == n2))
-                   {
-                      s += cur1->pos;
-                      eina_strbuf_append_n(txt, s, index - cur1->pos);
-                   }
-                 else if (n == n1)
-                   {
-                      s += cur1->pos;
-                      eina_strbuf_append(txt, s);
-                   }
-                 else if (n == n2)
-                   {
-                      eina_strbuf_append_n(txt, s, index);
-                   }
-                 else
-                   {
-                      eina_strbuf_append(txt, s);
-                   }
-              }
-         }
-       else if (n->text)
-         {
-            if (format == EVAS_TEXTBLOCK_TEXT_PLAIN)
-              {
-                 s = (char *)eina_strbuf_string_get(n->text);
-                 while (*s)
-                   {
-                      if (*s == '\n')
-                        eina_strbuf_append_char(txt, '\n');
-                      else if (*s == '\t')
-                        eina_strbuf_append_char(txt, '\t');
-                      s++;
-                   }
-              }
-            else if (format == EVAS_TEXTBLOCK_TEXT_MARKUP)
-              {
-                 size_t tag_len, replace_len = eina_strbuf_length_get(n->text);
-                 const char *tag = _style_match_replace(o->style, eina_strbuf_string_get(n->text), replace_len, &tag_len);
-                 eina_strbuf_append_char(txt, '<');
-                 if (tag)
-                   {
-                      // FIXME: need to escape
-                      eina_strbuf_append_length(txt, tag, tag_len);
-                   }
-                 else
-                   {
-                      int push = 0;
-                      int pop = 0;
-
-                      // FIXME: need to escape
-                      s = (char *)eina_strbuf_string_get(n->text);
-                      if (*s == '+') push = 1;
-                      if (*s == '-') pop = 1;
-                      while ((*s == ' ') || (*s == '+') || (*s == '-')) s++;
-                      if (pop) eina_strbuf_append_char(txt, '/');
-                      if (push) eina_strbuf_append(txt, "+ ");
-                      eina_strbuf_append(txt, s);
-                   }
-                 eina_strbuf_append_char(txt, '>');
-              }
-         }
-       if (n == n2) break;
-     }
-   ret = eina_strbuf_string_steal(txt);
-   eina_strbuf_free(txt);
-   return ret;
+   if (!cur) return EINA_FALSE;
+   if (!cur->node) return EINA_FALSE;
+   text = eina_ustrbuf_string_get(cur->node->unicode);
+   return (text[cur->pos] == EVAS_TEXTBLOCK_REPLACEMENT_CHAR) ?
+              EINA_TRUE : EINA_FALSE;
 }
 
+
 /**
- * to be documented.
- * @param cur to be documented.
- * @param cx to be documented.
- * @param cy to be documented.
- * @param cw to be documented.
- * @param ch to be documented.
- * @return to be documented.
+ * 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)
@@ -4828,9 +6240,10 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
    if (!cur->node)
      {
-        if (!o->nodes)
+        if (!o->text_nodes)
           {
-             ln = o->lines;
+             if (!o->paragraphs) return -1;
+             ln = o->paragraphs->lines;
              if (!ln) return -1;
              if (cx) *cx = ln->x;
              if (cy) *cy = ln->y;
@@ -4842,13 +6255,16 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C
           return -1;
      }
    if (!o->formatted.valid) _relayout(cur->obj);
-   if (cur->node->type == NODE_FORMAT)
+   if (evas_textblock_cursor_format_is_visible_get(cur))
      {
-       _find_layout_format_item_line_match(cur->obj, cur->node, &ln, &fi);
+        _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
      {
-       _find_layout_item_line_match(cur->obj, cur->node, cur->pos, cur->eol, &ln, &it);
+        _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it);
      }
    if (!ln)
      {
@@ -4856,30 +6272,25 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C
      }
    if (it)
      {
-       pos = cur->pos - it->source_pos;
-       ret = -1;
-        if (cur->eol)
-          {
-             int pos2;
+        pos = cur->pos - it->source_pos;
+        ret = -1;
 
-             pos2 = pos;
-             evas_common_font_utf8_get_next((unsigned char *)(it->text), &pos2);
-             if (pos2 > pos) pos = pos2;
-          }
         if (pos < 0) pos = 0;
-       if (it->format->font.font)
-         ret = cur->ENFN->font_char_coords_get(cur->ENDT, it->format->font.font,
-                                               it->text,
-                                               pos,
-                                               &x, &y, &w, &h);
-       if (ret <= 0)
-         {
-            if (it->format->font.font)
-               cur->ENFN->font_string_size_get(cur->ENDT, it->format->font.font,
-                                               it->text, &w, &h);
-            x = w;
-            y = 0;
-            w = 0;
+        if (it->format->font.font) 
+          {
+             ret = cur->ENFN->font_char_coords_get(cur->ENDT, it->format->font.font,
+                   it->text, &it->bidi_props,
+                   pos,
+                   &x, &y, &w, &h);
+          }
+        if (ret <= 0)
+          {
+             if (it->format->font.font)
+               cur->ENFN->font_string_size_get(cur->ENDT, it->format->font.font,
+                     it->text, &it->bidi_props, &w, &h);
+             x = w;
+             y = 0;
+             w = 0;
          }
        x = ln->x + it->x - it->inset + x;
        if (x < ln->x)
@@ -4909,13 +6320,14 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @param cx to be documented.
- * @param cy to be documented.
- * @param cw to be documented.
- * @param ch to be documented.
- * @return to be documented.
+ * Returns the geometry of the line at cur.
+ *
+ * @param cur the position of the line.
+ * @param cx the x of the line.
+ * @param cy the y of the line.
+ * @param cw the w of the line.
+ * @param ch the h of the line.
+ * @return line number of the line on success, -1 on error.
  */
 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)
@@ -4931,14 +6343,21 @@ evas_textblock_cursor_line_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C
    if (!o->formatted.valid) _relayout(cur->obj);
    if (!cur->node)
      {
-        ln = o->lines;
+        ln = o->paragraphs->lines;
      }
    else
      {
-        if (cur->node->type == NODE_FORMAT)
-          _find_layout_format_item_line_match(cur->obj, cur->node, &ln, &fi);
+        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
-          _find_layout_item_line_match(cur->obj, cur->node, cur->pos, cur->eol, &ln, &it);
+          {
+             _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it);
+          }
      }
    if (!ln) return -1;
    x = ln->x;
@@ -4953,11 +6372,12 @@ evas_textblock_cursor_line_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @param x to be documented.
- * @param y to be documented.
- * @return to be documented.
+ * 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)
@@ -4972,7 +6392,7 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, E
    if (!o->formatted.valid) _relayout(cur->obj);
    x += o->style_pad.l;
    y += o->style_pad.t;
-   EINA_INLIST_FOREACH(o->lines, ln)
+   EINA_INLIST_FOREACH(o->paragraphs->lines, ln)
      {
        if (ln->y > y) break;
        if ((ln->y <= y) && ((ln->y + ln->h) > y))
@@ -4991,11 +6411,11 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, E
 
                       pos = -1;
                       if (it->format->font.font)
-                        pos = cur->ENFN->font_char_at_coords_get(cur->ENDT,
-                                                                 it->format->font.font,
-                                                                 it->text,
-                                                                 x - it->x - ln->x, 0,
-                                                                 &cx, &cy, &cw, &ch);
+                         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;
@@ -5008,9 +6428,10 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, E
                  if ((fi->x + ln->x) > x) break;
                  if (((fi->x + ln->x) <= x) && (((fi->x + ln->x) + fi->w) > x))
                    {
-                      cur->pos = 0;
-                       cur->eol = 0;
-                      cur->node = fi->source_node;
+                       cur->pos =
+                          _evas_textblock_node_format_pos_get(fi->source_node);
+
+                      cur->node = fi->source_node->text_node;
                       return EINA_TRUE;
                    }
               }
@@ -5018,7 +6439,7 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, E
               {
                  it = it_break;
                  cur->pos = it->source_pos;
-                  cur->eol = 0;
+
                  cur->node = it->source_node;
                  return EINA_TRUE;
               }
@@ -5028,10 +6449,11 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, E
 }
 
 /**
- * to be documented.
- * @param cur to be documented.
- * @param y to be documented.
- * @return to be documented.
+ * 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)
@@ -5043,7 +6465,7 @@ evas_textblock_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y)
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
    if (!o->formatted.valid) _relayout(cur->obj);
    y += o->style_pad.t;
-   EINA_INLIST_FOREACH(o->lines, ln)
+   EINA_INLIST_FOREACH(o->paragraphs->lines, ln)
      {
        if (ln->y > y) break;
        if ((ln->y <= y) && ((ln->y + ln->h) > y))
@@ -5056,10 +6478,11 @@ evas_textblock_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y)
 }
 
 /**
- * to be documented.
- * @param cur1 to be documented.
- * @param cur2 to be documented.
- * @return to be documented.
+ * Get the geometry of a range.
+ *
+ * @param cur1 one side of the range.
+ * @param cur2 other side of the range.
+ * @return a list of Rectangles representing the geometry of the range.
  */
 EAPI Eina_List *
 evas_textblock_cursor_range_geometry_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2)
@@ -5080,12 +6503,14 @@ evas_textblock_cursor_range_geometry_get(const Evas_Textblock_Cursor *cur1, cons
        cur1 = cur2;
        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;
+
    if (line == line2)
      {
        tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
@@ -5170,10 +6595,13 @@ evas_textblock_cursor_format_item_geometry_get(const Evas_Textblock_Cursor *cur,
    Evas_Object_Textblock_Format_Item *fi = NULL;
    Evas_Coord x, y, w, h;
 
-   if (!cur) return 0;
+   if (!cur || !evas_textblock_cursor_format_is_visible_get(cur)) return 0;
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
    if (!o->formatted.valid) _relayout(cur->obj);
-   _find_layout_format_item_line_match(cur->obj, cur->node, &ln, &fi);
+   _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;
@@ -5187,42 +6615,38 @@ evas_textblock_cursor_format_item_geometry_get(const Evas_Textblock_Cursor *cur,
 }
 
 /**
- * To be documented.
- *
- * FIXME: To be fixed.
+ * Checks if the cursor points to the end of the line.
  *
+ * @param cur the cursor to check.
+ * @return #EINA_TRUE if true, #EINA_FALSE otherwise.
  */
 EAPI Eina_Bool
 evas_textblock_cursor_eol_get(const Evas_Textblock_Cursor *cur)
 {
+   Eina_Bool ret = EINA_FALSE;
+   Evas_Textblock_Cursor cur2;
    if (!cur) return EINA_FALSE;
-   return cur->eol;
-}
 
-/**
- * To be documented.
- *
- * FIXME: To be fixed.
- *
- */
-EAPI void
-evas_textblock_cursor_eol_set(Evas_Textblock_Cursor *cur, Eina_Bool eol)
-{
-   if (!cur) return;
-   cur->eol = eol;
+   evas_textblock_cursor_copy(cur, &cur2);
+   evas_textblock_cursor_line_char_last(&cur2);
+   if (cur2.pos == cur->pos)
+     {
+        ret = EINA_TRUE;
+     }
+   return ret;
 }
 
-
 /* general controls */
 /**
- * to be documented.
- * @param obj to be documented.
- * @param line to be documented.
- * @param cx to be documented.
- * @param cy to be documented.
- * @param cw to be documented.
- * @param ch to be documented.
- * @return to be documented.
+ * Get the geometry of a line number.
+ *
+ * @param obj the object.
+ * @param line the line number.
+ * @param cx x coord of the line.
+ * @param cy y coord of the line.
+ * @param cw w coord of the line.
+ * @param ch h coord of the line.
+ * @return #EINA_TRUE on success, #EINA_FALSE otherwise.
  */
 EAPI Eina_Bool
 evas_object_textblock_line_number_geometry_get(const Evas_Object *obj, int line, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
@@ -5240,9 +6664,11 @@ evas_object_textblock_line_number_geometry_get(const Evas_Object *obj, int line,
 }
 
 /**
- * to be documented.
- * @param obj to be documented.
- * @return Returns no value.
+ * Clear the textblock object.
+ * @note Does *NOT* free the evas object itself.
+ *
+ * @param obj the object to clear.
+ * @return nothing.
  */
 EAPI void
 evas_object_textblock_clear(Evas_Object *obj)
@@ -5254,36 +6680,40 @@ evas_object_textblock_clear(Evas_Object *obj)
    _nodes_clear(obj);
    o->cursor->node = NULL;
    o->cursor->pos = 0;
-   o->cursor->eol = 0;
    EINA_LIST_FOREACH(o->cursors, l, cur)
      {
        cur->node = NULL;
        cur->pos = 0;
-        cur->eol = 0;
-     }
-   if (o->lines)
-     {
-       _lines_clear(obj, o->lines);
-       o->lines = NULL;
+
      }
-   o->formatted.valid = 0;
-   o->native.valid = 0;
-   o->changed = 1;
-   if (o->markup_text)
+   if (o->paragraphs)
      {
-       free(o->markup_text);
-       o->markup_text = NULL;
+       _paragraphs_clear(obj, o->paragraphs);
+       o->paragraphs = NULL;
      }
-   evas_object_change(obj);
-   /* FIXME: adjust cursors that are affected by the change */
+    _evas_textblock_changed(o, obj);
 }
 
 /**
- * to be documented.
- * @param obj to be documented.
- * @param w to be documented.
- * @param h to be documented.
+ * Get the formatted width. This calculates the actual size after restricting
+ * the textblock to the current size of the object.
+ * The main difference between this and @ref evas_object_textblock_size_native_get
+ * is that the "native" function does not wrapping into account
+ * it just calculates the real wdith of the objcet if it was placed on an
+ * infinite canvas, while this function gives the size after wrapping
+ * according to the size restrictions of the object.
+ *
+ * For example for a textblock containing the text: "You shall not pass!"
+ * with no margins or padding and assuming a monospace font and a size of
+ * 7x10 char widths (for simplicity) has a native size of 19x1
+ * and a formatted size of 5x4.
+ *
+ *
+ * @param obj the evas object.
+ * @param w[out] the w of the object.
+ * @param h[out] the h of the object
  * @return Returns no value.
+ * @see evas_object_textblock_size_native_get
  */
 EAPI void
 evas_object_textblock_size_formatted_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
@@ -5295,10 +6725,22 @@ evas_object_textblock_size_formatted_get(const Evas_Object *obj, Evas_Coord *w,
 }
 
 /**
- * to be documented.
- * @param obj to be documented.
- * @param w to be documented.
- * @param h to be documented.
+ * Get the native idth. This calculates the actual size without taking account
+ * the current size of the object.
+ * The main difference between this and @ref evas_object_textblock_size_formatted_get
+ * is that the "native" function does not take wrapping into account
+ * it just calculates the real wdith of the objcet if it was placed on an
+ * infinite canvas, while the "formatted" function gives the size after
+ * wrapping text according to the size restrictions of the object.
+ *
+ * For example for a textblock containing the text: "You shall not pass!"
+ * with no margins or padding and assuming a monospace font and a size of
+ * 7x10 char widths (for simplicity) has a native size of 19x1
+ * and a formatted size of 5x4.
+ *
+ * @param obj the evas object of the textblock
+ * @param w[out] the width returned
+ * @param h[out] the height returned
  * @return Returns no value.
  */
 EAPI void
@@ -5337,10 +6779,6 @@ evas_object_textblock_style_insets_get(const Evas_Object *obj, Evas_Coord *l, Ev
    if (b) *b = o->style_pad.b;
 }
 
-/**
- * @}
- */
-
 /* all nice and private */
 static void
 evas_object_textblock_init(Evas_Object *obj)
@@ -5378,6 +6816,7 @@ evas_object_textblock_new(void)
    o = calloc(1, sizeof(Evas_Object_Textblock));
    o->magic = MAGIC_OBJ_TEXTBLOCK;
    o->cursor = calloc(1, sizeof(Evas_Textblock_Cursor));
+   _format_command_init();
    return o;
 }
 
@@ -5401,8 +6840,10 @@ evas_object_textblock_free(Evas_Object *obj)
    if (o->repch) eina_stringshare_del(o->repch);
    o->magic = 0;
    free(o);
+   _format_command_shutdown();
 }
 
+
 static void
 evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
 {
@@ -5432,8 +6873,12 @@ evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void
    obj->layer->evas->engine.func->context_multiplier_unset(output,
                                                           context);
    clip = ENFN->context_clip_get(output, context, &cx, &cy, &cw, &ch);
+   /* If there are no paragraphs and thus there are no lines,
+    * there's nothing left to do. */
+   if (!o->paragraphs) return;
+
 #define ITEM_WALK() \
-   EINA_INLIST_FOREACH(o->lines, ln) \
+   EINA_INLIST_FOREACH(o->paragraphs->lines, ln) \
      { \
        Evas_Object_Textblock_Item *it; \
        \
@@ -5462,7 +6907,7 @@ evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void
                   if ((obj->cur.geometry.x + x + ln->x + it->x - it->inset) > (cx + cw + 20)) \
                     break; \
                }
-             
+
 #define ITEM_WALK_END() \
          } \
      }
@@ -5478,19 +6923,19 @@ evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void
                                (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 - it->inset + 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
 #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), \
-                                                it->w, it->h, it->w, it->h, it->text);
-#if 0
-//#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);
+                                                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
 #define ITEM_WALK_LINE_SKIP_DROP() \
    if ((ln->y + ln->h) <= 0) continue; \
@@ -5554,6 +6999,8 @@ evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void
      }
    ITEM_WALK_END();
 
+   /* prepare everything for text draw */
+
    /* shadows */
    ITEM_WALK();
    ITEM_WALK_LINE_SKIP_DROP();
@@ -5843,10 +7290,10 @@ evas_object_textblock_render_pre(Evas_Object *obj)
    if ((o->changed) ||
        (o->last_w != obj->cur.geometry.w))
      {
-       Evas_Object_Textblock_Line *lines;
+       Evas_Object_Textblock_Paragraph *paragraphs;
 
-       lines = o->lines;
-       o->lines = NULL;
+       paragraphs = o->paragraphs;
+       o->paragraphs = NULL;
        o->formatted.valid = 0;
        o->native.valid = 0;
        _layout(obj,
@@ -5854,7 +7301,10 @@ evas_object_textblock_render_pre(Evas_Object *obj)
                obj->cur.geometry.w, obj->cur.geometry.h,
                &o->formatted.w, &o->formatted.h);
        o->formatted.valid = 1;
-       if (lines) _lines_clear(obj, lines);
+        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);
@@ -5978,7 +7428,7 @@ static void *evas_object_textblock_engine_data_get(Evas_Object *obj)
 }
 
 static int
-evas_object_textblock_is_opaque(Evas_Object *obj)
+evas_object_textblock_is_opaque(Evas_Object *obj __UNUSED__)
 {
    /* this returns 1 if the internal object data implies that the object is */
    /* currently fulyl opque over the entire gradient it occupies */
@@ -5986,7 +7436,7 @@ evas_object_textblock_is_opaque(Evas_Object *obj)
 }
 
 static int
-evas_object_textblock_was_opaque(Evas_Object *obj)
+evas_object_textblock_was_opaque(Evas_Object *obj __UNUSED__)
 {
    /* this returns 1 if the internal object data implies that the object was */
    /* currently fulyl opque over the entire gradient it occupies */
@@ -6020,7 +7470,7 @@ _evas_object_textblock_rehint(Evas_Object *obj)
    Evas_Object_Textblock_Line *ln;
 
    o = (Evas_Object_Textblock *)(obj->object_data);
-   EINA_INLIST_FOREACH(o->lines, ln)
+   EINA_INLIST_FOREACH(o->paragraphs->lines, ln)
      {
        Evas_Object_Textblock_Item *it;
 
@@ -6042,3 +7492,8 @@ _evas_object_textblock_rehint(Evas_Object *obj)
    o->changed = 1;
    evas_object_change(obj);
 }
+
+/**
+ * @}
+ */
+
index a30f32c..50037dd 100644 (file)
@@ -177,10 +177,10 @@ _evas_render_cur_clip_cache_del(Evas *e, Evas_Object *obj)
 }
 
 static void
-_evas_render_phase1_direct(Evas *e, 
-                           Eina_Array *active_objects
-                           Eina_Array *restack_objects
-                           Eina_Array *delete_objects
+_evas_render_phase1_direct(Evas *e,
+                           Eina_Array *active_objects __UNUSED__,
+                           Eina_Array *restack_objects __UNUSED__,
+                           Eina_Array *delete_objects __UNUSED__,
                            Eina_Array *render_objects)
 {
    unsigned int i;
@@ -1338,6 +1338,8 @@ evas_sync(Evas *e)
    MAGIC_CHECK_END();
 
    evas_common_frameq_flush ();
+#else
+   (void) e;
 #endif
 }
 
index 024e173..b28c2cc 100644 (file)
@@ -1,162 +1,2 @@
 #include "evas_common.h"
 #include "evas_private.h"
-#include <math.h>
-
-/**
- * @addtogroup Evas_Utils
- * @{
- */
-
-/**
- * To be documented.
- *
- * FIXME: To be fixed.
- *
- */
-EAPI void
-evas_transform_identity_set(Evas_Transform *t)
-{
-   if (t)
-     {
-       t->mxx = t->myy = t->mzz = 1;
-       t->mxy = t->mxz = 0;
-       t->myx = t->myz = 0;
-       t->mzx = t->mzy = 0;
-     }
-}
-
-/**
- * To be documented.
- *
- * FIXME: To be fixed.
- *
- */
-EAPI void
-evas_transform_rotate(double angle, Evas_Transform *t)
-{
-   double ca, sa;
-   float mxx, mxy, mxz;
-   float myx, myy, myz;
-
-   if (!t) return;
-
-   angle = (angle * M_PI) / 180.0;
-   ca = cos(angle);  sa = sin(angle);
-   if ((ca == 1) && (sa == 0)) return;
-
-   mxx = t->mxx;  mxy = t->mxy;  mxz = t->mxz;
-   myx = t->myx;  myy = t->myy;  myz = t->myz;
-
-   t->mxx = (ca * mxx) + (sa * myx);
-   t->mxy = (ca * mxy) + (sa * myy);
-   t->mxz = (ca * mxz) + (sa * myz);
-
-   t->myx = (-sa * mxx) + (ca * myx);
-   t->myy = (-sa * mxy) + (ca * myy);
-   t->myz = (-sa * mxz) + (ca * myz);
-}
-
-/**
- * To be documented.
- *
- * FIXME: To be fixed.
- *
- */
-EAPI void
-evas_transform_translate(float dx, float dy, Evas_Transform *t)
-{
-   if (!t) return;
-   if (!dx && !dy) return;
-
-   t->mxx = dx * t->mzx;
-   t->mxy = dx * t->mzy;
-   t->mxz = dx * t->mzz;
-
-   t->myx = dy * t->mzx;
-   t->myy = dy * t->mzy;
-   t->myz = dy * t->mzz;
-}
-
-/**
- * To be documented.
- *
- * FIXME: To be fixed.
- *
- */
-EAPI void
-evas_transform_scale(float sx, float sy, Evas_Transform *t)
-{
-   if (!t) return;
-   if ((sx == 1) && (sy == 1)) return;
-
-   t->mxx = sx * t->mxx;
-   t->mxy = sx * t->mxy;
-   t->mxz = sx * t->mxz;
-
-   t->myx = sy * t->myx;
-   t->myy = sy * t->myy;
-   t->myz = sy * t->myz;
-}
-
-/**
- * To be documented.
- *
- * FIXME: To be fixed.
- *
- */
-EAPI void
-evas_transform_shear(float sh, float sv, Evas_Transform *t)
-{
-   float mxx, mxy, mxz;
-   float myx, myy, myz;
-
-   if (!t) return;
-   if ((sh == 1) && (sv == 1)) return;
-
-   mxx = t->mxx;  mxy = t->mxy;  mxz = t->mxz;
-   myx = t->myx;  myy = t->myy;  myz = t->myz;
-
-   t->mxx = mxx + (sh * myx);
-   t->mxy = mxy + (sh * myy);
-   t->mxz = mxz + (sh * myz);
-
-   t->myx = (sv * mxx) + myx;
-   t->myy = (sv * mxy) + myy;
-   t->myz = (sv * mxz) + myz;
-}
-
-/**
- * To be documented.
- *
- * FIXME: To be fixed.
- *
- */
-EAPI void
-evas_transform_compose(Evas_Transform *l, Evas_Transform *t)
-{
-   float mxx, mxy, mxz;
-   float myx, myy, myz;
-   float mzx, mzy, mzz;
-
-   if (!t || !l) return;
-
-   mxx = t->mxx;  mxy = t->mxy;  mxz = t->mxz;
-   myx = t->myx;  myy = t->myy;  myz = t->myz;
-   mzx = t->mzx;  mzy = t->mzy;  mzz = t->mzz;
-
-   t->mxx = (l->mxx * mxx) + (l->mxy * myx) + (l->mxz * mzx);
-   t->mxy = (l->mxx * mxy) + (l->mxy * myy) + (l->mxz * mzy);
-   t->mxz = (l->mxx * mxz) + (l->mxy * myz) + (l->mxz * mzz);
-
-   t->myx = (l->myx * mxx) + (l->myy * myx) + (l->myz * mzx);
-   t->myy = (l->myx * mxy) + (l->myy * myy) + (l->myz * mzy);
-   t->myz = (l->myx * mxz) + (l->myy * myz) + (l->myz * mzz);
-
-   t->mzx = (l->mzx * mxx) + (l->mzy * myx) + (l->mzz * mzx);
-   t->mzy = (l->mzx * mxy) + (l->mzy * myy) + (l->mzz * mzy);
-   t->mzz = (l->mzx * mxz) + (l->mzy * myz) + (l->mzz * mzz);
-}
-
-/**
- * @}
- */
index dc2f2b7..2076059 100644 (file)
@@ -213,7 +213,7 @@ server_parse(Server *s, Client *c)
 {
    int *ints;
    unsigned char *data, *newbuf;
-   
+
    if (c->inbufsize < sizeof(int)) return 0;
    ints = (int *)((c->inbuf));
    if ((ints[0] < 0) || (ints[0] > (1024 * 1024)))
index 9d68875..0e7706c 100644 (file)
@@ -8,3 +8,9 @@ if BUILD_ENGINE_SOFTWARE_16
 SUBDIRS += common_16
 
 endif
+
+if BUILD_ENGINE_SOFTWARE_8
+
+SUBDIRS += common_8
+
+endif
index b0d0d35..00fbb06 100644 (file)
@@ -39,19 +39,11 @@ 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 \
 evas_font_query.c \
-evas_gradient_main.c \
-evas_gradient_linear.c \
-evas_gradient_radial.c \
-evas_gradient_angular.c \
-evas_gradient_rectangular.c \
-evas_gradient_sinusoidal.c \
-evas_gradient2_main.c \
-evas_gradient2_linear.c \
-evas_gradient2_radial.c \
 evas_image_load.c \
 evas_image_save.c \
 evas_image_main.c \
@@ -67,9 +59,7 @@ evas_scale_span.c \
 evas_tiler.c \
 evas_regionbuf.c \
 evas_pipe.c \
-evas_intl_utils.c \
-evas_intl/evas_intl_arabic.c \
-evas_intl/evas_intl_arabic.h \
+evas_bidi_utils.c \
 evas_map_image.c \
 evas_map_image.h
 
@@ -89,10 +79,9 @@ 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_gradient.h \
-evas_gradient_private.h \
 evas_image.h \
 evas_image_private.h \
 evas_line.h \
@@ -109,7 +98,7 @@ evas_scale_smooth_scaler_noscale.c \
 evas_scale_smooth_scaler_up.c \
 evas_scale_span.h \
 evas_pipe.h \
-evas_intl_utils.h \
+evas_bidi_utils.h \
 evas_map_image_internal.c \
 evas_map_image_core.c \
 evas_map_image_loop.c
diff --git a/src/lib/engines/common/evas_bidi_utils.c b/src/lib/engines/common/evas_bidi_utils.c
new file mode 100644 (file)
index 0000000..a64955b
--- /dev/null
@@ -0,0 +1,392 @@
+#include <string.h>
+#include <stdlib.h>
+
+#include "evas_common.h"
+#include "evas_bidi_utils.h"
+#include "evas_encoding.h"
+
+#include "evas_font_private.h"
+
+#ifdef BIDI_SUPPORT
+#include <fribidi/fribidi.h>
+/**
+ * @internal
+ * @addtogroup Evas_Utils
+ *
+ * @{
+ */
+/**
+ * @internal
+ * @addtogroup Evas_BiDi
+ *
+ * @{
+ */
+
+/**
+ * @internal
+ * @def _SAFE_FREE(x)
+ * checks if x is not NULL, if it's not, it's freed and set to NULL.
+ */
+#define _SAFE_FREE(x) \
+   do {               \
+      if (x)          \
+        {             \
+           free(x);   \
+           x = NULL;  \
+        }             \
+     } while(0)
+
+/* Convert bidichar to eina_unicode assume both are valid pointers */
+static Eina_Unicode *
+_evas_bidi_fribidichar_to_unicode(Eina_Unicode *dest, const FriBidiChar *src)
+{
+   Eina_Unicode *ret = dest;
+
+   while (*src)
+        *dest++ = *src++;
+   *dest = 0;
+   return ret;
+}
+
+/* Convert eina_unicode to bidi_char assume both are valid pointers */
+static FriBidiChar *
+_evas_bidi_unicode_to_fribidichar(FriBidiChar *dest, const Eina_Unicode *src)
+{
+   FriBidiChar *ret = dest;
+
+   while (*src)
+        *dest++ = *src++;
+   *dest = 0;
+   return ret;
+}
+
+/**
+ * @internal
+ * Checks if the string has RTL characters.
+ *
+ * @param str The string to be checked
+ * @return #EINA_TRUE if true, #EINA_FALSE otherwise.
+ */
+Eina_Bool
+evas_bidi_is_rtl_str(const Eina_Unicode *str)
+{
+   EvasBiDiCharType type;
+
+   if (!str)
+      return EINA_FALSE;
+
+   for ( ; *str ; str++)
+     {
+        type = fribidi_get_bidi_type((FriBidiChar) *str);
+        if (FRIBIDI_IS_LETTER(type) && FRIBIDI_IS_RTL(type))
+          {
+             return EINA_TRUE;
+          }
+     }
+   return EINA_FALSE;
+}
+
+/**
+ * @internal
+ * Shapes the string ustr according to the bidi properties.
+ *
+ * @param str The string to shape
+ * @param bidi_props the bidi props to shaped according.
+ * @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)
+{
+   FriBidiChar *ustr, *base_ustr = NULL;
+
+   if (!EVAS_BIDI_IS_BIDI_PROP(bidi_props->props))
+     return EINA_FALSE;
+
+   /* The size of fribidichar is different than eina_unicode, convert */
+   /*FIXME: Make this comparison at compile time and compile out
+    * unwanted code. - In all of this source file. */
+   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;
+     }
+
+
+   EvasBiDiJoiningType *join_types = NULL;
+   join_types = (EvasBiDiJoiningType *) malloc(sizeof(EvasBiDiJoiningType) * len);
+   if (!join_types)
+     {
+        return EINA_FALSE;
+     }
+   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);
+
+
+   /* Actually modify the string */
+   fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC,
+               bidi_props->props->embedding_levels + bidi_props->start, len, join_types, ustr);
+
+   if (join_types) free(join_types);
+
+   /* Convert back */
+   if (sizeof(Eina_Unicode) != sizeof(FriBidiChar))
+     {
+        eina_ustr = _evas_bidi_fribidichar_to_unicode(eina_ustr, ustr);
+        if (base_ustr) free(base_ustr);
+     }
+   return EINA_TRUE;
+}
+
+/**
+ * @internal
+ * Updates the bidi properties according to ustr. First checks to see if the
+ * passed has rtl chars, if not, it cleans intl_props and returns.
+ * Otherwise, it essentially frees the old fields, allocates new fields, and
+ * populates them.
+ * On error: bidi_props is cleaned.
+ *
+ * @param ustr The string to update according to.
+ * @param bidi_props the bidi_props to update.
+ * @return returns the length of the string on success, a negative value on error.
+ */
+int
+evas_bidi_update_props(const Eina_Unicode *eina_ustr, Evas_BiDi_Paragraph_Props *bidi_props)
+{
+   EvasBiDiCharType *char_types = NULL;
+   EvasBiDiLevel *embedding_levels = NULL;
+   const FriBidiChar *ustr;
+   FriBidiChar *base_ustr = NULL;
+   size_t len;
+
+   if (!eina_ustr)
+      return -2;
+
+
+   len = eina_unicode_strlen(eina_ustr);
+   /* The size of fribidichar s different than eina_unicode, convert */
+   if (sizeof(Eina_Unicode) != sizeof(FriBidiChar))
+     {
+        base_ustr = calloc(len + 1, sizeof(FriBidiChar));
+        base_ustr = _evas_bidi_unicode_to_fribidichar(base_ustr, eina_ustr);
+        ustr = base_ustr;
+     }
+   else
+     {
+        ustr = (const FriBidiChar *) eina_ustr;
+     }
+
+
+   if (!evas_bidi_is_rtl_str(eina_ustr)) /* No need to handle bidi */
+     {
+        len = -1;
+        goto cleanup;
+     }
+
+   /* Prep work for reordering */
+   char_types = (EvasBiDiCharType *) malloc(sizeof(EvasBiDiCharType) * len);
+   if (!char_types)
+      {
+         len = -2;
+         goto cleanup;
+      }
+   fribidi_get_bidi_types(ustr, len, char_types);
+
+   embedding_levels = (EvasBiDiLevel *)malloc(sizeof(EvasBiDiLevel) * len);
+   if (!embedding_levels)
+     {
+        len = -2;
+        goto cleanup;
+     }
+   if (!fribidi_get_par_embedding_levels(char_types, len, &bidi_props->direction, embedding_levels))
+     {
+        len = -2;
+        goto cleanup;
+     }
+
+
+   /* clean up */
+   if (bidi_props->embedding_levels)
+     {
+        free(bidi_props->embedding_levels);
+     }
+   bidi_props->embedding_levels = embedding_levels;
+
+   /* clean up */
+
+   if (bidi_props->char_types)
+     {
+        free(bidi_props->char_types);
+     }
+   bidi_props->char_types = char_types;
+
+   if (base_ustr) free(base_ustr);
+
+
+   return len;
+
+/* Cleanup */
+cleanup:
+   if (char_types) free(char_types);
+   if (embedding_levels) free(embedding_levels);
+   if (base_ustr) free(base_ustr);
+   evas_bidi_paragraph_props_clean(bidi_props); /*Mark that we don't need bidi handling */
+   return len;
+}
+
+/**
+ * @internal
+ * Reorders ustr according to the bidi props.
+ *
+ * @param ustr the string to reorder.
+ * @param intl_props the intl properties to rerorder 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)
+{
+   EvasBiDiStrIndex *v_to_l = NULL;
+   FriBidiChar *ustr, *base_ustr = NULL;
+   size_t len;
+
+   if (!EVAS_BIDI_IS_BIDI_PROP(intl_props->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))
+     {
+        base_ustr = ustr = calloc(len + 1, sizeof(FriBidiChar));
+        ustr = _evas_bidi_unicode_to_fribidichar(ustr, eina_ustr);
+     }
+   else
+     {
+        ustr = (FriBidiChar *) eina_ustr;
+     }
+
+
+   if (_v_to_l) {
+      int i;
+      v_to_l = *_v_to_l = calloc(len, sizeof(EvasBiDiStrIndex));
+      if (!v_to_l)
+        {
+           goto error;
+        }
+      /* init the array for fribidi */
+      for (i = 0 ; i < len ; i++)
+        {
+           v_to_l[i] = i;
+        }
+   }
+
+   /* 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;
+     }
+
+
+   /* 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);
+        free(base_ustr);
+     }
+   return EINA_FALSE;
+/* ERROR HANDLING */
+error:
+   if (base_ustr) free(base_ustr);
+   _SAFE_FREE(v_to_l);
+   return EINA_TRUE;
+}
+
+
+/**
+ * @internal
+ * Returns the visual string index from the logical string index.
+ *
+ * @param v_to_l the visual to logical map
+ * @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_logical_to_visual(EvasBiDiStrIndex *v_to_l, int len, EvasBiDiStrIndex position)
+{
+   int i;
+   EvasBiDiStrIndex *ind;
+   if (position >= len || !v_to_l)
+      return position;
+
+   for (i = 0, ind = v_to_l ; i < len ; i++, ind++)
+     {
+        if (*ind == position)
+          {
+             return i;
+          }
+     }
+   return position;
+}
+
+/**
+ * @internal
+ * Checks if the char is rtl oriented. I.e even a neutral char can become rtl
+ * if surrounded by rtl chars.
+ *
+ * @param embedded_level_list the bidi embedding list.
+ * @param index the index of the string.
+ * @return #EINA_TRUE if true, #EINA_FALSE otherwise.
+ */
+Eina_Bool
+evas_bidi_is_rtl_char(EvasBiDiLevel *embedded_level_list, EvasBiDiStrIndex index)
+{
+   if(!embedded_level_list || index < 0)
+      return EINA_FALSE;
+   return (FRIBIDI_IS_RTL(embedded_level_list[index])) ? EINA_TRUE : EINA_FALSE;
+}
+
+/**
+ * @internal
+ * Cleans the paragraph properties.
+ *
+ * @param bidi_props the properties to clean.
+ */
+void
+evas_bidi_paragraph_props_clean(Evas_BiDi_Paragraph_Props *bidi_props)
+{
+   _SAFE_FREE(bidi_props->embedding_levels);
+   _SAFE_FREE(bidi_props->char_types);
+}
+
+/**
+ * @internal
+ * Cleans the bidi properties.
+ *
+ * @param bidi_props the properties to clean.
+ */
+void
+evas_bidi_props_clean(Evas_BiDi_Props *bidi_props)
+{
+   if (!bidi_props) return;
+   evas_bidi_paragraph_props_clean(bidi_props->props);
+   bidi_props->props = NULL;
+}
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+#endif
+
diff --git a/src/lib/engines/common/evas_bidi_utils.h b/src/lib/engines/common/evas_bidi_utils.h
new file mode 100644 (file)
index 0000000..0d51675
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef _EVAS_BIDI_UTILS
+#define _EVAS_BIDI_UTILS
+
+/**
+ * @internal
+ * @addtogroup Evas_Utils
+ *
+ * @{
+ */
+/**
+ * @internal
+ * @defgroup Evas_BiDi Evas BiDi utility functions
+ *
+ * This set of functions and types helps evas handle BiDi strings correctly.
+ * @todo Document types, structures and macros.
+ *
+ * @{
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_FRIBIDI
+# define USE_FRIBIDI
+# define BIDI_SUPPORT
+#endif
+
+#include <Eina.h>
+#include "evas_common.h"
+
+#ifdef USE_FRIBIDI
+# include <fribidi/fribidi.h>
+#endif
+
+/* abstract fribidi - we statically define sizes here because otherwise we would
+ * have to ifdef everywhere (because function decorations may change with/without
+ * bidi support)
+ * These types should only be passed as pointers! i.e do not directely use any of
+ * these types in function declarations. Defining as void should help ensuring that.
+ */
+
+#ifdef USE_FRIBIDI
+# define _EVAS_BIDI_TYPEDEF(type) \
+   typedef FriBidi ## type EvasBiDi ## type
+#else
+# define _EVAS_BIDI_TYPEDEF(type) \
+   typedef void EvasBiDi ## type
+#endif
+
+#if 0 /* We are using Eina_Unicode instead */
+_EVAS_BIDI_TYPEDEF(Char);
+#endif
+_EVAS_BIDI_TYPEDEF(CharType);
+_EVAS_BIDI_TYPEDEF(ParType);
+_EVAS_BIDI_TYPEDEF(StrIndex);
+_EVAS_BIDI_TYPEDEF(Level);
+_EVAS_BIDI_TYPEDEF(JoiningType);
+
+typedef struct _Evas_BiDi_Paragraph_Props Evas_BiDi_Paragraph_Props;
+typedef struct _Evas_BiDi_Props Evas_BiDi_Props;
+
+/* This structure defines a set of properties of a BiDi string. In case of a
+ * non-bidi string, all values should be NULL.
+ * To check if a structure describes a bidi string or not, use the macro
+ * EVAS_BIDI_IS_BIDI_PROP. RTL-only strings are also treated as bidi ATM.
+ */
+struct _Evas_BiDi_Paragraph_Props {
+   EvasBiDiCharType  *char_types; /* BiDi char types */
+   EvasBiDiLevel     *embedding_levels; /* BiDi embedding levels */
+#ifdef USE_FRIBIDI
+   EvasBiDiParType    direction;
+#endif
+};
+
+struct _Evas_BiDi_Props {
+   Evas_BiDi_Paragraph_Props *props;
+   size_t                     start;
+};
+
+
+
+#ifdef USE_FRIBIDI
+
+
+#define EVAS_BIDI_PARAGRAPH_NATURAL FRIBIDI_PAR_ON
+#define EVAS_BIDI_PARAGRAPH_LTR     FRIBIDI_PAR_LTR
+#define EVAS_BIDI_PARAGRAPH_RTL     FRIBIDI_PAR_RTL
+#define EVAS_BIDI_PARAGRAPH_WLTR    FRIBIDI_PAR_WLTR
+#define EVAS_BIDI_PARAGRAPH_WRTL    FRIBIDI_PAR_WRTL
+
+#define EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(direction)       \
+                (((direction == EVAS_BIDI_PARAGRAPH_RTL) ||   \
+                 (direction == EVAS_BIDI_PARAGRAPH_WRTL)) ?   \
+                 EINA_TRUE : EINA_FALSE)
+
+
+# define EVAS_BIDI_IS_BIDI_PROP(intl_props) ((intl_props) && (intl_props)->char_types)
+# define evas_bidi_position_visual_to_logical(list, position) \
+                (list) ? list[position] : position;
+
+EvasBiDiStrIndex
+evas_bidi_position_logical_to_visual(EvasBiDiStrIndex *v_to_l, int len, EvasBiDiStrIndex position);
+
+Eina_Bool
+evas_bidi_is_rtl_str(const Eina_Unicode *str);
+
+Eina_Bool
+evas_bidi_is_rtl_char(EvasBiDiLevel *embedded_level_list, EvasBiDiStrIndex index);
+
+Eina_Bool
+evas_bidi_props_reorder_line(Eina_Unicode *text, const Evas_BiDi_Props *intl_props, EvasBiDiStrIndex **_v_to_l);
+
+int
+evas_bidi_update_props(const Eina_Unicode *text, Evas_BiDi_Paragraph_Props *intl_props) EINA_ARG_NONNULL(1, 2);
+
+Eina_Bool
+evas_bidi_shape_string(Eina_Unicode *ustr, const Evas_BiDi_Props *intl_props, size_t len);
+
+void
+evas_bidi_props_clean(Evas_BiDi_Props *intl_props) EINA_ARG_NONNULL(1);
+
+void
+evas_bidi_paragraph_props_clean(Evas_BiDi_Paragraph_Props *bidi_props) EINA_ARG_NONNULL(1);
+
+#endif
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+
+#endif
+
index 65ed493..1a98f3f 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_BLEND_H
 #define _EVAS_BLEND_H
 
index 6ab7cb8..4aadd02 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_blend_private.h"
 
index 84513d1..1d14951 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_BLEND_PRIVATE_H
 #define _EVAS_BLEND_PRIVATE_H
 
index 4630df2..18cc0b2 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 
 #if defined BUILD_MMX || defined BUILD_SSE
@@ -15,6 +11,11 @@ static void evas_common_copy_pixels_mmx      (DATA32 *src, DATA32 *dst, int len)
 static void evas_common_copy_pixels_mmx2     (DATA32 *src, DATA32 *dst, int len);
 static void evas_common_copy_pixels_sse/*NB*/ (DATA32 *src, DATA32 *dst, int len);
 
+#ifdef BUILD_NEON
+static void evas_common_copy_pixels_neon     (DATA32 *src, DATA32 *dst, int len);
+static void evas_common_copy_pixels_rev_neon (DATA32 *src, DATA32 *dst, int len);
+#endif
+
 static void evas_common_copy_pixels_rev_c           (DATA32 *src, DATA32 *dst, int len);
 static void evas_common_copy_pixels_rev_mmx         (DATA32 *src, DATA32 *dst, int len);
 static void evas_common_copy_pixels_rev_sse/*NB*/ (DATA32 *src, DATA32 *dst, int len);
@@ -129,6 +130,110 @@ evas_common_copy_rev_pixels_c(DATA32 *src, DATA32 *dst, int len)
        *dst++ = *src--;
 }
 
+
+#ifdef BUILD_NEON
+static void
+evas_common_copy_pixels_rev_neon(DATA32 *src, DATA32 *dst, int len)
+{
+   uint32_t *tmp = (void *)37;
+#define AP     "evas_common_copy_rev_pixels_neon_"
+   asm volatile (
+               // Can we do 32 byte?
+               "andS           %[tmp], %[d], $0x1f     \n\t"
+               "beq            "AP"quadstart           \n\t"
+
+               // Can we do at least 16 byte?
+               "andS           %[tmp], %[d], $0x4      \n\t"
+               "beq            "AP"dualstart           \n\t"
+
+       // Only once
+       AP"singleloop:                                  \n\t"
+               "sub            %[s], #4                \n\t"
+               "vld1.32        d0[0],  [%[s]]          \n\t"
+               "vst1.32        d0[0],  [%[d]]!         \n\t"
+
+       // Up to 3 times
+       AP"dualstart:                                   \n\t"
+               "sub            %[tmp], %[e], %[d]      \n\t"
+               "cmp            %[tmp], #31             \n\t"
+               "blt            "AP"loopout             \n\t"
+
+               "andS           %[tmp], %[d], $0x1f     \n\t"
+               "beq            "AP"quadstart           \n\t"
+
+       AP"dualloop:                                    \n\t"
+               "sub            %[s], #8                \n\t"
+               "vldm           %[s], {d0}              \n\t"
+               "vrev64.32      d1, d0                  \n\t"
+               "vstm           %[d]!, {d1}             \n\t"
+
+               "andS           %[tmp], %[d], $0x1f     \n\t"
+               "bne            "AP"dualloop            \n\t"
+
+
+       AP"quadstart:                                   \n\t"
+               "sub            %[tmp], %[e], %[d]      \n\t"
+               "cmp            %[tmp], #32             \n\t"
+               "blt            "AP"loopout             \n\t"
+
+               "sub            %[tmp],%[e],#32         \n\t"
+
+       AP "quadloop:                                   \n\t"
+               "sub            %[s],   #32             \n\t"
+               "vldm           %[s],   {d0,d1,d2,d3}   \n\t"
+
+               "vrev64.32      d7,d0                   \n\t"
+               "vrev64.32      d6,d1                   \n\t"
+               "vrev64.32      d5,d2                   \n\t"
+               "vrev64.32      d4,d3                   \n\t"
+
+               "vstm           %[d]!,  {d4,d5,d6,d7}   \n\t"
+
+               "cmp            %[tmp], %[d]            \n\t"
+                "bhi           "AP"quadloop            \n\t"
+
+
+       AP "loopout:                                    \n\t"
+               "cmp            %[d], %[e]              \n\t"
+                "beq           "AP"done                \n\t"
+               "sub            %[tmp],%[e], %[d]       \n\t"
+               "cmp            %[tmp],$0x04            \n\t"
+               "beq            "AP"singleloop2         \n\t"
+
+       AP "dualloop2:                                  \n\t"
+               "sub            %[tmp],%[e],$0x7        \n\t"
+       AP "dualloop2int:                               \n\t"
+               "sub            %[s], #8                \n\t"
+               "vldm           %[s], {d0}              \n\t"
+               "vrev64.32      d1,d0                   \n\t"
+               "vstm           %[d]!, {d1}             \n\t"
+
+               "cmp            %[tmp], %[d]            \n\t"
+               "bhi            "AP"dualloop2int        \n\t"
+
+               // Single ??
+               "cmp            %[e], %[d]              \n\t"
+               "beq            "AP"done                \n\t"
+
+       AP "singleloop2:                                \n\t"
+               "sub            %[s], #4                \n\t"
+               "vld1.32        d0[0], [%[s]]           \n\t"
+               "vst1.32        d0[0], [%[d]]           \n\t"
+
+       AP "done:\n\t"
+
+               : // No output regs
+               // Input
+               : [s] "r" (src + len), [e] "r" (dst + len), [d] "r" (dst),[tmp] "r" (tmp)
+               // Clobbered
+               : "q0","q1","q2","q3","0","1","memory"
+   );
+#undef AP
+
+}
+#endif
+
+
 #ifdef BUILD_C
 static void
 evas_common_copy_pixels_c(DATA32 *src, DATA32 *dst, int len)
@@ -226,6 +331,97 @@ evas_common_copy_pixels_mmx2(DATA32 *src, DATA32 *dst, int len)
 }
 #endif
 
+#ifdef BUILD_NEON
+static void
+evas_common_copy_pixels_neon(DATA32 *src, DATA32 *dst, int len){
+   uint32_t *e,*tmp = (void *)37;
+   e = dst + len;
+#define AP     "evas_common_copy_pixels_neon_"
+   asm volatile (
+               // Can we do 32 byte?
+               "andS           %[tmp], %[d], $0x1f     \n\t"
+               "beq            "AP"quadstart           \n\t"
+
+               // Can we do at least 16 byte?
+               "andS           %[tmp], %[d], $0x4      \n\t"
+               "beq            "AP"dualstart           \n\t"
+
+       // Only once
+       AP"singleloop:                                  \n\t"
+               "vld1.32        d0[0],  [%[s]]!         \n\t"
+               "vst1.32        d0[0],  [%[d]]!         \n\t"
+
+       // Up to 3 times
+       AP"dualstart:                                   \n\t"
+               "sub            %[tmp], %[e], %[d]      \n\t"
+               "cmp            %[tmp], #31             \n\t"
+               "blt            "AP"loopout             \n\t"
+
+               "andS           %[tmp], %[d], $0x1f     \n\t"
+               "beq            "AP"quadstart           \n\t"
+
+       AP"dualloop:                                    \n\t"
+               "vldm           %[s]!, {d0}             \n\t"
+               "vstm           %[d]!, {d0}             \n\t"
+
+               "andS           %[tmp], %[d], $0x1f     \n\t"
+               "bne            "AP"dualloop            \n\t"
+
+
+       AP"quadstart:                                   \n\t"
+               "sub            %[tmp], %[e], %[d]      \n\t"
+               "cmp            %[tmp], #64             \n\t"
+               "blt            "AP"loopout             \n\t"
+
+               "sub            %[tmp],%[e],#63         \n\t"
+
+       AP "quadloop:                                   \n\t"
+               "vldm           %[s]!,  {d0,d1,d2,d3}   \n\t"
+               "vldm           %[s]!,  {d4,d5,d6,d7}   \n\t"
+               "vstm           %[d]!,  {d0,d1,d2,d3}   \n\t"
+               "vstm           %[d]!,  {d4,d5,d6,d7}   \n\t"
+
+               "cmp            %[tmp], %[d]            \n\t"
+                "bhi           "AP"quadloop            \n\t"
+
+
+       AP "loopout:                                    \n\t"
+               "cmp            %[d], %[e]              \n\t"
+                "beq           "AP"done                \n\t"
+               "sub            %[tmp],%[e], %[d]       \n\t"
+               "cmp            %[tmp],$0x04            \n\t"
+               "beq            "AP"singleloop2         \n\t"
+
+       AP "dualloop2:                                  \n\t"
+               "sub            %[tmp],%[e],$0x7        \n\t"
+       AP "dualloop2int:                               \n\t"
+               "vldm           %[s]!, {d0}             \n\t"
+               "vstm           %[d]!, {d0}             \n\t"
+
+               "cmp            %[tmp], %[d]            \n\t"
+               "bhi            "AP"dualloop2int        \n\t"
+
+               // Single ??
+               "cmp            %[e], %[d]              \n\t"
+               "beq            "AP"done                \n\t"
+
+       AP "singleloop2:                                \n\t"
+               "vld1.32        d0[0], [%[s]]           \n\t"
+               "vst1.32        d0[0], [%[d]]           \n\t"
+
+       AP "done:\n\t"
+
+               : // No output regs
+               // Input
+               : [s] "r" (src), [e] "r" (e), [d] "r" (dst),[tmp] "r" (tmp)
+               // Clobbered
+               : "q0","q1","q2","q3","memory"
+   );
+#undef AP
+
+}
+#endif /* BUILD_NEON */
+
 #ifdef BUILD_SSE
 static void
 evas_common_copy_pixels_sse(DATA32 *src, DATA32 *dst, int len)
@@ -412,8 +608,16 @@ evas_common_draw_func_copy_get(int pixels, int reverse)
          if (evas_common_cpu_has_feature(CPU_FEATURE_MMX))
            return evas_common_copy_pixels_rev_mmx;
 #endif
+#ifdef BUILD_NEON
+# if defined(BUILD_SSE) || defined(BUILD_MMX)
+       else
+# endif
+         if (evas_common_cpu_has_feature(CPU_FEATURE_NEON))
+           return evas_common_copy_pixels_rev_neon;
+#endif
+
 #ifdef BUILD_C
-# ifdef BUILD_MMX
+# if defined(BUILD_MMX) || defined(BUILD_NEON)
        else
 # endif
          return evas_common_copy_pixels_rev_c;
@@ -441,6 +645,15 @@ evas_common_draw_func_copy_get(int pixels, int reverse)
             else
 # endif
 #endif
+# ifdef BUILD_NEON
+# ifdef BUILD_C
+            if (evas_common_cpu_has_feature(CPU_FEATURE_NEON))
+# endif
+              return evas_common_copy_pixels_neon;
+# ifdef BUILD_SSE
+            else
+# endif
+#endif
 #ifdef BUILD_MMX
 # ifdef BUILD_C
               if (evas_common_cpu_has_feature(CPU_FEATURE_MMX))
index 5b16eac..70a9e90 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_color.h"
 
index a95bef8..0224879 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_COLOR_H
 #define _EVAS_CONVERT_COLOR_H
 
index 1ad9ad7..75711bb 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_colorspace.h"
 
index d82a5d9..354a08c 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_COLORSPACE_H
 #define _EVAS_CONVERT_COLORSPACE_H
 
index 3f9b5f2..45e16ee 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_gry_1.h"
 
index 81c99f6..38d6776 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_GRY_1_H
 #define _EVAS_CONVERT_GRY_1_H
 
index a633f28..2fa7ee3 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_gry_4.h"
 
index fc7b0a7..1614359 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_GRY_4_H
 #define _EVAS_CONVERT_GRY_4_H
 
index 0824351..66934e3 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_gry_8.h"
 
index 9e393cb..d70f59d 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_GRY_8_H
 #define _EVAS_CONVERT_GRY_8_H
 
index 8f8bb46..2351fda 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_grypal_6.h"
 
index 38ccda8..5f839c2 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_GRY_4_H
 #define _EVAS_CONVERT_GRY_4_H
 
index b364651..d52d1cd 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_rgb_8.h"
 #include "evas_convert_rgb_16.h"
index fb21203..51c2cc8 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_MAIN_H
 #define _EVAS_CONVERT_MAIN_H
 
index 143f150..597c4cb 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_rgb_16.h"
 
index fd1e570..f7ae63c 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_RGB_16_H
 #define _EVAS_CONVERT_RGB_16_H
 
index d5d4f4e..9efa006 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_rgb_24.h"
 
index 5a67cbc..bc114ca 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_RGB_24_H
 #define _EVAS_CONVERT_RGB_24_H
 
index dd5d450..aba2c4a 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_rgb_32.h"
 
@@ -90,46 +86,91 @@ evas_common_convert_rgba_to_32bpp_rgb_8888_rot_90 (DATA32 *src, DATA8 *dst, int
 
    CONVERT_LOOP_END_ROT_90();
 #else
+   if ((w & 1) || (h & 1))
+     {
+       /* Rarely (if ever) if ever: so slow path is fine */
+        DATA32 *src_ptr;
+        DATA32 *dst_ptr;
+        int x, y;
+
+        dst_ptr = (DATA32 *)dst;
+        CONVERT_LOOP_START_ROT_90();
+
+        *dst_ptr = *src_ptr;
+
+        CONVERT_LOOP_END_ROT_90();
+   } else {
 #define AP     "convert_rgba32_rot_90_"
-   asm volatile (
-       AP"outer:                                               \n\t"
-               // Set up src
-       "       sub             %[s1],          %[src], %[y],lsl #2     \n\t"
-       "       sub             %[s2],          %[src2], %[y],lsl #2    \n\t"
+       asm volatile (
+       "       mov             %[s1],  %[src]                  \n\t"
+       "       add             %[s1],  %[h],lsl #2             \n\t"
+       "       sub             %[s1],  #8                      \n\t"
+
+       "       mov             %[s2],  %[src]                  \n\t"
+       "       add             %[s2],  %[h], lsl #3            \n\t"
+       "       add             %[s2],  %[sjmp], lsr #1         \n\t"
+       "       sub             %[s2],  #8                      \n\t"
+
+       "       mov             %[d1],  %[dst]                  \n\t"
+
+       "       add             %[d2],  %[d1], %[djmp]          \n\t"
+       "       add             %[d2],  %[w], lsl #2            \n\t"
+
+       "       mov             %[sadv], %[h], lsl #3           \n\t"
+       "       add             %[sadv], %[sjmp], lsl #1        \n\t"
+
+       "       mov             %[y],   #0                      \n\t"
+       "       mov             %[x],   #0                      \n\t"
+       AP"loop:                                                \n\t"
+       "       vld1.u32        d0,     [%[s1]]                 \n\t"
+       "       vld1.u32        d1,     [%[s2]]                 \n\t"
+       "       add             %[x],   #2                      \n\t"
+       "       add             %[s1],  %[sadv]                 \n\t"
+       "       add             %[s2],  %[sadv]                 \n\t"
+       "       vtrn.u32        d0,     d1                      \n\t"
+       "       cmp             %[x],   %[w]                    \n\t"
+       "       vst1.u32        d1,     [%[d1]]!                \n\t"
+       "       vst1.u32        d0,     [%[d2]]!                \n\t"
+       "       blt             "AP"loop                        \n\t"
+
+       "       mov             %[x],   #0                      \n\t"
+       "       add             %[d1],  %[djmp]                 \n\t"
+       "       add             %[d1],  %[w], lsl #2            \n\t"
+       "       add             %[d2],  %[djmp]                 \n\t"
+       "       add             %[d2],  %[w], lsl #2            \n\t"
+
+       "       mov             %[s1],  %[src]                  \n\t"
+       "       add             %[s1],  %[h], lsl #2            \n\t"
+       "       sub             %[s1],  %[y], lsl #2            \n\t"
+       "       sub             %[s1],  #16                     \n\t"
+
+       "       add             %[s2],  %[s1], %[h], lsl #2     \n\t"
+       "       add             %[s2],  %[sjmp], lsl #2         \n\t"
+
        "       add             %[y],   #2                      \n\t"
-       "       add             %[x],   %[d1], %[w], lsl #2             \n\t"
-       AP"inner:                                               \n\t"
-       "       vldm            %[s1], {d0}                     \n\t"
-       "       vldm            %[s2], {d1}                     \n\t"
-       "       vtrn.u32        d1,d0                           \n\t"
-       "       vstm            %[d1]!, {d0}                    \n\t"
-       "       vstm            %[d2]!, {d1}                    \n\t"
-       "       add             %[s1],          %[sadv]         \n\t"
-       "       add             %[s2],          %[sadv]         \n\t"
-       "       cmp             %[x],           %[d1]           \n\t"
-       "       bhi             "AP"inner                       \n\t"
-
-       "       add             %[d1], %[djump]                 \n\t"
-       "       add             %[d2], %[djump]                 \n\t"
-       "       cmp             %[y],   %[h]                    \n\t"
-       "       blt             "AP"outer                       \n\t"
 
+       "       cmp             %[y],   %[h]                    \n\t"
+       "       blt             "AP"loop                        \n\t"
 
        : // Out
-       :       [s1] "r" (src),
-               [s2] "r" (src + (h + src_jump) * 4),
-               [d1] "r" (dst),
-               [d2] "r" ((DATA32*)dst + w + dst_jump),
-               [sadv] "r" ((h + 2 * src_jump) * 8),
-               [src] "r" ((DATA32*)src + (h - 1)- 1),
-               [src2] "r" ((DATA32*)src + (h - 1)- 2),
-               [djump] "r" ((w + 2 * dst_jump) * 4),
-               [x] "r" (7),
-               [y] "r" (0),
+       :       [s1] "r" (1),
+               [s2] "r" (11),
+               [d1] "r" (2),
+               [d2] "r" (12),
+               [src] "r" (src),
+               [dst] "r" (dst),
+               [x] "r" (3),
+               [y] "r" (4),
                [w] "r" (w),
-               [h] "r" (h)
-       : "q0", "q1", "memory", "cc"// Clober
-   );
+               [h] "r" (h),
+               [sadv] "r" (5),
+               [sjmp] "r" (src_jump * 4),
+               [djmp] "r" (dst_jump * 4 * 2)
+       : "d0", "d1", "memory", "cc"// Clober
+
+
+       );
+   }
 #undef AP
 #endif
    return;
index 8f4150f..75595c7 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_RGB_32_H
 #define _EVAS_CONVERT_RGB_32_H
 
index c2f08fb..f69f398 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_rgb_8.h"
 
@@ -25,8 +21,8 @@ void evas_common_convert_rgba_to_8bpp_rgb_332_dith     (DATA32 *src, DATA8 *dst,
 
    CONVERT_LOOP_START_ROT_0();
 
-   dith = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(3);
-   dith2 = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(2);
+   dith = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 3);
+   dith2 = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 2);
 /*   r = (R_VAL(src_ptr)) >> (8 - 3);*/
 /*   g = (G_VAL(src_ptr)) >> (8 - 3);*/
 /*   b = (B_VAL(src_ptr)) >> (8 - 2);*/
@@ -98,8 +94,8 @@ void evas_common_convert_rgba_to_8bpp_rgb_232_dith     (DATA32 *src, DATA8 *dst,
 
    CONVERT_LOOP_START_ROT_0();
 
-   dith = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(3);
-   dith2 = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(2);
+   dith = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 3);
+   dith2 = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 2);
 /*   r = (R_VAL(src_ptr)) >> (8 - 2);*/
 /*   g = (G_VAL(src_ptr)) >> (8 - 3);*/
 /*   b = (B_VAL(src_ptr)) >> (8 - 2);*/
@@ -131,7 +127,7 @@ void evas_common_convert_rgba_to_8bpp_rgb_222_dith     (DATA32 *src, DATA8 *dst,
 
    CONVERT_LOOP_START_ROT_0();
 
-   dith = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(2);
+   dith = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 2);
 /*   r = (R_VAL(src_ptr)) >> (8 - 2);*/
 /*   g = (G_VAL(src_ptr)) >> (8 - 2);*/
 /*   b = (B_VAL(src_ptr)) >> (8 - 2);*/
@@ -163,8 +159,8 @@ void evas_common_convert_rgba_to_8bpp_rgb_221_dith     (DATA32 *src, DATA8 *dst,
 
    CONVERT_LOOP_START_ROT_0();
 
-   dith = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(2);
-   dith2 = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(1);
+   dith = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 2);
+   dith2 = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 1);
 /*   r = (R_VAL(src_ptr)) >> (8 - 2);*/
 /*   g = (G_VAL(src_ptr)) >> (8 - 2);*/
 /*   b = (B_VAL(src_ptr)) >> (8 - 1);*/
@@ -196,8 +192,8 @@ void evas_common_convert_rgba_to_8bpp_rgb_121_dith     (DATA32 *src, DATA8 *dst,
 
    CONVERT_LOOP_START_ROT_0();
 
-   dith = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(2);
-   dith2 = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(1);
+   dith = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 2);
+   dith2 = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 1);
 /*   r = (R_VAL(src_ptr)) >> (8 - 1);*/
 /*   g = (G_VAL(src_ptr)) >> (8 - 2);*/
 /*   b = (B_VAL(src_ptr)) >> (8 - 1);*/
@@ -230,7 +226,7 @@ void evas_common_convert_rgba_to_8bpp_rgb_111_dith     (DATA32 *src, DATA8 *dst,
 
    CONVERT_LOOP_START_ROT_0();
 
-   dith = DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK] >> DM_SHF(1);
+   dith = DM_SHR(DM_TABLE[(x + dith_x) & DM_MSK][(y + dith_y) & DM_MSK], 1);
 /*   r = (R_VAL(src_ptr)) >> (8 - 1);*/
 /*   g = (G_VAL(src_ptr)) >> (8 - 1);*/
 /*   b = (B_VAL(src_ptr)) >> (8 - 1);*/
index b7f85b0..edb3a89 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_RGB_8_H
 #define _EVAS_CONVERT_RGB_8_H
 
index 4a24732..2679145 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_yuv.h"
 
index e03ff8b..ab75c4e 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_CONVERT_YUV_H
 #define _EVAS_CONVERT_YUV_H
 
index 1d286d6..9ccd40d 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #if defined BUILD_MMX || defined BUILD_SSE
 #include "evas_mmx.h"
@@ -176,6 +172,8 @@ evas_common_cpu_init(void)
    cpu_feature_mask |= CPU_FEATURE_NEON *
      evas_common_cpu_feature_test(evas_common_cpu_neon_test);
    evas_common_cpu_end_opt();
+   if (getenv("EVAS_CPU_NO_NEON"))
+     cpu_feature_mask &= ~CPU_FEATURE_NEON;
 #endif
 #endif
 }
index 4683bc3..1c907d8 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_DRAW_H
 #define _EVAS_DRAW_H
 
index 7fe510c..a2723e4 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_main.h"
 #include "evas_private.h"
@@ -46,7 +42,6 @@ evas_common_init(void)
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
diff --git a/src/lib/engines/common/evas_encoding.c b/src/lib/engines/common/evas_encoding.c
new file mode 100644 (file)
index 0000000..24989b1
--- /dev/null
@@ -0,0 +1,211 @@
+#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
+    */
+   int index = *iindex, len, r;
+   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];
+       r = d & 0x1f; /* copy lower 5 */
+       r <<= 6;
+       r |= (d2 & 0x3f); /* copy lower 6 */
+     }
+   else if (len == 3)
+     {
+       /* 3 bytes */
+        d2 = buf[*iindex + 1];
+        d3 = buf[*iindex + 2];
+       r = d & 0x0f; /* copy lower 4 */
+       r <<= 6;
+       r |= (d2 & 0x3f);
+       r <<= 6;
+       r |= (d3 & 0x3f);
+     }
+   else
+     {
+       /* 4 bytes */
+        d2 = buf[*iindex + 1];
+        d3 = buf[*iindex + 2];
+        d4 = buf[*iindex + 3];
+       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;
+}
+
+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 index = 0, len = 0;
+
+   while (buf[index])
+     {
+       if ((buf[index] & 0xc0) != 0x80)
+         len++;
+       index++;
+     }
+   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
new file mode 100644 (file)
index 0000000..e278727
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef EVAS_ENCODING_H
+#define EVAS_ENCODING_H
+#include <Eina.h>
+
+/* 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
index e776fe4..6993388 100644 (file)
@@ -1,9 +1,6 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_FONT_H
 #define _EVAS_FONT_H
+#include "evas_bidi_utils.h"
 
 
 /* main */
@@ -18,16 +15,17 @@ EAPI int               evas_common_font_max_ascent_get       (RGBA_Font *fn);
 EAPI int               evas_common_font_max_descent_get      (RGBA_Font *fn);
 EAPI int               evas_common_font_get_line_advance     (RGBA_Font *fn);
 
-EAPI int               evas_common_font_utf8_get_next        (const unsigned char *buf, int *iindex);
-EAPI int               evas_common_font_utf8_get_prev        (const unsigned char *buf, int *iindex);
-EAPI int               evas_common_font_utf8_get_last        (const unsigned char *buf, int buflen);
-EAPI int               evas_common_font_utf8_get_len         (const unsigned char *buf);
+EINA_DEPRECATED EAPI int               evas_common_font_utf8_get_next        (const unsigned char *buf, int *iindex);
+EINA_DEPRECATED EAPI int               evas_common_font_utf8_get_prev        (const unsigned char *buf, int *iindex);
+EINA_DEPRECATED EAPI int               evas_common_font_utf8_get_last        (const unsigned char *buf, int buflen);
+EINA_DEPRECATED EAPI int               evas_common_font_utf8_get_len         (const unsigned char *buf);
 
 /* draw */
 
-EAPI void              evas_common_font_draw                 (RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text);
+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 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);
 
 /* load */
 EAPI void              evas_common_font_dpi_set              (int dpi);
@@ -58,16 +56,17 @@ EAPI void              evas_common_font_cache_set            (int size);
 EAPI void              evas_common_font_flush                (void);
 EAPI void              evas_common_font_flush_last           (void);
 EAPI RGBA_Font_Int    *evas_common_font_int_find             (const char *name, int size);
+EAPI void              evas_common_font_all_clear            (void);
 
 /* query */
 
 EAPI int               evas_common_font_query_kerning        (RGBA_Font_Int* fi, FT_UInt prev, FT_UInt index, int* kerning);
-EAPI void              evas_common_font_query_size           (RGBA_Font *fn, const char *text, int *w, int *h);
-EAPI int               evas_common_font_query_inset          (RGBA_Font *fn, const char *text);
-EAPI void              evas_common_font_query_advance        (RGBA_Font *fn, const char *text, int *h_adv, int *v_adv);
-EAPI int               evas_common_font_query_char_coords    (RGBA_Font *fn, const char *text, int pos, int *cx, int *cy, int *cw, int *ch);
-EAPI int               evas_common_font_query_text_at_pos    (RGBA_Font *fn, const char *text, 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 char *text, int x, int y);
+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);
 
 void evas_common_font_load_init(void);
 void evas_common_font_load_shutdown(void);
index d629718..c1a801c 100644 (file)
@@ -1,22 +1,70 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_private.h"
 #include "evas_blend_private.h"
 
-#include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */
+#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
 #include "evas_font_private.h" /* for Frame-Queuing support */
 
-#ifdef EVAS_FRAME_QUEUING
+#define WORD_CACHE_MAXLEN      50
+/* How many to cache */
+#define WORD_CACHE_NWORDS      40
+static int max_cached_words = WORD_CACHE_NWORDS;
+
+struct prword {
+       EINA_INLIST;
+       /* FIXME: Need to save font/size et al */
+       int size;
+       struct cinfo *cinfo;
+       RGBA_Font *font;
+       const Eina_Unicode *str;
+       int len;
+       DATA8 *im;
+       int roww;
+       int width;
+       int height;
+       int baseline;
+};
+
+struct cinfo {
+       int gl;
+       FT_UInt index;
+       struct { int x, y; } pos;
+       int posx;
+       RGBA_Font_Glyph *fg;
+       struct {
+               int w,h;
+               int rows;
+               unsigned char *data;
+       } bm;
+};
+
+
+#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);
+#endif
+
 EAPI void
 evas_common_font_draw_init(void)
 {
+   char *p;
+   int tmp;
+#ifdef EVAS_FRAME_QUEUING
    LKI(lock_font_draw);
    LKI(lock_fribidi);
+#endif
+   if ((p = getenv("EVAS_WORD_CACHE_MAX_WORDS")))
+     {
+       tmp = strtol(p,NULL,10);
+       /* 0 to disable of course */
+       if (tmp > -1 && tmp < 500){
+            max_cached_words = tmp;
+       }
+     }
 }
 
+#ifdef EVAS_FRAME_QUEUING
 EAPI void
 evas_common_font_draw_finish(void)
 {
@@ -203,7 +251,7 @@ static FT_UInt
 _evas_common_get_char_index(RGBA_Font_Int* fi, int gl)
 {
    Font_Char_Index result;
-   FT_UInt ret;
+   //FT_UInt ret;
 
 #ifdef HAVE_PTHREAD
 ///   pthread_mutex_lock(&fi->ft_mutex);
@@ -339,71 +387,171 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl)
 }
 
 
-
+/* 
+ * BiDi handling: We recieve the shaped string + other props from intl_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 char *in_text,
-                               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
+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, 
+                               int ext_h, RGBA_Font_Int *fi, int im_w, int im_h __UNUSED__, int use_kerning
                                )
 {
    int pen_x, pen_y;
-   int chr;
-   const char *text = in_text;
+   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 */
 
-#ifdef INTERNATIONAL_SUPPORT
-   int len = 0;
-   /*FIXME: should get the direction by parmater */
-   EvasIntlParType direction = FRIBIDI_TYPE_ON;
-   EvasIntlLevel *level_list;
-
-   /* change the text to visual ordering and update the level list
-    * for as minimum impact on the code as possible just use text as an
-    * holder, will change in the future.*/
-   char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, NULL, &level_list);
-   text = (visual_text) ? visual_text : in_text;
-   
+
+#if defined(METRIC_CACHE) || defined(WORD_CACHE)
+   unsigned int len;
+
+   /* 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){
+     struct prword *word = evas_font_word_prerender(dc, text, intl_props, len, fn, fi,
+          use_kerning);
+     if (word){
+         int j,rowstart,rowend,xstart,xrun;
+         im = dst->image.data;
+         xrun = word->width;
+         y -= word->baseline;
+         xstart = 0;
+         rowstart = 0;
+         rowend = word->height;
+         /* Clip to extent */
+         if (x + xrun > ext_x + ext_w){
+              xrun -= x + xrun - ext_x - ext_w;
+         }
+         if (x < ext_x) {
+              int excess = ext_x - x;
+              xstart = excess - 1;
+              xrun -= excess;
+              x = ext_x;
+         }
+         if (y + rowend > ext_y + ext_h){
+             rowend -= (y - ext_y + rowend - ext_h);
+         }
+         if (y < ext_y){
+             int excess = ext_y - y;
+             rowstart += excess;
+             //rowend -= excess;
+       //      y = ext_y;
+         }
+
+         if (xrun < 1) return;
+# ifdef WORD_CACHE
+         if (word->im){
+            for (j = rowstart ; j < rowend ; j ++){
+                 func(NULL, word->im + (word->roww * j) + xstart, dc->col.col,
+                       im + ((y + j) * im_w) + x, xrun);
+            }
+            return;
+         }
+# elif defined(METRIC_CACHE)
+         int ind;
+         y += word->baseline;
+         for (ind = 0 ; ind < len ; ind ++){
+            // FIXME Do we need to draw?
+            struct cinfo *ci = word->cinfo + ind;
+            for (j = rowstart ; j < rowend ; j ++)
+              {
+                if ((ci->fg->ext_dat) && (dc->font_ext.func.gl_draw))
+                  {
+                    /* ext glyph draw */
+                     dc->font_ext.func.gl_draw(dc->font_ext.data,
+                           (void *)dst,
+                           dc, ci->fg,
+                           x + ci->pos.x,
+                           y - ci->bm.h + j
+                           );
+                  }
+               else
+                  {
+                    func(NULL, word->im + (word->roww * j) + xstart,
+                          dc->col.col, im + ((y + j) * im_w) + x, xrun);
+                 }
+            }
+         }
+       return;
+# endif
+     }
+
+   }
 #endif
 
+#ifdef BIDI_SUPPORT
+   Eina_Unicode *visual_text;
+
+   visual_text = eina_unicode_strdup(in_text);
+
+   if (visual_text)
+     {
+        evas_bidi_props_reorder_line(visual_text, intl_props, NULL);
+        text = visual_text;
+     }
+   else
+     {
+        text = in_text;
+     }
+#endif
+
+
    pen_x = x;
    pen_y = y;
+   last_adv = 0;
    prev_index = 0;
    im = dst->image.data;
-   for (char_index = 0, c = 0, chr = 0; text[chr]; char_index++)
+   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 = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+       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;
+          }
        /* 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))
            {
-#ifdef INTERNATIONAL_SUPPORT
-              /* if it's rtl, the kerning matching should be reversed, i.e prev
-               * index is now the index and the other way around. */
-              if (evas_intl_is_rtl_char(level_list, char_index))
-                {
-                   if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
-                     pen_x += kern;
-                }
+#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->props->embedding_levels, char_index) &&
+                  fg->glyph->advance.x >> 16 > 0)
+               {
+                   if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
+                   pen_x += kern;
+                }
               else
 #endif
                 {
@@ -412,11 +560,8 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
                      pen_x += kern;
                 }
            }
-
          pface = fi->src->ft.face;
-         fg = evas_common_font_int_cache_glyph_get(fi, index);
          LKU(fi->ft_mutex);
-         if (!fg) continue;
 
          if (dc->font_ext.func.gl_new)
            {
@@ -424,7 +569,13 @@ 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));
 
@@ -557,17 +708,18 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font
            }
          else
            break;
-         pen_x += fg->glyph->advance.x >> 16;
+
          prev_index = index;
      }
-#ifdef INTERNATIONAL_SUPPORT
-   if (level_list) free(level_list);
+#ifdef BIDI_SUPPORT
    if (visual_text) free(visual_text);
 #endif
 }
 
+
 EAPI void
-evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text)
+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)
 {
    int ext_x, ext_y, ext_w, ext_h;
    int im_w, im_h;
@@ -618,7 +770,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,
+        evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props,
                                        func, ext_x, ext_y, ext_w, ext_h, fi,
                                        im_w, im_h, use_kerning
                                        );
@@ -635,7 +787,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,
+                  evas_common_font_draw_internal(dst, dc, fn, x, y, text, intl_props,
                                                  func, r->x, r->y, r->w, r->h, fi,
                                                  im_w, im_h, use_kerning
                                                  );
@@ -648,3 +800,165 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
    LKU(fn->lock);
 #endif
 }
+
+
+/* FIXME: Where is it freed at? */
+/* 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){
+   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 gl;
+
+# ifndef METRIC_CACHE
+   gl = dc->font_ext.func.gl_new ? 1: 0;
+   if (gl) return NULL;
+# endif
+
+
+   LKL(lock_words);
+   EINA_INLIST_FOREACH(words,w){
+       if (w->len == len && w->font == fn && fi->size == w->size &&
+             (w->str == in_text || memcmp(w->str, in_text, len * sizeof(Eina_Unicode)) == 0)){
+         words = eina_inlist_promote(words, EINA_INLIST_GET(w));
+         LKU(lock_words);
+         return w;
+       }
+   }
+   LKU(lock_words);
+
+   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);
+   /* First pass: Work out how big */
+   for (char_index = 0, c = 0, chr = 0 ; *text ; text++, char_index ++){
+       struct cinfo *ci = metrics + char_index;
+       ci->gl = *text;
+       if (ci->gl == 0) break;
+       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);
+       LKU(fi->ft_mutex);
+       if (!ci->fg) 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) && (ci->index) &&
+            (pface == fi->src->ft.face))
+          {
+              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 && 
+                  evas_bidi_is_rtl_char(intl_props->props->embedding_levels, char_index) &&
+                  ci->fg->glyph->advance.x >> 16 > 0)
+               {
+                  if (evas_common_font_query_kerning(fi, ci->index, prev_index, &kern))
+                     ci->pos.x += kern;
+               }
+             else
+# endif
+              {
+
+                  if (evas_common_font_query_kerning(fi, prev_index, ci->index, &kern))
+                     ci->pos.x += kern;
+             }
+           }
+
+       pface = fi->src->ft.face;
+       if (gl){
+           ci->fg->ext_dat =dc->font_ext.func.gl_new(dc->font_ext.data,ci->fg);
+           ci->fg->ext_dat_free = dc->font_ext.func.gl_free;
+       }
+       ci->bm.data = ci->fg->glyph_out->bitmap.buffer;
+       ci->bm.w = MAX(ci->fg->glyph_out->bitmap.pitch,
+                     ci->fg->glyph_out->bitmap.width);
+       ci->bm.rows = ci->fg->glyph_out->bitmap.rows;
+       ci->bm.h = ci->fg->glyph_out->top;
+       above = ci->bm.rows - (ci->bm.rows - ci->bm.h);
+       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;
+  }
+
+  /* First loop done */
+  width = pen_x;
+  width = (width & 0x7) ? width + (8 - (width & 0x7)) : width;
+
+  height = baseline + descent;
+  if (!gl){
+     im = calloc(height, width);
+     for (i = 0 ; i  < char_index ; 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);
+         }
+
+     }
+  } else {
+       im = NULL;
+  }
+   /* Save it */
+   struct prword *save;
+
+
+   save = malloc(sizeof(struct prword));
+   save->cinfo = metrics;
+   save->str = eina_ustringshare_add(in_text);
+   save->font = fn;
+   save->size = fi->size;
+   save->len = len;
+   save->im = im;
+   save->width = pen_x;
+   save->roww = width;
+   save->height = height;
+   save->baseline = baseline;
+   LKL(lock_words);
+   words = eina_inlist_prepend(words, EINA_INLIST_GET(save));
+
+   /* Clean up if too long */
+   if (eina_inlist_count(words) > max_cached_words){
+       struct prword *last = (struct prword *)(words->last);
+       if (last->im) free(last->im);
+       if (last->cinfo) free(last->cinfo);
+       eina_ustringshare_del(last->str);
+       words = eina_inlist_remove(words,EINA_INLIST_GET(last));
+       free(last);
+   }
+   LKU(lock_words);
+
+   return save;
+}
+#endif
+
+
+
index a6b07e1..4acbc9f 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_private.h"
 
index 1201514..1dab2fe 100644 (file)
@@ -1,9 +1,9 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_private.h"
+#include "evas_encoding.h"
+
+#include "evas_font_private.h"
+
 FT_Library      evas_ft_lib = 0;
 static int      initialised = 0;
 
@@ -20,9 +20,7 @@ evas_common_font_init(void)
    error = FT_Init_FreeType(&evas_ft_lib);
    if (error) return;
    evas_common_font_load_init();
-#ifdef EVAS_FRAME_QUEUING
    evas_common_font_draw_init();
-#endif
    LKI(lock_font_draw);
    LKI(lock_fribidi);
 }
@@ -59,8 +57,7 @@ evas_common_font_font_all_unload(void)
 EAPI int
 evas_common_font_ascent_get(RGBA_Font *fn)
 {
-   int val, dv;
-   int ret;
+   int val;
    RGBA_Font_Int *fi;
 
 //   evas_common_font_size_use(fn);
@@ -73,7 +70,9 @@ evas_common_font_ascent_get(RGBA_Font *fn)
              if (!fi->src->ft.face) continue;
              if (fi->src->current_size != fi->size)
                {
+                 FTLOCK();
                   FT_Activate_Size(fi->ft.size);
+                 FTUNLOCK();
                   fi->src->current_size = fi->size;
                }
              val = (int)fi->src->ft.face->size->metrics.ascender;
@@ -88,7 +87,9 @@ evas_common_font_ascent_get(RGBA_Font *fn)
    fi = fn->fonts->data;
    if (fi->src->current_size != fi->size)
      {
+       FTLOCK();
         FT_Activate_Size(fi->ft.size);
+       FTUNLOCK();
         fi->src->current_size = fi->size;
      }
    if (!FT_IS_SCALABLE(fi->src->ft.face))
@@ -108,15 +109,16 @@ evas_common_font_ascent_get(RGBA_Font *fn)
 EAPI int
 evas_common_font_descent_get(RGBA_Font *fn)
 {
-   int val, dv;
-   int ret;
+   int val;
    RGBA_Font_Int *fi;
 
 //   evas_common_font_size_use(fn);
    fi = fn->fonts->data;
    if (fi->src->current_size != fi->size)
      {
+       FTLOCK();
         FT_Activate_Size(fi->ft.size);
+       FTUNLOCK();
         fi->src->current_size = fi->size;
      }
    val = -(int)fi->src->ft.face->size->metrics.descender;
@@ -139,7 +141,9 @@ evas_common_font_max_ascent_get(RGBA_Font *fn)
    fi = fn->fonts->data;
    if (fi->src->current_size != fi->size)
      {
+       FTLOCK();
         FT_Activate_Size(fi->ft.size);
+       FTUNLOCK();
         fi->src->current_size = fi->size;
      }
    val = (int)fi->src->ft.face->bbox.yMax;
@@ -161,7 +165,9 @@ evas_common_font_max_descent_get(RGBA_Font *fn)
    fi = fn->fonts->data;
    if (fi->src->current_size != fi->size)
      {
+       FTLOCK();
         FT_Activate_Size(fi->ft.size);
+       FTUNLOCK();
         fi->src->current_size = fi->size;
      }
    val = -(int)fi->src->ft.face->bbox.yMin;
@@ -175,15 +181,16 @@ evas_common_font_max_descent_get(RGBA_Font *fn)
 EAPI int
 evas_common_font_get_line_advance(RGBA_Font *fn)
 {
-   int val, dv;
-   int ret;
+   int val;
    RGBA_Font_Int *fi;
 
 //   evas_common_font_size_use(fn);
    fi = fn->fonts->data;
    if (fi->src->current_size != fi->size)
      {
+       FTLOCK();
         FT_Activate_Size(fi->ft.size);
+       FTUNLOCK();
         fi->src->current_size = fi->size;
      }
    val = (int)fi->src->ft.face->size->metrics.height;
@@ -195,139 +202,3 @@ evas_common_font_get_line_advance(RGBA_Font *fn)
 //   return ret;
 }
 
-EAPI int
-evas_common_font_utf8_get_next(const unsigned 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
-    */
-   int index = *iindex, len, r;
-   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];
-       r = d & 0x1f; /* copy lower 5 */
-       r <<= 6;
-       r |= (d2 & 0x3f); /* copy lower 6 */
-     }
-   else if (len == 3)
-     {
-       /* 3 bytes */
-        d2 = buf[*iindex + 1];
-        d3 = buf[*iindex + 2];
-       r = d & 0x0f; /* copy lower 4 */
-       r <<= 6;
-       r |= (d2 & 0x3f);
-       r <<= 6;
-       r |= (d3 & 0x3f);
-     }
-   else
-     {
-       /* 4 bytes */
-        d2 = buf[*iindex + 1];
-        d3 = buf[*iindex + 2];
-        d4 = buf[*iindex + 3];
-       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;
-}
-
-EAPI int
-evas_common_font_utf8_get_prev(const unsigned 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_font_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 int
-evas_common_font_utf8_get_last(const unsigned 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_font_utf8_get_len(const unsigned char *buf)
-{
-   /* returns the number of utf8 characters (not bytes) in the string */
-   int index = 0, len = 0;
-
-   while (buf[index])
-     {
-       if ((buf[index] & 0xc0) != 0x80)
-         len++;
-       index++;
-     }
-   return len;
-}
index 31bdaed..99ec2a4 100644 (file)
@@ -6,7 +6,7 @@ extern LK(lock_font_draw); // for freetype2 API calls
 extern LK(lock_fribidi); // for fribidi API calls
 #endif
 
-# ifdef EVAS_FRAME_QUEUING
+# if defined(EVAS_FRAME_QUEUING) || defined(BUILD_PIPE_RENDER)
 #  define FTLOCK() LKL(lock_font_draw)
 #  define FTUNLOCK() LKU(lock_font_draw)
 
index d1b2f99..5d3b71b 100644 (file)
@@ -1,5 +1,5 @@
 #include "evas_common.h"
-#include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */
+#include "evas_bidi_utils.h" /*defines BIDI_SUPPORT if possible */
 #include "evas_font_private.h" /* for Frame-Queuing support */
 
 EAPI int
@@ -56,9 +56,15 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi,
    return error;
 }
 
-/* string extents */
+/* size of the string (width and height) in pixels
+ * BiDi handling: We recieve the shaped string + other props from intl_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 char *text, int *w, int *h)
+evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h)
 {
    int use_kerning;
    int pen_x, pen_y;
@@ -78,20 +84,22 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
 //   evas_common_font_size_use(fn);
    use_kerning = FT_HAS_KERNING(fi->src->ft.face);
    prev_index = 0;
-   for (chr = 0; text[chr];)
+   for (chr = 0; *text; text++)
      {
        FT_UInt index;
        RGBA_Font_Glyph *fg;
-       int chr_x, chr_y, chr_w;
+       int chr_x, chr_y, advw;
         int gl, kern;
 
-       gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+       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;
           }
       /* hmmm kerning means i can't sanely do my own cached metric tables! */
@@ -99,9 +107,9 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
        /* you want performance */
        kern = 0;
        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) && 
+            evas_common_font_query_kerning(fi, prev_index, index, &kern))
+          pen_x += kern;
 
        pface = fi->src->ft.face;
        fg = evas_common_font_int_cache_glyph_get(fi, index);
@@ -109,21 +117,28 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
        if (!fg) continue;
 
        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;
-       chr_w = fg->glyph_out->bitmap.width + kern;
-         {
-            int advw;
+       
+        /* 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;
+          }
 
-            advw = ((fg->glyph->advance.x + (kern << 16)) >> 16);
-            if (chr_w < advw) chr_w = advw;
-         }
 
        if ((!prev_index) && (chr_x < 0))
          start_x = chr_x;
-       if ((chr_x + chr_w) > end_x)
-         end_x = chr_x + chr_w;
+       if ((chr_x + advw) > end_x)
+         end_x = chr_x + advw;
 
        pen_x += fg->glyph->advance.x >> 16;
        prev_index = index;
@@ -134,7 +149,7 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h)
 
 /* text x inset */
 EAPI int
-evas_common_font_query_inset(RGBA_Font *fn, const char *text)
+evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text)
 {
    FT_UInt index;
    RGBA_Font_Glyph *fg;
@@ -145,17 +160,21 @@ evas_common_font_query_inset(RGBA_Font *fn, const char *text)
    fi = fn->fonts->data;
 
    chr = 0;
-   if (!text[0]) return 0;
-   gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+   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);
    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);
+   LKU(fi->ft_mutex);
    if (!fg) return 0;
 /*
    INF("fg->glyph_out->left = %i\n"
@@ -174,14 +193,20 @@ evas_common_font_query_inset(RGBA_Font *fn, const char *text)
    return fg->glyph_out->left;
 }
 
-/* h & v advance */
+/* h & v advance
+ * BiDi handling: We recieve the shaped string + other props from intl_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 char *text, int *h_adv, int *v_adv)
+evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *h_adv, int *v_adv)
 {
    int use_kerning;
    int pen_x, pen_y;
    int start_x;
-   int chr;
+   int char_index;
    FT_UInt prev_index;
    RGBA_Font_Int *fi;
    FT_Face pface = NULL;
@@ -196,38 +221,60 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int
    use_kerning = FT_HAS_KERNING(fi->src->ft.face);
    FTUNLOCK();
    prev_index = 0;
-   for (chr = 0; text[chr];)
+   for (char_index = 0 ; *text ; text++, char_index++)
      {
        FT_UInt index;
        RGBA_Font_Glyph *fg;
-       int chr_x, chr_y, chr_w;
         int gl, kern;
 
-       gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+       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;
           }
-      /* hmmm kerning means i can't sanely do my own cached metric tables! */
+       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) &&
-           (pface == fi->src->ft.face))
-         if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
-           pen_x += kern;
+            (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->props->embedding_levels, char_index) &&
+                  fg->glyph->advance.x >> 16 > 0)
+               {
+                  if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
+                     pen_x += kern;
+               }
+             else
+#endif
+              {
+
+                  if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
+                     pen_x += kern;
+             }
+           }
 
        pface = fi->src->ft.face;
-       fg = evas_common_font_int_cache_glyph_get(fi, index);
        LKU(fi->ft_mutex);
-       if (!fg) continue;
-
-        chr_x = (pen_x + (fg->glyph_out->left));
-       chr_y = (pen_y + (fg->glyph_out->top));
-       chr_w = fg->glyph_out->bitmap.width;
 
        pen_x += fg->glyph->advance.x >> 16;
        prev_index = index;
@@ -236,30 +283,48 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int
    if (h_adv) *h_adv = pen_x - start_x;
 }
 
-/* x y w h for char at char pos */
+/* x y w h for char at char pos
+ * BiDi handling: We recieve the shaped string + other props from intl_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_char_coords(RGBA_Font *fn, const char *in_text, int pos, int *cx, int *cy, int *cw, int *ch)
+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)
 {
    int use_kerning;
    int pen_x, pen_y;
    int prev_chr_end;
-   int chr;
    int asc, desc;
    int char_index = 0; /* the index of the current char */
-   int position;
-   const char *text = in_text;
+   int position = 0;
+   const Eina_Unicode *text = in_text;
    int ret_val = 0;
+   int last_adv;
    FT_UInt prev_index;
    RGBA_Font_Int *fi;
    FT_Face pface = NULL;
 
-#ifdef INTERNATIONAL_SUPPORT
+#ifdef BIDI_SUPPORT
    int len = 0;
-   EvasIntlParType direction = FRIBIDI_TYPE_ON;
-   EvasIntlLevel *level_list = NULL;
-   EvasIntlStrIndex *visual_to_logical = NULL;
-   char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, &visual_to_logical, NULL, &level_list);
-   text = (visual_text) ? visual_text : in_text;
+   EvasBiDiStrIndex *visual_to_logical = NULL;
+   Eina_Unicode *visual_text;
+
+   visual_text = eina_unicode_strdup(in_text);
+
+   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);
 #endif
 
    fi = fn->fonts->data;
@@ -269,7 +334,9 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
 //   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;
      }
    use_kerning = FT_HAS_KERNING(fi->src->ft.face);
@@ -278,37 +345,31 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
    asc = evas_common_font_max_ascent_get(fn);
    desc = evas_common_font_max_descent_get(fn);
 
-   /* find the actual index, not the byte position */
-   for (position = 0 , chr = 0 ; in_text[chr] && chr < pos ; position++) {
-      evas_common_font_utf8_get_next((unsigned char *)in_text, &chr);
-   }
-   /* if we couldn't reach the correct position for some reason,
-    * return with an error */
-   if (chr != pos) {
-      ret_val = 0;
-      goto end;
-   }
-     
-#ifdef INTERNATIONAL_SUPPORT 
-   /* if it's an in string position (not end), get logical position */
-   if (position < len)
-      position = evas_intl_position_visual_to_logical(visual_to_logical, position);
+#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
 
-
-   for (char_index = 0, chr = 0; text[chr]; char_index++)
+   last_adv = 0;
+   for (char_index = 0; *text ; text++, char_index++)
      {
-       int pchr;
        FT_UInt index;
        RGBA_Font_Glyph *fg;
        int chr_x, chr_y, chr_w;
-        int gl, kern;
+   int gl, kern;
 
-       pchr = chr;
-       gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+       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) 
+          {
+             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! */
@@ -317,10 +378,14 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
        if ((use_kerning) && (prev_index) && (index) &&
             (pface == fi->src->ft.face))
           {
-#ifdef INTERNATIONAL_SUPPORT
+#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. */
-             if (evas_intl_is_rtl_char(level_list, char_index))
+              * 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->props->embedding_levels, char_index) &&
+                  fg->glyph->advance.x >> 16 > 0)
                {
                   if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
                      pen_x += kern;
@@ -333,31 +398,37 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
                      pen_x += kern;
              }
            }
-
+        
        pface = fi->src->ft.face;
-       fg = evas_common_font_int_cache_glyph_get(fi, index);
        LKU(fi->ft_mutex);
-       if (!fg) continue;
-
+       /* 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);
+        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
        /* 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;
@@ -366,13 +437,11 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *in_text, int pos,
             goto end;
          }
        prev_chr_end = chr_x + chr_w;
-       pen_x += fg->glyph->advance.x >> 16;
        prev_index = index;
      }
 end:
 
-#ifdef INTERNATIONAL_SUPPORT
-   if (level_list) free(level_list);
+#ifdef BIDI_SUPPORT
    if (visual_to_logical) free(visual_to_logical);
    if (visual_text) free(visual_text);
 #endif
@@ -380,29 +449,45 @@ end:
    return ret_val;
 }
 
-/* char pos of text at xy pos */
+/* char pos of text at xy pos
+ * BiDi handling: Since we are looking for the char at the specific coords,
+ * we have to get the visual string (to which the coords relate to), do
+ * reverse kerning query because we are working on the visual string, and then
+ * we need to get the logical position of the char we found from the visual string.
+ */
+
 EAPI int
-evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, 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 *in_text, const Evas_BiDi_Props *intl_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 chr;
    int asc, desc;
    int char_index = 0; /* the index of the current char */
-   const char *text = in_text;
+   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;
 
-#ifdef INTERNATIONAL_SUPPORT
+#ifdef BIDI_SUPPORT
    int len = 0;
-   EvasIntlParType direction = FRIBIDI_TYPE_ON;
-   EvasIntlLevel *level_list = NULL;
-   EvasIntlStrIndex *visual_to_logical = NULL;
-   char *visual_text = evas_intl_utf8_to_visual(in_text, &len, &direction, NULL, &visual_to_logical, &level_list);
-   text = (visual_text) ? visual_text : in_text;
+   EvasBiDiStrIndex *visual_to_logical = NULL;
+   Eina_Unicode *visual_text;
+
+   visual_text = eina_unicode_strdup(in_text);
+
+   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);
 #endif
 
    fi = fn->fonts->data;
@@ -412,28 +497,36 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in
 //   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;
      }
    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, chr = 0; text[chr]; char_index++)
+
+   for (char_index = 0; *text; text++, char_index++)
      {
-       int pchr;
        FT_UInt index;
        RGBA_Font_Glyph *fg;
        int chr_x, chr_y, chr_w;
         int gl, kern;
 
-       pchr = chr;
-       gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+       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) 
+          {
+             LKU(fi->ft_mutex);
+             continue;
+          }
+           
        // FIXME: Why not FT_Activate_Size here ?
        kern = 0;
         /* hmmm kerning means i can't sanely do my own cached metric tables! */
@@ -442,10 +535,14 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in
        if ((use_kerning) && (prev_index) && (index) &&
             (pface == fi->src->ft.face))
           {
-#ifdef INTERNATIONAL_SUPPORT
+#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. */
-             if (evas_intl_is_rtl_char(level_list, char_index))
+              * 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->props->embedding_levels, char_index) &&
+                  fg->glyph->advance.x >> 16 > 0)
                {
                   if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
                      pen_x += kern;
@@ -458,16 +555,21 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in
                      pen_x += kern;
                }
            }
-
        pface = fi->src->ft.face;
-       fg = evas_common_font_int_cache_glyph_get(fi, index);
        LKU(fi->ft_mutex);
-       if (!fg) continue;
-
+       /* 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;
@@ -475,43 +577,38 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *in_text, int x, in
             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 INTERNATIONAL_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 */
-               int i;
-               int position = evas_intl_position_visual_to_logical(visual_to_logical, char_index);
-                
-               /* ensure even if the list won't run */
-                for (pchr = 0, i = 0; i < position; i++)
-                  evas_common_font_utf8_get_next((unsigned char *)in_text, &pchr);
-             }
+#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 = pchr;
+            ret_val = position;
             goto end;
          }
        prev_chr_end = chr_x + chr_w;
-       pen_x += fg->glyph->advance.x >> 16;
        prev_index = index;
      }
      
 end:
    
-#ifdef INTERNATIONAL_SUPPORT
-   if (level_list) free(level_list);
+#ifdef BIDI_SUPPORT
    if (visual_to_logical) free(visual_to_logical);
    if (visual_text) free(visual_text);
 #endif
@@ -519,17 +616,23 @@ end:
    return ret_val;
 }
 
-/* last char pos of text at xy pos
- * Note: no need for special rtl handling
- * because the string is in logical order, which is correct */
+/* position of the last char in thext text that will fit in xy.
+ * BiDi handling: We recieve the shaped string + other props from intl_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 char *text, int x, int y)
+evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text, const Evas_BiDi_Props *intl_props, int x, int y)
 {
    int use_kerning;
    int pen_x, pen_y;
    int prev_chr_end;
-   int chr;
+   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;
@@ -544,22 +647,22 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, in
    prev_chr_end = 0;
    asc = evas_common_font_max_ascent_get(fn);
    desc = evas_common_font_max_descent_get(fn);
-   for (chr = 0; text[chr];)
+   for (char_index = 0; *text; text++, char_index++)
      {
-       int pchr;
        FT_UInt index;
        RGBA_Font_Glyph *fg;
        int chr_x, chr_y, chr_w;
         int gl, kern;
 
-       pchr = chr;
-       gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr);
+       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;
@@ -568,13 +671,14 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, in
        /* 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;
-
+     {
+      /* No need for special RTL handling because we are working on the logical string*/
+      if (evas_common_font_query_kerning(fi, index, prev_index, &kern))
+         pen_x += kern;
+     }
        pface = fi->src->ft.face;
        fg = evas_common_font_int_cache_glyph_get(fi, index);
        LKU(fi->ft_mutex);
-       if (!fg) continue;
 
        if (kern < 0) kern = 0;
         chr_x = ((pen_x - kern) + (fg->glyph_out->left));
@@ -595,11 +699,14 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const char *text, int x, in
        if ((x >= chr_x) && (x <= (chr_x + chr_w)) &&
            (y >= -asc) && (y <= desc))
          {
-            return pchr;
+            ret = char_index;
+             goto end;
          }
        prev_chr_end = chr_x + chr_w;
        pen_x += fg->glyph->advance.x >> 16;
        prev_index = index;
      }
-   return -1;
+end:
+
+   return ret;
 }
index afcf6ff..fb335fb 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include <assert.h>
 
 #include "evas_common.h"
index e776fcf..e50f95f 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_private.h"
 #include "evas_cs.h"
index d2efb67..785fb1e 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifdef HAVE_CONFIG_H
 # include "config.h"  /* so that EAPI in Eet.h is correctly defined */
 #endif
@@ -142,9 +138,9 @@ _evas_common_rgba_image_new(void)
    im->flags = RGBA_IMAGE_NOTHING;
    im->ref = 1;
 #ifdef EVAS_FRAME_QUEUING
-   LKI(im->ref_fq_add);
-   LKI(im->ref_fq_del);
-   pthread_cond_init(&(im->cond_fq_del), NULL);
+   LKI(im->cache_entry.ref_fq_add);
+   LKI(im->cache_entry.ref_fq_del);
+   pthread_cond_init(&(im->cache_entry.cond_fq_del), NULL);
 #endif
 
    evas_common_rgba_image_scalecache_init(&im->cache_entry);
@@ -159,9 +155,9 @@ _evas_common_rgba_image_delete(Image_Entry *ie)
 #ifdef BUILD_PIPE_RENDER
    evas_common_pipe_free(im);
 # ifdef EVAS_FRAME_QUEUING
-   LKD(im->ref_fq_add);
-   LKD(im->ref_fq_del);
-   pthread_cond_destroy(&(im->cond_fq_del));
+   LKD(im->cache_entry.ref_fq_add);
+   LKD(im->cache_entry.ref_fq_del);
+   pthread_cond_destroy(&(im->cache_entry.cond_fq_del));
 # endif
 #endif   
    evas_common_rgba_image_scalecache_shutdown(&im->cache_entry);
@@ -295,6 +291,7 @@ static void
 _evas_common_rgba_image_unload(Image_Entry *im)
 {
 //   printf("unload: [%p] %s %s\n", im, im->file, im->key);
+   evas_common_rgba_image_scalecache_dirty(im);
    evas_common_rgba_image_unload(im);
 }
 
index a2fa3c8..d7484c0 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
index 71ae93e..132d00d 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
@@ -194,7 +190,7 @@ _sci_fix_newest(RGBA_Image *im)
 {
    Eina_List *l;
    Scaleitem *sci;
-   
+
    im->cache.newest_usage = 0;
    im->cache.newest_usage_count = 0;
    EINA_LIST_FOREACH(im->cache.list, l, sci)
@@ -269,8 +265,7 @@ _sci_find(RGBA_Image *im,
 
         if (eina_list_count(im->cache.list) > (max_scale_items - 1))
           return NULL;
-        sci = malloc(sizeof(Scaleitem));
-        memset(sci, 0, sizeof(Eina_Inlist));
+        sci = calloc(1, sizeof(Scaleitem));
         sci->parent_im = im;
 #ifdef EVAS_FRAME_QUEUING
         RWLKI(sci->lock);
index a49d8f4..3db94b0 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_blend_private.h"
 
index 3112a83..9cd2b23 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_blend_private.h"
 
index 1e33771..883b278 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_MAP_H
 #define _EVAS_MAP_H
 
index d4788fe..05fd291 100644 (file)
@@ -1,6 +1,3 @@
-/*
-  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
-  */
 //#undef SCALE_USING_MMX
 {
    if (smooth)
index 8026523..eddd7d5 100644 (file)
@@ -1,6 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
 // 66.74 % of time
 static void
 FUNC_NAME(RGBA_Image *src, RGBA_Image *dst,
index 3e6c402..2ac5b88 100644 (file)
@@ -1,6 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
 #ifdef SMOOTH
 {
    while (ww > 0)
index 538fb29..ef8b728 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 static RGBA_Gfx_Func     op_add_span_funcs[SP_LAST][SM_LAST][SC_LAST][DP_LAST][CPU_LAST];
 static RGBA_Gfx_Pt_Func  op_add_pt_funcs[SP_LAST][SM_LAST][SC_LAST][DP_LAST][CPU_LAST];
index 09eca0e..9738970 100644 (file)
@@ -1,3 +1,18 @@
+#define NEONDEBUG 0
+
+
+#if NEONDEBUG
+#define DEBUG_FNCOUNT(x)       \
+       do {                    \
+       static int _foo = 0;            \
+       if (_foo++%10000 ==0)           \
+               printf("%s %+d %s: %d (%s)\n",__FILE__,__LINE__,__FUNCTION__,\
+                               _foo, x " optimised");\
+       } while (0)
+#else
+#define        DEBUG_FNCOUNT(x)        ((void)x)
+#endif
+
 
 /* blend mask x color -> dst */
 
@@ -5,7 +20,9 @@
 static void
 _op_blend_mas_c_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, int l) {
    DATA32 *e;
-   int alpha = 256 - (c >> 24);
+
+   DEBUG_FNCOUNT("");
+
 #define AP "blend_mas_c_dp_"
      asm volatile (
        "       vdup.i32        q15, %[c]                       \n\t"
@@ -60,6 +77,8 @@ _op_blend_mas_c_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, int
        "       sub             %[tmp], %[e], %[d]              \n\t"
        "       cmp             %[tmp], #16                     \n\t"
        "       blt             "AP"loopout                     \n\t"
+
+
        "       sub             %[tmp], %[e], #15               \n\t"
 
        "       sub             %[d],   #16                     \n\t"
@@ -109,6 +128,15 @@ _op_blend_mas_c_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, int
        "       bhi             "AP"quadloopint                 \n\t"
 
        AP"loopout:                                             \n\t"
+#if NEONDEBUG
+               "cmp            %[d], %[e]              \n\t"
+               "ble            "AP"foo         \n\t"
+               "cmp            %[tmp], %[m]    \n\t"
+               "sub            %[x],   %[x]            \n\t"
+               "vst1.32        d0[0], [%[x]]           \n\t"
+       AP"foo: \n\t"
+#endif
+
        "       cmp             %[d], %[e]                      \n\t"
        "       beq             "AP"done                        \n\t"
        "       sub             %[tmp],%[e], %[d]               \n\t"
@@ -116,7 +144,7 @@ _op_blend_mas_c_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, int
        "       beq             "AP"singleout                   \n\t"
 
        AP "dualloop2:                                  \n\t"
-               "sub            %[tmp],%[e],$0x7        \n\t"
+               "sub            %[tmp],%[e],$0x8        \n\t"
        "       vld1.16         d0[0],  [%[m]]!                 \n\t"
        "       vldm            %[d],   {d4}                    \n\t"
        "       vmovl.u8        q0,     d0                      \n\t"
@@ -150,7 +178,13 @@ _op_blend_mas_c_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, int
        "       vst1.32         d0[0],  [%[d]]!                 \n\t"
 
        AP"done:                                                \n\t"
-
+#if NEONDEBUG
+               "cmp            %[d], %[e]              \n\t"
+               "beq            "AP"reallydone          \n\t"
+               "sub            %[tmp], %[tmp]          \n\t"
+               "vst1.32        d0[0], [%[tmp]]         \n\t"
+       AP"reallydone:"
+#endif
        : // Out
        :  [e] "r" (d + l), [d] "r" (d), [c] "r" (c),
                [tmp] "r" (7), [m] "r" (m), [x] "r" (0)
@@ -166,6 +200,9 @@ static void
 _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, int l) {
    DATA32 *e,*tmp;
    int alpha;
+
+   DEBUG_FNCOUNT("");
+
 #define AP     "_blend_mas_can_dp_neon_"
      asm volatile (
                "vdup.u32       q9,     %[c]            \n\t"
@@ -181,7 +218,7 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
        "       beq             "AP"quadloop            \n\t"
 
        "       andS            %[tmp], %[d], #4        \n\t"
-       "       beq             "AP"dualloop            \n\t"
+       "       beq             "AP"dualstart           \n\t"
 
 
        AP"singleloop:                                  \n\t"
@@ -198,16 +235,21 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
        "       vqmovun.s16     d2,     q6              \n\t"
        "       vst1.32         d2[0],  [%[d]]!         \n\t"
 
-       "       andS            %[tmp], %[d],   #15     \n\t"
+       "       andS            %[tmp], %[d],   $0xf    \n\t"
        "       beq             "AP"quadloop            \n\t"
 
+       AP"dualstart:                                   \n\t"
+       "       sub             %[tmp], %[e], %[d]      \n\t"
+       "       cmp             %[tmp], #16             \n\t"
+       "       blt             "AP"loopout             \n\t"
+
        AP"dualloop:                                    \n\t"
-       "       vld1.16 d0[0],  [%[m]]!         \n\t"
-       "       vldm            %[d],           {d8}    \n\t"
+       "       vld1.16         d0[0],  [%[m]]!         \n\t"
+       "       vldm            %[d],   {d8}            \n\t"
        "       vmovl.u8        q0,     d0              \n\t"
        "       vmovl.u8        q0,     d0              \n\t"
        "       vmul.u32        d0,     d0,     d30     \n\t"
-       "       vshr.u8 d0,     d0, #1          \n\t"
+       "       vshr.u8         d0,     d0, #1          \n\t"
        "       vmovl.u8        q0,     d0              \n\t"
        "       vmovl.u8        q4,     d8              \n\t"
        "       vsub.s16        q6,     q2, q4          \n\t"
@@ -227,21 +269,23 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
        AP"fastloop:                                    \n\t"
        "       add             %[d],   #16             \n\t"
        "       cmp             %[tmp], %[d]            \n\t"
-       "       ble             "AP"loopout             \n\t"
+       "       blt             "AP"loopout             \n\t"
 
        AP"quadloopint:                                 \n\t"
                // Load the mask: 4 bytes: It has d0/d1
        "       ldr             %[x],   [%[m]]          \n\t"
        "       add             %[m], #4                \n\t"
+
+               // Check for shortcuts
        "       cmp             %[x],   #0              \n\t"
        "       beq             "AP"fastloop            \n\t"
-       "       vmov.32         d0[0],  %[x]            \n\t"
 
-               // Load d into d8/d9 q4
-       "       vldm            %[d],   {d8,d9}         \n\t"
        "       cmp             %[x],   $0xffffffff     \n\t"
        "       beq             "AP"quadstore           \n\t"
 
+       "       vmov.32         d0[0],  %[x]            \n\t"
+               // Load d into d8/d9 q4
+       "       vldm            %[d],   {d8,d9}         \n\t"
 
                // Get the alpha channel ready (m)
        "       vmovl.u8        q0,     d0              \n\t"
@@ -277,7 +321,7 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
        "       vqmovun.s16     d9,  q7                 \n\t"
        "       vqmovun.s16     d8,  q6                 \n\t"
 
-       "       vstm            %[d]!,  {d8,d9} \n\t"
+       "       vstm            %[d]!,  {d8,d9}         \n\t"
 
        "       cmp             %[tmp], %[d]            \n\t"
        "       bhi             "AP"quadloopint         \n\t"
@@ -288,8 +332,14 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
        "       cmp             %[tmp], %[d]            \n\t"
        "       bhi             "AP"quadloopint         \n\t"
 
-
        AP"loopout:                                     \n\t"
+#if NEONDEBUG
+               "cmp            %[d], %[e]              \n\t"
+               "ble            "AP"foo         \n\t"
+               "sub            %[tmp], %[tmp]          \n\t"
+               "vst1.32        d0[0], [%[tmp]]         \n\t"
+       AP"foo: \n\t"
+#endif
 
        "       cmp             %[e], %[d]              \n\t"
        "       beq             "AP"done                \n\t"
@@ -300,7 +350,7 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
        "       blt             "AP"onebyte             \n\t"
 
                // Load the mask: 2 bytes: It has d0
-       "       vld1.16 d0[0],  [%[m]]!         \n\t"
+       "       vld1.16         d0[0],  [%[m]]!         \n\t"
 
                // Load d into d8/d9 q4
        "       vldm            %[d],           {d8}    \n\t"
@@ -310,7 +360,7 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
        "       vmovl.u8        q0,     d0              \n\t"
        "       vmul.u32        d0,     d0,     d30     \n\t"
                // Lop a bit off to prevent overflow
-       "       vshr.u8 d0,     d0, #1          \n\t"
+       "       vshr.u8 d0,     d0, #1                  \n\t"
 
                // Now make it 16 bit
        "       vmovl.u8        q0,     d0              \n\t"
@@ -338,7 +388,7 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
                "beq            "AP"done                \n\t"
 
        AP"onebyte:                                     \n\t"
-               "vld1.8 d0[0],  [%[m]]!                 \n\t"
+               "vld1.8         d0[0],  [%[m]]!         \n\t"
                "vld1.32        d8[0],  [%[d]]          \n\t"
                "vdup.u8        d0,     d0[0]           \n\t"
                "vshr.u8        d0,     d0, #1          \n\t"
@@ -351,13 +401,22 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
                "vqmovun.s16    d2,  q6                 \n\t"
                "vst1.32        d2[0], [%[d]]!          \n\t"
 
+
        AP"done:                                        \n\t"
+#if NEONDEBUG
+               "cmp            %[d], %[e]              \n\t"
+               "beq            "AP"reallydone          \n\t"
+               "sub            %[m],   %[m]            \n\t"
+               "vst1.32        d0[0], [%[m]]           \n\t"
+       AP"reallydone:"
+#endif
+
 
          : // output regs
          // Input
           :  [e] "r" (e = d + l), [d] "r" (d), [c] "r" (c),
                [m] "r" (m), [tmp] "r" (7), [x] "r" (33)
-          : "q0", "q1", "q2","q3", "q4","q5","q6", "q7","q14","q15",
+          : "q0", "q1", "q2","q3", "q4","q5","q6", "q7","q9","q14","q15",
                        "memory" // clobbered
 
      );
@@ -431,6 +490,9 @@ static void
 _op_blend_rel_mas_c_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, int l) {
    DATA32 *e;
    int alpha;
+
+   DEBUG_FNCOUNT("not");
+
    UNROLL8_PLD_WHILE(d, l, e,
                      {
                         DATA32 mc = MUL_SYM(*m, c);
index 6442d5e..a44b128 100644 (file)
@@ -1,4 +1,3 @@
-
 /* blend pixel x color --> dst */
 #ifdef BUILD_NEON
 /* Note: Optimisation is based on keeping _dest_ aligned: else it's a pair of
index 51238e7..2f72e9f 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_blend_private.h"
 
index c71d132..cf532a4 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 // THIS IS DEPRECATED. WILL GO EVENTUALLTY. NO NEED TO SUPPORT ANYMORE
 
 #include "evas_common.h"
@@ -19,9 +15,9 @@ evas_common_surface_alloc(void *surface, int x, int y, int w, int h)
 
    e_surface = calloc(1, sizeof(Evas_Surface));
    e_surface->im = surface;
-   LKL(e_surface->im->ref_fq_add);
-   e_surface->im->ref_fq[0]++;
-   LKU(e_surface->im->ref_fq_add);
+   LKL(e_surface->im->cache_entry.ref_fq_add);
+   e_surface->im->cache_entry.ref_fq[0]++;
+   LKU(e_surface->im->cache_entry.ref_fq_add);
    e_surface->x = x;
    e_surface->y = y;
    e_surface->w = w;
@@ -39,9 +35,9 @@ evas_common_surface_dealloc(Evas_Surface *surface)
      {
         d_surface = surface;
         surface = (Evas_Surface *)eina_inlist_remove(EINA_INLIST_GET(surface), EINA_INLIST_GET(d_surface));
-        LKL(d_surface->im->ref_fq_del);
-        d_surface->im->ref_fq[1]++;
-        LKU(d_surface->im->ref_fq_del);
+        LKL(d_surface->im->cache_entry.ref_fq_del);
+        d_surface->im->cache_entry.ref_fq[1]++;
+        LKU(d_surface->im->cache_entry.ref_fq_del);
 
         free(d_surface);
 
@@ -287,7 +283,7 @@ evas_common_pipe_thread(void *data)
 //   {
 //      thinfo->info = NULL;
 //      INF(" TH %i GO", thinfo->thread_num);
-        EINA_INLIST_FOREACH(EINA_INLIST_GET(info->im->pipe), p)
+        EINA_INLIST_FOREACH(EINA_INLIST_GET(info->im->cache_entry.pipe), p)
           {
              int i;
 
@@ -378,7 +374,7 @@ evas_common_frameq_thread(void *data)
              p_info.w = surface->im->cache_entry.w;
              p_info.h = surface->im->cache_entry.h;
 
-             EINA_INLIST_FOREACH(EINA_INLIST_GET(p_info.im->pipe), p)
+             EINA_INLIST_FOREACH(EINA_INLIST_GET(p_info.im->cache_entry.pipe), p)
                {
                   int i;
 
@@ -820,7 +816,7 @@ evas_common_pipe_begin(RGBA_Image *im)
    return;
 #endif
 
-   if (!im->pipe) return;
+   if (!im->cache_entry.pipe) return;
    if (thread_num == 1) return;
    y = 0;
    h = im->cache_entry.h / thread_num;
@@ -965,7 +961,7 @@ evas_common_pipe_flush(RGBA_Image *im)
    RGBA_Pipe *p;
    int i;
 
-   if (!im->pipe) return;
+   if (!im->cache_entry.pipe) return;
 
 #ifndef EVAS_FRAME_QUEUING
 
@@ -979,7 +975,7 @@ evas_common_pipe_flush(RGBA_Image *im)
 #endif
      {
         /* process pipe - 1 thead */
-        for (p = im->pipe; p; p = (RGBA_Pipe *)(EINA_INLIST_GET(p))->next)
+        for (p = im->cache_entry.pipe; p; p = (RGBA_Pipe *)(EINA_INLIST_GET(p))->next)
           {
              for (i = 0; i < p->op_num; i++)
                {
@@ -1002,13 +998,13 @@ evas_common_pipe_free(RGBA_Image *im)
    RGBA_Pipe *p;
    int i;
 
-   if (!im->pipe) return;
+   if (!im->cache_entry.pipe) return;
    /* FIXME: PTHREAD join all threads here (if not finished) */
 
    /* free pipe */
-   while (im->pipe)
+   while (im->cache_entry.pipe)
      {
-        p = im->pipe;
+        p = im->cache_entry.pipe;
         for (i = 0; i < p->op_num; i++)
           {
              if (p->op[i].free_func)
@@ -1016,7 +1012,7 @@ evas_common_pipe_free(RGBA_Image *im)
                   p->op[i].free_func(&(p->op[i]));
                }
           }
-        im->pipe = (RGBA_Pipe *)eina_inlist_remove(EINA_INLIST_GET(im->pipe), EINA_INLIST_GET(p));
+        im->cache_entry.pipe = (RGBA_Pipe *)eina_inlist_remove(EINA_INLIST_GET(im->cache_entry.pipe), EINA_INLIST_GET(p));
         free(p);
      }
 }
@@ -1057,8 +1053,8 @@ evas_common_pipe_rectangle_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
    RGBA_Pipe_Op *op;
 
    if ((w < 1) || (h < 1)) return;
-   dst->pipe = evas_common_pipe_add(dst->pipe, &op);
-   if (!dst->pipe) return;
+   dst->cache_entry.pipe = evas_common_pipe_add(dst->cache_entry.pipe, &op);
+   if (!dst->cache_entry.pipe) return;
    op->op.rect.x = x;
    op->op.rect.y = y;
    op->op.rect.w = w;
@@ -1100,8 +1096,8 @@ evas_common_pipe_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
 {
    RGBA_Pipe_Op *op;
 
-   dst->pipe = evas_common_pipe_add(dst->pipe, &op);
-   if (!dst->pipe) return;
+   dst->cache_entry.pipe = evas_common_pipe_add(dst->cache_entry.pipe, &op);
+   if (!dst->cache_entry.pipe) return;
    op->op.line.x0 = x0;
    op->op.line.y0 = y0;
    op->op.line.x1 = x1;
@@ -1158,8 +1154,8 @@ evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
    RGBA_Polygon_Point *pts = NULL, *p, *pp;
 
    if (!points) return;
-   dst->pipe = evas_common_pipe_add(dst->pipe, &op);
-   if (!dst->pipe) return;
+   dst->cache_entry.pipe = evas_common_pipe_add(dst->cache_entry.pipe, &op);
+   if (!dst->cache_entry.pipe) return;
    /* FIXME: copy points - maybe we should refcount? */
    for (p = points; p; p = (RGBA_Polygon_Point *)(EINA_INLIST_GET(p))->next)
      {
@@ -1177,178 +1173,6 @@ evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
    evas_common_pipe_draw_context_copy(dc, op);
 }
 
-/**************** GRAD ******************/
-static void
-evas_common_pipe_op_grad_free(RGBA_Pipe_Op *op)
-{
-#ifdef EVAS_FRAME_QUEUING
-   LKL(op->op.grad.grad->ref_fq_del);
-   op->op.grad.grad->ref_fq[1]++;
-   LKU(op->op.grad.grad->ref_fq_del);
-   pthread_cond_signal(&(op->op.grad.grad->cond_fq_del)); 
-#else
-   evas_common_gradient_free(op->op.grad.grad);
-#endif
-   evas_common_pipe_op_free(op);
-}
-
-#ifdef EVAS_FRAME_QUEUING
-EAPI void
-evas_common_pipe_op_grad_flush(RGBA_Gradient *gr)
-{
-   if (! evas_common_frameq_enabled())
-      return;
-
-   LKL(gr->ref_fq_add);
-   LKL(gr->ref_fq_del);
-
-   while (gr->ref_fq[0] != gr->ref_fq[1])
-      pthread_cond_wait(&(gr->cond_fq_del), &(gr->ref_fq_del));
-
-   LKU(gr->ref_fq_del);
-   LKU(gr->ref_fq_add);
-}
-#endif
-
-static void
-evas_common_pipe_grad_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
-{
-   if (info)
-     {
-        RGBA_Draw_Context context;
-
-        memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
-#ifdef EVAS_SLI
-        evas_common_draw_context_set_sli(&(context), info->y, info->h);
-#else
-        evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
-#endif
-        evas_common_gradient_draw(dst, &(context),
-                  op->op.grad.x, op->op.grad.y,
-                  op->op.grad.w, op->op.grad.h,
-                  op->op.grad.grad);
-     }
-   else
-     {
-        evas_common_gradient_draw(dst, &(op->context),
-                  op->op.grad.x, op->op.grad.y,
-                  op->op.grad.w, op->op.grad.h,
-                  op->op.grad.grad);
-     }
-}
-
-EAPI void
-evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
-            int x, int y, int w, int h, RGBA_Gradient *gr)
-{
-   RGBA_Pipe_Op *op;
-
-   if (!gr) return;
-   dst->pipe = evas_common_pipe_add(dst->pipe, &op);
-   if (!dst->pipe) return;
-   op->op.grad.x = x;
-   op->op.grad.y = y;
-   op->op.grad.w = w;
-   op->op.grad.h = h;
-#ifdef EVAS_FRAME_QUEUING
-   LKL(gr->ref_fq_add);
-   gr->ref_fq[0]++;
-   LKU(gr->ref_fq_add);
-#else
-   gr->references++;
-#endif
-   op->op.grad.grad = gr;
-   op->op_func = evas_common_pipe_grad_draw_do;
-   op->free_func = evas_common_pipe_op_grad_free;
-   evas_common_pipe_draw_context_copy(dc, op);
-}
-
-/**************** GRAD2 ******************/
-static void
-evas_common_pipe_op_grad2_free(RGBA_Pipe_Op *op)
-{
-#ifdef EVAS_FRAME_QUEUING
-   LKL(op->op.grad2.grad->ref_fq_del);
-   op->op.grad2.grad->ref_fq[1]++;
-   LKU(op->op.grad2.grad->ref_fq_del);
-   pthread_cond_signal(&(op->op.grad2.grad->cond_fq_del)); 
-#else
-   evas_common_gradient2_free(op->op.grad2.grad);
-#endif
-   evas_common_pipe_op_free(op);
-}
-
-#ifdef EVAS_FRAME_QUEUING
-EAPI void
-evas_common_pipe_op_grad2_flush(RGBA_Gradient2 *gr)
-{
-   if (! evas_common_frameq_enabled())
-      return;
-
-   LKL(gr->ref_fq_add);
-   LKL(gr->ref_fq_del);
-
-   while (gr->ref_fq[0] != gr->ref_fq[1])
-      pthread_cond_wait(&(gr->cond_fq_del), &(gr->ref_fq_del));
-
-   LKU(gr->ref_fq_del);
-   LKU(gr->ref_fq_add);
-}
-#endif
-
-static void
-evas_common_pipe_grad2_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
-{
-   if (info)
-     {
-        RGBA_Draw_Context context;
-       
-        memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
-#ifdef EVAS_SLI
-        evas_common_draw_context_set_sli(&(context), info->y, info->h);
-#else  
-        evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
-#endif 
-        evas_common_gradient2_draw(dst, &(context),
-               op->op.grad2.x, op->op.grad2.y,
-               op->op.grad2.w, op->op.grad2.h,
-               op->op.grad2.grad);
-     }
-   else
-     {
-        evas_common_gradient2_draw(dst, &(op->context),
-               op->op.grad2.x, op->op.grad2.y,
-               op->op.grad2.w, op->op.grad2.h,
-               op->op.grad2.grad);
-     }
-}
-
-EAPI void
-evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
-            int x, int y, int w, int h, RGBA_Gradient2 *gr)
-{
-   RGBA_Pipe_Op *op;
-
-   if (!gr) return;
-   dst->pipe = evas_common_pipe_add(dst->pipe, &op);
-   if (!dst->pipe) return;
-   op->op.grad2.x = x;
-   op->op.grad2.y = y;
-   op->op.grad2.w = w;
-   op->op.grad2.h = h;
-#ifdef EVAS_FRAME_QUEUING
-   LKL(gr->ref_fq_add);
-   gr->ref_fq[0]++;
-   LKU(gr->ref_fq_add);
-#else
-   gr->references++;
-#endif
-   op->op.grad2.grad = gr;
-   op->op_func = evas_common_pipe_grad2_draw_do;
-   op->free_func = evas_common_pipe_op_grad2_free;
-   evas_common_pipe_draw_context_copy(dc, op);
-}
-
 /**************** TEXT ******************/
 static void
 evas_common_pipe_op_text_free(RGBA_Pipe_Op *op)
@@ -1399,28 +1223,29 @@ evas_common_pipe_text_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Threa
 #endif
         evas_common_font_draw(dst, &(context),
                   op->op.text.font, op->op.text.x, op->op.text.y,
-                  op->op.text.text);
+                  op->op.text.text, op->op.text.intl_props);
      }
    else
      {
         evas_common_font_draw(dst, &(op->context),
                   op->op.text.font, op->op.text.x, op->op.text.y,
-                  op->op.text.text);
+                  op->op.text.text, op->op.text.intl_props);
      }
 }
 
 EAPI void
 evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
-               RGBA_Font *fn, int x, int y, const char *text)
+               RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
 {
    RGBA_Pipe_Op *op;
 
    if ((!fn) || (!text)) return;
-   dst->pipe = evas_common_pipe_add(dst->pipe, &op);
-   if (!dst->pipe) return;
+   dst->cache_entry.pipe = evas_common_pipe_add(dst->cache_entry.pipe, &op);
+   if (!dst->cache_entry.pipe) return;
    op->op.text.x = x;
    op->op.text.y = y;
-   op->op.text.text = strdup(text);
+   op->op.text.text = eina_unicode_strdup(text);
+   op->op.text.intl_props = intl_props;
 #ifdef EVAS_FRAME_QUEUING
    LKL(fn->ref_fq_add);
    fn->ref_fq[0]++;
@@ -1439,10 +1264,10 @@ static void
 evas_common_pipe_op_image_free(RGBA_Pipe_Op *op)
 {
 #ifdef EVAS_FRAME_QUEUING
-   LKL(op->op.image.src->ref_fq_del);
-   op->op.image.src->ref_fq[1]++;
-   LKU(op->op.image.src->ref_fq_del);
-   pthread_cond_signal(&(op->op.image.src->cond_fq_del)); 
+   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);
+   pthread_cond_signal(&(op->op.image.src->cache_entry.cond_fq_del)); 
 #else
    op->op.image.src->ref--;
    if (op->op.image.src->ref == 0)
@@ -1460,14 +1285,14 @@ evas_common_pipe_op_image_flush(RGBA_Image *im)
    if (! evas_common_frameq_enabled())
       return;
    
-   LKL(im->ref_fq_add);
-   LKL(im->ref_fq_del);
+   LKL(im->cache_entry.ref_fq_add);
+   LKL(im->cache_entry.ref_fq_del);
 
-   while (im->ref_fq[0] != im->ref_fq[1])
-      pthread_cond_wait(&(im->cond_fq_del), &(im->ref_fq_del));
+   while (im->cache_entry.ref_fq[0] != im->cache_entry.ref_fq[1])
+      pthread_cond_wait(&(im->cache_entry.cond_fq_del), &(im->cache_entry.ref_fq_del));
 
-   LKU(im->ref_fq_del);
-   LKU(im->ref_fq_add);
+   LKU(im->cache_entry.ref_fq_del);
+   LKU(im->cache_entry.ref_fq_add);
 }
 #endif
 
@@ -1486,7 +1311,7 @@ evas_common_pipe_image_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thre
 #endif
 
 #ifdef SCALECACHE
-        evas_common_rgba_image_scalecache_do(op->op.image.src,
+        evas_common_rgba_image_scalecache_do((Image_Entry *)(op->op.image.src),
                                              dst, &(context),
                                              op->op.image.smooth,
                                              op->op.image.sx,
@@ -1529,17 +1354,17 @@ evas_common_pipe_image_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thre
    else
      {
 #ifdef SCALECACHE
-        evas_common_rgba_image_scalecache_do(op->op.image.src,
-                           dst, &(op->context),
-                           op->op.image.smooth,
-                           op->op.image.sx,
-                           op->op.image.sy,
-                           op->op.image.sw,
-                           op->op.image.sh,
-                           op->op.image.dx,
-                           op->op.image.dy,
-                           op->op.image.dw,
-                           op->op.image.dh);
+        evas_common_rgba_image_scalecache_do((Image_Entry *)(op->op.image.src),
+                                             dst, &(op->context),
+                                             op->op.image.smooth,
+                                             op->op.image.sx,
+                                             op->op.image.sy,
+                                             op->op.image.sw,
+                                             op->op.image.sh,
+                                             op->op.image.dx,
+                                             op->op.image.dy,
+                                             op->op.image.dw,
+                                             op->op.image.dh);
 #else
         if (op->op.image.smooth)
           {
@@ -1583,8 +1408,8 @@ evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst,
 
    if (!src) return;
 //   evas_common_pipe_flush(src);
-   dst->pipe = evas_common_pipe_add(dst->pipe, &op);
-   if (!dst->pipe) return;
+   dst->cache_entry.pipe = evas_common_pipe_add(dst->cache_entry.pipe, &op);
+   if (!dst->cache_entry.pipe) return;
    op->op.image.smooth = smooth;
    op->op.image.sx = src_region_x;
    op->op.image.sy = src_region_y;
@@ -1595,9 +1420,9 @@ evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst,
    op->op.image.dw = dst_region_w;
    op->op.image.dh = dst_region_h;
 #ifdef EVAS_FRAME_QUEUING
-   LKL(src->ref_fq_add);
-   src->ref_fq[0]++;
-   LKU(src->ref_fq_add);
+   LKL(src->cache_entry.ref_fq_add);
+   src->cache_entry.ref_fq[0]++;
+   LKU(src->cache_entry.ref_fq_add);
 #else
    src->ref++;
 #endif
@@ -1624,9 +1449,9 @@ static void
 evas_common_pipe_op_map4_free(RGBA_Pipe_Op *op)
 {
 #ifdef EVAS_FRAME_QUEUING
-   LKL(op->op.image.src->ref_fq_del);
-   op->op.image.src->ref_fq[1]++;
-   LKU(op->op.image.src->ref_fq_del);
+   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)
@@ -1674,8 +1499,8 @@ evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst,
    if (!src) return;
    pts_copy = malloc(sizeof (RGBA_Map_Point) * 4);
    if (!pts_copy) return;
-   dst->pipe = evas_common_pipe_add(dst->pipe, &op);
-   if (!dst->pipe) 
+   dst->cache_entry.pipe = evas_common_pipe_add(dst->cache_entry.pipe, &op);
+   if (!dst->cache_entry.pipe) 
      {
        free(pts_copy);
        return; 
@@ -1687,9 +1512,9 @@ evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst,
    op->op.map4.smooth = smooth;
    op->op.map4.level = level;
 #ifdef EVAS_FRAME_QUEUING
-   LKL(src->ref_fq_add);
-   src->ref_fq[0]++;
-   LKU(src->ref_fq_add);
+   LKL(src->cache_entry.ref_fq_add);
+   src->cache_entry.ref_fq[0]++;
+   LKU(src->cache_entry.ref_fq_add);
 #else
    src->ref++;
 #endif
@@ -1720,18 +1545,18 @@ evas_common_pipe_map4_render(RGBA_Image *root)
   int i;
 
   /* Map imply that we need to process them recursively first. */
-  for (p = root->pipe; p; p = (RGBA_Pipe *)(EINA_INLIST_GET(p))->next)
+  for (p = root->cache_entry.pipe; p; p = (RGBA_Pipe *)(EINA_INLIST_GET(p))->next)
     {
       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.map4.src->pipe)
+             if (p->op[i].op.map4.src->cache_entry.pipe)
                evas_common_pipe_map4_render(p->op[i].op.map4.src);
            }
          else if (p->op[i].op_func == evas_common_pipe_image_draw_do)
            {
-             if (p->op[i].op.image.src->pipe)
+             if (p->op[i].op.image.src->cache_entry.pipe)
                evas_common_pipe_map4_render(p->op[i].op.image.src);
            }
        }
@@ -1851,6 +1676,10 @@ evas_common_pipe_init(void)
                            evas_common_pipe_load, &(task_thinfo[i]));
             pthread_attr_destroy(&attr);
          }
+
+#if defined(METRIC_CACHE) || defined(WORD_CACHE)
+       eina_threads_init();
+#endif
      }
    if (thread_num == 1) return EINA_FALSE;
    return EINA_TRUE;
index 651582c..c10b55d 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef _EVAS_PIPE_H
 #define _EVAS_PIPE_H
+#include "evas_bidi_utils.h"
 
 #ifdef BUILD_PTHREAD
 typedef struct _Thinfo
@@ -9,7 +10,7 @@ typedef struct _Thinfo
    pthread_barrier_t     *barrier;
    RGBA_Pipe_Thread_Info *info;
 #ifdef EVAS_FRAME_QUEUING
-   void                 *fq_info;
+   void                         *fq_info;
 #endif
 } Thinfo;
 #endif
@@ -50,7 +51,7 @@ struct _Evas_FrameQ
    pthread_cond_t cond_done;
    LK(mutex);
 
-   int               thread_num;
+   int             thread_num;
    Thinfo          thinfo[TH_MAX];
    int            frameq_sz;
 
@@ -65,17 +66,17 @@ struct _Evas_Frameq_Thread_Info
 };
 typedef struct _Evas_Frameq_Thread_Info Evas_Frameq_Thread_Info;
 
-EAPI Evas_Surface *evas_common_frameq_new_surface (void *surface, int x, int y, int w, int h);
+EAPI Evas_Surface *evas_common_frameq_new_surface(void *surface, int x, int y, int w, int h);
 EAPI void evas_common_frameq_add_surface(Evas_Surface *surface);
 EAPI void evas_common_frameq_set_frame_data(void *data, 
      void (*fn_output_redraws_next_update_push) (void *data, void *surface, int x, int y, int w, int h),
      void (*fn_output_flush)  (void *data),
      void (*fn_output_set_priv)(void *data, void *cur, void *prev));
-EAPI void evas_common_frameq_prepare_frame();
-EAPI void evas_common_frameq_ready_frame();
-EAPI void evas_common_frameq_init();
-EAPI void evas_common_frameq_flush();
-EAPI void evas_common_frameq_flush_ready ();
+EAPI void evas_common_frameq_prepare_frame(void);
+EAPI void evas_common_frameq_ready_frame(void);
+EAPI void evas_common_frameq_init(void);
+EAPI void evas_common_frameq_flush(void);
+EAPI void evas_common_frameq_flush_ready(void);
 #endif
 
 /* image rendering pipelines... new optional system - non-immediate and
@@ -86,18 +87,15 @@ 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_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient *gr);
-EAPI void evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient2 *gr);
-EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text);
+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_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_map4_draw(RGBA_Image *src, RGBA_Image *dst,
                                     RGBA_Draw_Context *dc, RGBA_Map_Point *p,
                                     int smooth, int level);
+EAPI void evas_common_pipe_flush(RGBA_Image *im);
 
 #ifdef EVAS_FRAME_QUEUING
-EAPI void evas_common_pipe_op_grad_flush(RGBA_Gradient *gr);
-EAPI void evas_common_pipe_op_grad2_flush(RGBA_Gradient2 *gr);
 EAPI void evas_common_pipe_op_text_flush(RGBA_Font *fn);
 EAPI void evas_common_pipe_op_image_flush(RGBA_Image *im);
 #endif
index cd8410a..bca3f83 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include <math.h>
 
 #include "evas_common.h"
index c457848..28aaf16 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_blend_private.h"
 
index 8f0f535..959336c 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 
 EAPI void
index 5da6bdc..0040e7e 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_SCALE_MAIN_H
 #define _EVAS_SCALE_MAIN_H
 
index 0d57717..c6fa9f2 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_blend_private.h"
 
index cd6c5d6..bc01bfc 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_scale_smooth.h"
 #include "evas_blend_private.h"
@@ -315,8 +311,11 @@ evas_common_scale_rgba_mipmap_down_2x2_mmx(DATA32 *src, DATA32 *dst, int src_w,
    if (dst_w < 1) dst_w = 1;
    if (dst_h < 1) dst_h = 1;
 
+   /* NB: Dead assignments (reassigned to different values below)
    src_ptr = src;
    src_ptr2 = src + src_w;
+    */
+
    dst_ptr = dst;
    for (y = 0; y < dst_h; y++)
      {
@@ -400,7 +399,9 @@ evas_common_scale_rgba_mipmap_down_1x2_mmx(DATA32 *src, DATA32 *dst, int src_w,
    if (dst_w < 1) dst_w = 1;
    if (dst_h < 1) dst_h = 1;
 
-   src_ptr = src;
+   /* NB: Dead assignment (gets reassigned later) */
+//   src_ptr = src;
+
    src_ptr2 = src + src_w;
    dst_ptr = dst;
    for (y = 0; y < dst_h; y++)
index d4bfb46..63ced50 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_SCALE_SMOOTH_H
 #define _EVAS_SCALE_SMOOTH_H
 
index 6cf7cc6..d119411 100644 (file)
@@ -7,7 +7,6 @@ SCALE_FUNC(RGBA_Image *src, RGBA_Image *dst,
           int dst_region_w, int dst_region_h)
 {
    DATA32  *dst_ptr;
-   int      dst_jump;
    int      dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h;
    int      src_w, src_h, dst_w, dst_h;
 
@@ -137,8 +136,9 @@ SCALE_FUNC(RGBA_Image *src, RGBA_Image *dst,
      }
    if (dst_clip_h <= 0) return;
 
-   /* figure out dst jump */
-   dst_jump = dst_w - dst_clip_w;
+   /* figure out dst jump
+    * NB: Unused currently, so commented out */
+//   dst_jump = dst_w - dst_clip_w;
 
    /* figure out dest start ptr */
    dst_ptr = dst->image.data + dst_clip_x + (dst_clip_y * dst_w);
index 3ccaec4..9fd4d86 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #include "evas_common.h"
 #include "evas_convert_color.h"
 #include "evas_scale_span.h"
index 6c51619..874c594 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef _EVAS_SCALE_SPAN_H
 #define _EVAS_SCALE_SPAN_H
 
index 415d137..8177d28 100644 (file)
@@ -169,6 +169,7 @@ _evas_common_load_soft16_image_from_file(Image_Entry *ie)
    sim->cache_entry.w = sim->source->cache_entry.w;
    sim->cache_entry.h = sim->source->cache_entry.h;
    ie->flags.alpha = im->cache_entry.flags.alpha;
+   sim->cache_entry.info = im->cache_entry.info;
    if (sim->stride < 0) sim->stride = _calc_stride(sim->cache_entry.w);
 
    return 0;
@@ -288,6 +289,8 @@ _evas_common_load_soft16_image_data_from_file(Image_Entry *ie)
           soft16_image_convert_from_rgb(im, sp);
      }
    evas_cache_image_drop(&im->source->cache_entry);
+   im->cache_entry.info.module = NULL;
+   im->cache_entry.info.loader = NULL;
    im->source = NULL;
 
    return 0;
diff --git a/src/lib/engines/common_8/Makefile.am b/src/lib/engines/common_8/Makefile.am
new file mode 100644 (file)
index 0000000..5fdd086
--- /dev/null
@@ -0,0 +1,31 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/src/lib \
+-I$(top_srcdir)/src/lib/include \
+@FREETYPE_CFLAGS@ \
+@VALGRIND_CFLAGS@ \
+@EINA_CFLAGS@ \
+@EET_CFLAGS@ \
+@pthread_cflags@
+
+noinst_LTLIBRARIES = libevas_engine_common_8.la
+
+libevas_engine_common_8_la_SOURCES = \
+evas_soft8_dither_mask.c \
+evas_soft8_font.c \
+evas_soft8_image_unscaled.c \
+evas_soft8_main.c \
+evas_soft8_rectangle.c \
+evas_soft8_line.c \
+evas_soft8_polygon.c \
+evas_soft8_image_scaled_sampled.c
+
+
+libevas_engine_common_8_la_DEPENDENCIES = $(top_builddir)/config.h
+
+EXTRA_DIST = \
+evas_soft8_scanline_blend.c \
+evas_soft8_scanline_fill.c
diff --git a/src/lib/engines/common_8/evas_soft8_dither_mask.c b/src/lib/engines/common_8/evas_soft8_dither_mask.c
new file mode 100644 (file)
index 0000000..74c88b4
--- /dev/null
@@ -0,0 +1,103 @@
+#include "evas_common_soft8.h"
+
+static always_inline void
+_soft8_convert_from_rgba_pt(const DATA32 * src, DATA8 * dst, DATA8 * alpha,
+                            const int x, const int y)
+{
+   if (A_VAL(src) == 0)
+     {
+        *dst = 0;
+        *alpha = 0;
+     }
+   else
+     {
+        *dst = GRY_8_FROM_RGB(src);
+        *alpha = A_VAL(src);
+     }
+}
+
+static inline void
+_soft8_convert_from_rgba_scanline(const DATA32 * src, DATA8 * dst,
+                                  DATA8 * alpha, const int y, const int w)
+{
+   int x, m;
+
+   m = (w & ~7);
+   x = 0;
+   pld(src, 0);
+
+   while (x < m)
+     {
+        pld(src, 32);
+        UNROLL8(
+                  {
+                  _soft8_convert_from_rgba_pt(src, dst, alpha, x, y);
+                  src++; dst++; alpha++; x++;}
+        );
+     }
+
+   for (; x < w; x++, src++, dst++, alpha++)
+      _soft8_convert_from_rgba_pt(src, dst, alpha, x, y);
+}
+
+void
+soft8_image_convert_from_rgba(Soft8_Image * im, const DATA32 * src)
+{
+   const DATA32 *sp;
+   DATA8 *dp;
+   DATA8 *ap;
+   int y;
+
+   sp = src;
+   dp = im->pixels;
+   ap = im->alpha;
+
+   for (y = 0; y < im->cache_entry.h;
+        y++, sp += im->cache_entry.w, dp += im->stride, ap += im->stride)
+      _soft8_convert_from_rgba_scanline(sp, dp, ap, y, im->cache_entry.w);
+}
+
+static always_inline void
+_soft8_convert_from_rgb_pt(const DATA32 * src, DATA8 * dst,
+                           const int x, const int y)
+{
+   *dst = GRY_8_FROM_RGB(src);
+}
+
+static inline void
+_soft8_convert_from_rgb_scanline(const DATA32 * src, DATA8 * dst, const int y,
+                                 const int w)
+{
+   int x, m;
+
+   m = (w & ~7);
+   x = 0;
+   pld(src, 0);
+
+   while (x < m)
+     {
+        pld(src, 32);
+        UNROLL8(
+                  {
+                  _soft8_convert_from_rgb_pt(src, dst, x, y); src++; dst++; x++;}
+        );
+     }
+
+   for (; x < w; x++, src++, dst++)
+      _soft8_convert_from_rgb_pt(src, dst, x, y);
+}
+
+void
+soft8_image_convert_from_rgb(Soft8_Image * im, const DATA32 * src)
+{
+   const DATA32 *sp;
+   DATA8 *dp;
+   int y;
+
+   sp = src;
+   dp = im->pixels;
+
+   for (y = 0; y < im->cache_entry.h;
+        y++, sp += im->cache_entry.w, dp += im->stride)
+      _soft8_convert_from_rgb_scanline(sp, dp, y, im->cache_entry.w);
+}
diff --git a/src/lib/engines/common_8/evas_soft8_font.c b/src/lib/engines/common_8/evas_soft8_font.c
new file mode 100644 (file)
index 0000000..b935a9b
--- /dev/null
@@ -0,0 +1,285 @@
+#include "evas_common_soft8.h"
+#include "evas_soft8_scanline_blend.c"
+
+static always_inline void
+_glyph_pt_mask_solid_solid(DATA8 * dst, const DATA8 gry8, const DATA8 * mask)
+{
+   DATA8 alpha = *mask;
+
+   if (alpha == 0xff)
+      *dst = gry8;
+   else if (alpha > 0)
+     {
+        *dst = GRY_8_BLEND_UNMUL(gry8, *dst, alpha);
+     }
+}
+
+static void
+_glyph_scanline_mask_solid_solid(DATA8 * dst,
+                                 int size, const DATA8 gry8, const DATA8 * mask)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   pld(start, 0);
+   pld(mask, 0);
+   end = start + (size & ~3);
+
+   while (start < end)
+     {
+        pld(start, 8);
+        pld(mask, 4);
+        UNROLL4(
+                  {
+                  _glyph_pt_mask_solid_solid(start, gry8, mask);
+                  start++; mask++;}
+        );
+     }
+
+   end = start + (size & 3);
+   for (; start < end; start++, mask++)
+      _glyph_pt_mask_solid_solid(start, gry8, mask);
+}
+
+static always_inline void
+_glyph_pt_mask_transp_solid(DATA8 * dst,
+                            DATA8 gry8, DATA8 alpha, const DATA8 * mask)
+{
+   int rel_alpha;
+
+   rel_alpha = *mask;
+   alpha = (alpha * rel_alpha) >> 8;
+   if (alpha == 0)
+      return;
+
+   alpha++;
+
+   *dst = GRY_8_BLEND((gry8 * rel_alpha) >> 8, *dst, alpha);
+}
+
+static void
+_glyph_scanline_mask_transp_solid(DATA8 * dst,
+                                  int size,
+                                  const DATA8 gry8,
+                                  const DATA8 rel_alpha, const DATA8 * mask)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   pld(start, 0);
+   pld(mask, 0);
+   end = start + (size & ~3);
+
+   while (start < end)
+     {
+        pld(start, 8);
+        pld(mask, 4);
+        UNROLL4(
+                  {
+                  _glyph_pt_mask_transp_solid(start, gry8, rel_alpha, mask);
+                  start++; mask++;}
+        );
+     }
+
+   end = start + (size & 3);
+   for (; start < end; start++, mask++)
+      _glyph_pt_mask_transp_solid(start, gry8, rel_alpha, mask);
+}
+
+static inline void
+_calc_ext(const Soft8_Image * dst, const RGBA_Draw_Context * dc,
+          Eina_Rectangle * ext)
+{
+   EINA_RECTANGLE_SET(ext, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
+
+   if (dc->clip.use)
+     {
+        int v;
+
+        EINA_RECTANGLE_SET(ext, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
+        if (ext->x < 0)
+          {
+             ext->w += ext->x;
+             ext->x = 0;
+          }
+        if (ext->y < 0)
+          {
+             ext->h += ext->y;
+             ext->y = 0;
+          }
+
+        v = dst->cache_entry.w - ext->x;
+        if (ext->w > v)
+           ext->w = v;
+
+        v = dst->cache_entry.h - ext->y;
+        if (ext->h > v)
+           ext->h = v;
+     }
+}
+
+static inline void
+_glyph_scanline(Soft8_Image * dst, const DATA8 * p_mask,
+                const Eina_Rectangle ext, int dx, int dy, int max_x, int max_y,
+                int w, DATA8 alpha, const DATA8 gry8)
+{
+   int size, in_x, in_w;
+   DATA8 *p_pixels;
+
+   if ((dx >= max_x) || (dy < ext.y) || (dy >= max_y))
+      return;
+
+   in_x = 0;
+   in_w = 0;
+
+   if (dx + w > max_x)
+      in_w += (dx + w) - max_x;
+
+   if (dx < ext.x)
+     {
+        in_w += ext.x - dx;
+        in_x = ext.x - dx;
+        dx = ext.x;
+     }
+
+   size = w - in_w;
+   p_pixels = dst->pixels + (dy * dst->stride) + dx;
+   p_mask += in_x;
+
+   if (size > 1)
+     {
+        if (alpha == 0xff)
+           _glyph_scanline_mask_solid_solid(p_pixels, size, gry8, p_mask);
+        else if (alpha != 0)
+           _glyph_scanline_mask_transp_solid
+               (p_pixels, size, gry8, alpha, p_mask);
+     }
+   else if (size == 1)
+     {
+        if (alpha == 0xff)
+           _glyph_pt_mask_solid_solid(p_pixels, gry8, p_mask);
+        else if (alpha != 0)
+           _glyph_pt_mask_transp_solid(p_pixels, gry8, alpha, p_mask);
+     }
+}
+
+static void
+_soft8_font_glyph_draw_grayscale(Soft8_Image * dst,
+                                 RGBA_Draw_Context * dc __UNUSED__,
+                                 RGBA_Font_Glyph * fg __UNUSED__, int x, int y,
+                                 DATA8 alpha, DATA8 gry8,
+                                 const Eina_Rectangle ext, int bw, int bh,
+                                 int bpitch, const DATA8 * bitmap)
+{
+   int i, max_x, max_y;
+
+   max_x = ext.x + ext.w;
+   max_y = ext.y + ext.h;
+
+   for (i = 0; i < bh; i++, bitmap += bpitch)
+      _glyph_scanline(dst, bitmap, ext, x, y + i, max_x, max_y, bw,
+                      alpha, gry8);
+}
+
+static inline void
+_glyph_create_mask_line(DATA8 * mask, const DATA8 * bitmap, int w)
+{
+   const DATA8 bitrepl[2] = { 0x0, 0xff };
+   int i;
+
+   for (i = 0; i < w; i += 8, bitmap++)
+     {
+        int j, size;
+        DATA32 bits;
+
+        if (i + 8 < w)
+           size = 8;
+        else
+           size = w - i;
+
+        bits = *bitmap;
+
+        for (j = size - 1; j >= 0; j--, mask++)
+           *mask = bitrepl[(bits >> j) & 0x1];
+     }
+}
+
+static void
+_soft8_font_glyph_draw_mono(Soft8_Image * dst,
+                            RGBA_Draw_Context * dc __UNUSED__,
+                            RGBA_Font_Glyph * fg __UNUSED__, int x, int y,
+                            DATA8 alpha, DATA8 gry8, const Eina_Rectangle ext,
+                            int bw, int bh, int bpitch, const DATA8 * bitmap)
+{
+   DATA8 *mask;
+   int i, max_x, max_y;
+
+   max_x = ext.x + ext.w;
+   max_y = ext.y + ext.h;
+
+   mask = alloca(bpitch);
+   for (i = 0; i < bh; i++, bitmap += bpitch)
+     {
+        _glyph_create_mask_line(mask, bitmap, bw);
+        _glyph_scanline(dst, mask, ext, x, y + i, max_x, max_y, bw,
+                        alpha, gry8);
+     }
+}
+
+void
+soft8_font_glyph_draw(void *data, void *dest __UNUSED__, void *context,
+                      RGBA_Font_Glyph * fg, int x, int y)
+{
+   Soft8_Image *dst;
+   RGBA_Draw_Context *dc;
+   const DATA8 *bitmap;
+   DATA8 alpha; // r, g, b
+   DATA8 gry8;
+   Eina_Rectangle ext;
+   int bpitch, bw, bh;
+
+   dst = data;
+   dc = context;
+
+   alpha = A_VAL(&dc->col.col);
+   if (alpha == 0)
+      return;
+
+   gry8 = GRY_8_FROM_RGB(&dc->col.col);
+
+   /*
+    * if (r > alpha) r = alpha;
+    * if (g > alpha) g = alpha;
+    * if (b > alpha) b = alpha;
+    *
+    * gry8 = GRY_8_FROM_COMPONENTS(r, g, b);
+    */
+
+   bitmap = fg->glyph_out->bitmap.buffer;
+   bh = fg->glyph_out->bitmap.rows;
+   bw = fg->glyph_out->bitmap.width;
+   bpitch = fg->glyph_out->bitmap.pitch;
+   if (bpitch < bw)
+      bpitch = bw;
+
+   _calc_ext(dst, dc, &ext);
+
+   if ((fg->glyph_out->bitmap.num_grays == 256) &&
+       (fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
+      _soft8_font_glyph_draw_grayscale(dst, dc, fg, x, y, alpha, gry8,
+                                       ext, bw, bh, bpitch, bitmap);
+   else
+      _soft8_font_glyph_draw_mono(dst, dc, fg, x, y, alpha, gry8,
+                                  ext, bw, bh, bpitch, bitmap);
+}
+
+void *
+soft8_font_glyph_new(void *data __UNUSED__, RGBA_Font_Glyph * fg __UNUSED__)
+{
+   return (void *)1;            /* core requires != NULL to work */
+}
+
+void
+soft8_font_glyph_free(void *ext_dat __UNUSED__)
+{
+}
diff --git a/src/lib/engines/common_8/evas_soft8_image_scaled_sampled.c b/src/lib/engines/common_8/evas_soft8_image_scaled_sampled.c
new file mode 100644 (file)
index 0000000..9e8dcad
--- /dev/null
@@ -0,0 +1,463 @@
+#include "evas_common_soft8.h"
+#include "evas_soft8_scanline_blend.c"
+
+static void
+_soft8_image_draw_scaled_solid_solid(Soft8_Image * src,
+                                     Soft8_Image * dst,
+                                     RGBA_Draw_Context * dc __UNUSED__,
+                                     int dst_offset, int w, int h,
+                                     int *offset_x, int *offset_y)
+{
+   DATA8 *dst_itr;
+   int y, w_align;
+
+   w_align = w & ~7;
+
+   dst_itr = dst->pixels + dst_offset;
+   for (y = 0; y < h; y++, dst_itr += dst->stride)
+     {
+        DATA8 *d, *s;
+        int x;
+
+        s = src->pixels + offset_y[y];
+        pld(s, 0);
+        pld(offset_x, 0);
+
+        d = dst_itr;
+        x = 0;
+        while (x < w_align)
+          {
+             pld(s, 32);
+             pld(offset_x + x, 32);
+
+             UNROLL8(
+                       {
+                       _soft8_pt_blend_solid_solid(d, s[offset_x[x]]); x++; d++;}
+             );
+          }
+
+        for (; x < w; x++, d++)
+           _soft8_pt_blend_solid_solid(d, s[offset_x[x]]);
+     }
+}
+static void
+_soft8_image_draw_scaled_transp_solid(Soft8_Image * src,
+                                      Soft8_Image * dst,
+                                      RGBA_Draw_Context * dc __UNUSED__,
+                                      int dst_offset, int w, int h,
+                                      int *offset_x, int *offset_y)
+{
+   DATA8 *dst_itr;
+   int y, w_align;
+
+   w_align = w & ~7;
+
+   dst_itr = dst->pixels + dst_offset;
+   for (y = 0; y < h; y++, dst_itr += dst->stride)
+     {
+        DATA8 *d, *s;
+        DATA8 *a;
+        int x;
+
+        s = src->pixels + offset_y[y];
+        a = src->alpha + offset_y[y];
+        pld(s, 0);
+        pld(a, 0);
+        pld(offset_x, 0);
+
+        d = dst_itr;
+        x = 0;
+        while (x < w_align)
+          {
+             pld(s, 32);
+             pld(a, 8);
+             pld(offset_x + x, 32);
+
+             UNROLL8(
+                       {
+                       int off_x = offset_x[x];
+                       _soft8_pt_blend_transp_solid(d, s[off_x], a[off_x]);
+                       x++; d++;});
+          }
+
+        for (; x < w; x++, d++)
+           _soft8_pt_blend_transp_solid(d, s[offset_x[x]], a[offset_x[x]]);
+     }
+}
+
+static inline void
+_soft8_image_draw_scaled_no_mul(Soft8_Image * src, Soft8_Image * dst,
+                                RGBA_Draw_Context * dc,
+                                int dst_offset, int w, int h,
+                                int *offset_x, int *offset_y)
+{
+   if ((src->cache_entry.flags.alpha && src->alpha) &&
+       (!dst->cache_entry.flags.alpha))
+      _soft8_image_draw_scaled_transp_solid
+          (src, dst, dc, dst_offset, w, h, offset_x, offset_y);
+   else if (!dst->cache_entry.flags.alpha)
+      _soft8_image_draw_scaled_solid_solid
+          (src, dst, dc, dst_offset, w, h, offset_x, offset_y);
+   else
+      ERR("Unsupported draw of scaled images src->cache_entry.flags.alpha=%d, "
+          "dst->cache_entry.flags.alpha=%d, WITHOUT COLOR MUL",
+          src->cache_entry.flags.alpha, dst->cache_entry.flags.alpha);
+}
+
+static void
+_soft8_image_draw_scaled_solid_solid_mul_alpha(Soft8_Image * src,
+                                               Soft8_Image * dst,
+                                               RGBA_Draw_Context *
+                                               dc __UNUSED__, int dst_offset,
+                                               int w, int h, int *offset_x,
+                                               int *offset_y, DATA8 alpha)
+{
+   DATA8 *dst_itr;
+   int y, w_align;
+
+   w_align = w & ~7;
+
+   dst_itr = dst->pixels + dst_offset;
+   for (y = 0; y < h; y++, dst_itr += dst->stride)
+     {
+        DATA8 *d, *s;
+        int x;
+
+        s = src->pixels + offset_y[y];
+        pld(s, 0);
+        pld(offset_x, 0);
+
+        d = dst_itr;
+        x = 0;
+        while (x < w_align)
+          {
+             pld(s, 32);
+             pld(offset_x + x, 32);
+
+             UNROLL8(
+                       {
+                       _soft8_pt_blend_solid_solid_mul_alpha
+                       (d, s[offset_x[x]], alpha); x++; d++;}
+             );
+          }
+
+        for (; x < w; x++, d++)
+           _soft8_pt_blend_solid_solid_mul_alpha(d, s[offset_x[x]], alpha);
+     }
+}
+
+static void
+_soft8_image_draw_scaled_transp_solid_mul_alpha(Soft8_Image * src,
+                                                Soft8_Image * dst,
+                                                RGBA_Draw_Context *
+                                                dc __UNUSED__, int dst_offset,
+                                                int w, int h, int *offset_x,
+                                                int *offset_y, DATA8 alpha)
+{
+   DATA8 *dst_itr;
+   int y, w_align;
+
+   w_align = w & ~7;
+
+   dst_itr = dst->pixels + dst_offset;
+   for (y = 0; y < h; y++, dst_itr += dst->stride)
+     {
+        DATA8 *d, *s;
+        DATA8 *a;
+        int x;
+
+        s = src->pixels + offset_y[y];
+        a = src->alpha + offset_y[y];
+        pld(s, 0);
+        pld(a, 0);
+        pld(offset_x, 0);
+
+        d = dst_itr;
+        x = 0;
+        while (x < w_align)
+          {
+             pld(s, 32);
+             pld(a, 8);
+             pld(offset_x + x, 32);
+
+             UNROLL8(
+                       {
+                       int off_x = offset_x[x];
+                       _soft8_pt_blend_transp_solid_mul_alpha
+                       (d, s[off_x], a[off_x], alpha); x++; d++;});
+          }
+
+        for (; x < w; x++, d++)
+           _soft8_pt_blend_transp_solid_mul_alpha
+               (d, s[offset_x[x]], a[offset_x[x]], alpha);
+     }
+}
+
+static inline void
+_soft8_image_draw_scaled_mul_alpha(Soft8_Image * src, Soft8_Image * dst,
+                                   RGBA_Draw_Context * dc,
+                                   int dst_offset, int w, int h,
+                                   int *offset_x, int *offset_y, DATA8 a)
+{
+   if ((src->cache_entry.flags.alpha && src->alpha) &&
+       (!dst->cache_entry.flags.alpha))
+      _soft8_image_draw_scaled_transp_solid_mul_alpha
+          (src, dst, dc, dst_offset, w, h, offset_x, offset_y, a);
+   else if (!dst->cache_entry.flags.alpha)
+      _soft8_image_draw_scaled_solid_solid_mul_alpha
+          (src, dst, dc, dst_offset, w, h, offset_x, offset_y, a);
+   else
+      ERR("Unsupported draw of scaled images src->cache_entry.flags.alpha=%d, "
+          "dst->cache_entry.flags.alpha=%d, WITH ALPHA MUL %d",
+          src->cache_entry.flags.alpha, dst->cache_entry.flags.alpha,
+          A_VAL(&dc->mul.col));
+}
+
+static void
+_soft8_image_draw_scaled_solid_solid_mul_color(Soft8_Image * src,
+                                               Soft8_Image * dst,
+                                               RGBA_Draw_Context *
+                                               dc __UNUSED__, int dst_offset,
+                                               int w, int h, int *offset_x,
+                                               int *offset_y, DATA8 r, DATA8 g,
+                                               DATA8 b, DATA8 alpha)
+{
+   DATA8 *dst_itr;
+   int y, w_align;
+
+   w_align = w & ~7;
+
+   dst_itr = dst->pixels + dst_offset;
+
+   if (alpha == 0xff)
+      for (y = 0; y < h; y++, dst_itr += dst->stride)
+        {
+           DATA8 *d, *s;
+           int x;
+
+           s = src->pixels + offset_y[y];
+           pld(s, 0);
+           pld(offset_x, 0);
+
+           d = dst_itr;
+           x = 0;
+           while (x < w_align)
+             {
+                pld(s, 32);
+                pld(offset_x + x, 32);
+
+                UNROLL8(
+                          {
+                          _soft8_pt_blend_solid_solid_mul_color_solid
+                          (d, s[offset_x[x]], r, g, b); x++; d++;}
+                );
+             }
+
+           for (; x < w; x++, d++)
+              _soft8_pt_blend_solid_solid_mul_color_solid
+                  (d, s[offset_x[x]], r, g, b);
+        }
+   else
+      for (y = 0; y < h; y++, dst_itr += dst->stride)
+        {
+           DATA8 *d, *s;
+           int x;
+
+           s = src->pixels + offset_y[y];
+           pld(s, 0);
+           pld(offset_x, 0);
+
+           d = dst_itr;
+           x = 0;
+           while (x < w_align)
+             {
+                pld(s, 32);
+                pld(offset_x + x, 32);
+
+                UNROLL8(
+                          {
+                          _soft8_pt_blend_solid_solid_mul_color_transp
+                          (d, s[offset_x[x]], alpha, r, g, b); x++; d++;}
+                );
+             }
+
+           for (; x < w; x++, d++)
+              _soft8_pt_blend_solid_solid_mul_color_transp
+                  (d, s[offset_x[x]], alpha, r, g, b);
+        }
+}
+
+static void
+_soft8_image_draw_scaled_transp_solid_mul_color(Soft8_Image * src,
+                                                Soft8_Image * dst,
+                                                RGBA_Draw_Context *
+                                                dc __UNUSED__, int dst_offset,
+                                                int w, int h, int *offset_x,
+                                                int *offset_y, DATA8 r, DATA8 g,
+                                                DATA8 b, DATA8 alpha)
+{
+   DATA8 *dst_itr;
+   int y, w_align;
+
+   w_align = w & ~7;
+
+   dst_itr = dst->pixels + dst_offset;
+
+   if (alpha == 0xff)
+      for (y = 0; y < h; y++, dst_itr += dst->stride)
+        {
+           DATA8 *d, *s;
+           DATA8 *a;
+           int x;
+
+           s = src->pixels + offset_y[y];
+           a = src->alpha + offset_y[y];
+           pld(s, 0);
+           pld(a, 0);
+           pld(offset_x, 0);
+
+           d = dst_itr;
+           x = 0;
+           while (x < w_align)
+             {
+                pld(s, 32);
+                pld(a, 8);
+                pld(offset_x + x, 32);
+
+                UNROLL8(
+                          {
+                          int off_x = offset_x[x];
+                          _soft8_pt_blend_transp_solid_mul_color_solid
+                          (d, s[off_x], a[off_x], r, g, b); x++; d++;});
+             }
+
+           for (; x < w; x++, d++)
+              _soft8_pt_blend_transp_solid_mul_color_solid
+                  (d, s[offset_x[x]], a[offset_x[x]], r, g, b);
+        }
+   else
+      for (y = 0; y < h; y++, dst_itr += dst->stride)
+        {
+           DATA8 *d, *s;
+           DATA8 *a;
+           int x;
+
+           s = src->pixels + offset_y[y];
+           a = src->alpha + offset_y[y];
+           pld(s, 0);
+           pld(a, 0);
+           pld(offset_x, 0);
+
+           d = dst_itr;
+           x = 0;
+           while (x < w_align)
+             {
+                pld(s, 32);
+                pld(a, 8);
+                pld(offset_x + x, 32);
+
+                UNROLL8(
+                          {
+                          int off_x = offset_x[x];
+                          _soft8_pt_blend_transp_solid_mul_color_transp
+                          (d, s[off_x], a[off_x], alpha, r, g, b); x++; d++;});
+             }
+
+           for (; x < w; x++, d++)
+              _soft8_pt_blend_transp_solid_mul_color_transp
+                  (d, s[offset_x[x]], a[offset_x[x]], alpha, r, g, b);
+        }
+}
+
+static inline void
+_soft8_image_draw_scaled_mul_color(Soft8_Image * src, Soft8_Image * dst,
+                                   RGBA_Draw_Context * dc,
+                                   int dst_offset, int w, int h,
+                                   int *offset_x, int *offset_y,
+                                   DATA8 r, DATA8 g, DATA8 b, DATA8 a)
+{
+   if ((src->cache_entry.flags.alpha && src->alpha) &&
+       (!dst->cache_entry.flags.alpha))
+      _soft8_image_draw_scaled_transp_solid_mul_color
+          (src, dst, dc, dst_offset, w, h, offset_x, offset_y, r, g, b, a);
+   else if (!dst->cache_entry.flags.alpha)
+      _soft8_image_draw_scaled_solid_solid_mul_color
+          (src, dst, dc, dst_offset, w, h, offset_x, offset_y, r, g, b, a);
+   else
+      ERR("Unsupported draw of scaled images src->cache_entry.flags.alpha=%d, "
+          "dst->cache_entry.flags.alpha=%d, WITH COLOR MUL 0x%08x",
+          src->cache_entry.flags.alpha, dst->cache_entry.flags.alpha,
+          dc->mul.col);
+}
+
+static inline void
+_soft8_image_draw_scaled_mul(Soft8_Image * src, Soft8_Image * dst,
+                             RGBA_Draw_Context * dc,
+                             int dst_offset, int w, int h,
+                             int *offset_x, int *offset_y, DATA8 r, DATA8 g,
+                             DATA8 b, DATA8 a)
+{
+   if ((a == r) && (a == g) && (a == b))
+      _soft8_image_draw_scaled_mul_alpha
+          (src, dst, dc, dst_offset, w, h, offset_x, offset_y, a);
+   else
+      _soft8_image_draw_scaled_mul_color
+          (src, dst, dc, dst_offset, w, h, offset_x, offset_y, r, g, b, a);
+}
+
+void
+soft8_image_draw_scaled_sampled(Soft8_Image * src, Soft8_Image * dst,
+                                RGBA_Draw_Context * dc,
+                                const Eina_Rectangle sr,
+                                const Eina_Rectangle dr,
+                                const Eina_Rectangle cr)
+{
+   int x, y, dst_offset, *offset_x, *offset_y;
+   DATA8 mul_gry8;
+   DATA8 r, g, b, a;
+
+   if (!dc->mul.use)
+     {
+        r = g = b = a = 0xff;
+        mul_gry8 = 0xff;
+     }
+   else
+     {
+        a = A_VAL(&dc->mul.col);
+        if (a == 0)
+           return;
+
+        r = R_VAL(&dc->mul.col);
+        g = G_VAL(&dc->mul.col);
+        b = B_VAL(&dc->mul.col);
+
+        if (r > a)
+           r = a;
+        if (g > a)
+           g = a;
+        if (b > a)
+           b = a;
+
+        mul_gry8 = GRY_8_FROM_COMPONENTS(r, g, b);
+     }
+
+   /* pre-calculated scale tables */
+   offset_x = alloca(cr.w * sizeof(*offset_x));
+   for (x = 0; x < cr.w; x++)
+      offset_x[x] = (((x + cr.x - dr.x) * sr.w) / dr.w) + sr.x;
+
+   offset_y = alloca(cr.h * sizeof(*offset_y));
+   for (y = 0; y < cr.h; y++)
+      offset_y[y] = (((((y + cr.y - dr.y) * sr.h) / dr.h) + sr.y)
+                     * src->stride);
+
+   dst_offset = cr.x + (cr.y * dst->stride);
+
+   if (mul_gry8 == 0xff)
+      _soft8_image_draw_scaled_no_mul
+          (src, dst, dc, dst_offset, cr.w, cr.h, offset_x, offset_y);
+   else
+      _soft8_image_draw_scaled_mul
+          (src, dst, dc, dst_offset, cr.w, cr.h, offset_x, offset_y, r, g, b,
+           a);
+}
diff --git a/src/lib/engines/common_8/evas_soft8_image_unscaled.c b/src/lib/engines/common_8/evas_soft8_image_unscaled.c
new file mode 100644 (file)
index 0000000..912e5fe
--- /dev/null
@@ -0,0 +1,284 @@
+#include "evas_common_soft8.h"
+#include "evas_soft8_scanline_blend.c"
+
+static void
+_soft8_image_draw_unscaled_solid_solid(Soft8_Image * src, Soft8_Image * dst,
+                                       RGBA_Draw_Context * dc __UNUSED__,
+                                       int src_offset, int dst_offset,
+                                       int w, int h)
+{
+   DATA8 *src_itr, *dst_itr;
+   int y;
+
+   src_itr = src->pixels + src_offset;
+   dst_itr = dst->pixels + dst_offset;
+
+   for (y = 0; y < h; y++)
+     {
+        _soft8_scanline_blend_solid_solid(src_itr, dst_itr, w);
+        src_itr += src->stride;
+        dst_itr += dst->stride;
+     }
+}
+
+static void
+_soft8_image_draw_unscaled_transp_solid(Soft8_Image * src, Soft8_Image * dst,
+                                        RGBA_Draw_Context * dc __UNUSED__,
+                                        int src_offset, int dst_offset,
+                                        int w, int h)
+{
+   DATA8 *src_itr, *dst_itr;
+   DATA8 *alpha_itr;
+   int y;
+
+   src_itr = src->pixels + src_offset;
+   alpha_itr = src->alpha + src_offset;
+   dst_itr = dst->pixels + dst_offset;
+
+   for (y = 0; y < h; y++)
+     {
+        _soft8_scanline_blend_transp_solid(src_itr, alpha_itr, dst_itr, w);
+        src_itr += src->stride;
+        alpha_itr += src->stride;
+        dst_itr += dst->stride;
+     }
+}
+
+static inline void
+_soft8_image_draw_unscaled_no_mul(Soft8_Image * src, Soft8_Image * dst,
+                                  RGBA_Draw_Context * dc,
+                                  int src_offset, int dst_offset,
+                                  int width, int height)
+{
+   if (src->cache_entry.flags.alpha && (!dst->cache_entry.flags.alpha))
+      _soft8_image_draw_unscaled_transp_solid(src, dst, dc,
+                                              src_offset, dst_offset,
+                                              width, height);
+   else if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha))
+      _soft8_image_draw_unscaled_solid_solid(src, dst, dc,
+                                             src_offset, dst_offset,
+                                             width, height);
+   else
+      ERR("Unsupported draw of unscaled images src->cache_entry.flags.alpha=%d, "
+          "dst->cache_entry.flags.alpha=%d, WITHOUT COLOR MUL",
+          src->cache_entry.flags.alpha, dst->cache_entry.flags.alpha);
+}
+
+static void
+_soft8_image_draw_unscaled_solid_solid_mul_alpha(Soft8_Image * src,
+                                                 Soft8_Image * dst,
+                                                 RGBA_Draw_Context *
+                                                 dc __UNUSED__, int src_offset,
+                                                 int dst_offset, int w, int h,
+                                                 DATA8 a)
+{
+   DATA8 *src_itr, *dst_itr;
+   int y;
+
+   src_itr = src->pixels + src_offset;
+   dst_itr = dst->pixels + dst_offset;
+
+   for (y = 0; y < h; y++)
+     {
+        _soft8_scanline_blend_solid_solid_mul_alpha(src_itr, dst_itr, w, a);
+        src_itr += src->stride;
+        dst_itr += dst->stride;
+     }
+}
+
+static void
+_soft8_image_draw_unscaled_transp_solid_mul_alpha(Soft8_Image * src,
+                                                  Soft8_Image * dst,
+                                                  RGBA_Draw_Context *
+                                                  dc __UNUSED__, int src_offset,
+                                                  int dst_offset, int w, int h,
+                                                  DATA8 a)
+{
+   DATA8 *src_itr, *dst_itr;
+   DATA8 *alpha_itr;
+   int y;
+
+   src_itr = src->pixels + src_offset;
+   alpha_itr = src->alpha + src_offset;
+   dst_itr = dst->pixels + dst_offset;
+
+   for (y = 0; y < h; y++)
+     {
+        _soft8_scanline_blend_transp_solid_mul_alpha(src_itr, alpha_itr,
+                                                     dst_itr, w, a);
+        src_itr += src->stride;
+        alpha_itr += src->stride;
+        dst_itr += dst->stride;
+     }
+}
+
+static inline void
+_soft8_image_draw_unscaled_mul_alpha(Soft8_Image * src, Soft8_Image * dst,
+                                     RGBA_Draw_Context * dc,
+                                     int src_offset, int dst_offset,
+                                     int width, int height, DATA8 a)
+{
+   if (src->cache_entry.flags.alpha && (!dst->cache_entry.flags.alpha))
+      _soft8_image_draw_unscaled_transp_solid_mul_alpha
+          (src, dst, dc, src_offset, dst_offset, width, height, a);
+   else if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha))
+      _soft8_image_draw_unscaled_solid_solid_mul_alpha
+          (src, dst, dc, src_offset, dst_offset, width, height, a);
+   else
+      ERR("Unsupported draw of unscaled images src->cache_entry.flags.alpha=%d, "
+          "dst->cache_entry.flags.alpha=%d, WITH ALPHA MUL %d",
+          src->cache_entry.flags.alpha, dst->cache_entry.flags.alpha, A_VAL(&dc->mul.col));
+}
+
+static void
+_soft8_image_draw_unscaled_solid_solid_mul_color(Soft8_Image * src,
+                                                 Soft8_Image * dst,
+                                                 RGBA_Draw_Context *
+                                                 dc __UNUSED__, int src_offset,
+                                                 int dst_offset, int w, int h,
+                                                 DATA8 r, DATA8 g, DATA8 b,
+                                                 DATA8 a)
+{
+   DATA8 *src_itr, *dst_itr;
+   int y;
+
+   src_itr = src->pixels + src_offset;
+   dst_itr = dst->pixels + dst_offset;
+
+   if (a == 0xff)
+      for (y = 0; y < h; y++)
+        {
+           _soft8_scanline_blend_solid_solid_mul_color_solid
+               (src_itr, dst_itr, w, r, g, b);
+           src_itr += src->stride;
+           dst_itr += dst->stride;
+        }
+   else
+      for (y = 0; y < h; y++)
+        {
+           _soft8_scanline_blend_solid_solid_mul_color_transp
+               (src_itr, dst_itr, w, a, r, g, b);
+           src_itr += src->stride;
+           dst_itr += dst->stride;
+        }
+}
+
+static void
+_soft8_image_draw_unscaled_transp_solid_mul_color(Soft8_Image * src,
+                                                  Soft8_Image * dst,
+                                                  RGBA_Draw_Context *
+                                                  dc __UNUSED__, int src_offset,
+                                                  int dst_offset, int w, int h,
+                                                  DATA8 r, DATA8 g, DATA8 b,
+                                                  DATA8 a)
+{
+   DATA8 *src_itr, *dst_itr;
+   DATA8 *alpha_itr;
+   int y;
+
+   src_itr = src->pixels + src_offset;
+   alpha_itr = src->alpha + src_offset;
+   dst_itr = dst->pixels + dst_offset;
+
+   if (a == 0xff)
+      for (y = 0; y < h; y++)
+        {
+           _soft8_scanline_blend_transp_solid_mul_color_solid
+               (src_itr, alpha_itr, dst_itr, w, r, g, b);
+           src_itr += src->stride;
+           alpha_itr += src->stride;
+           dst_itr += dst->stride;
+        }
+   else
+      for (y = 0; y < h; y++)
+        {
+           _soft8_scanline_blend_transp_solid_mul_color_transp
+               (src_itr, alpha_itr, dst_itr, w, a, r, g, b);
+           src_itr += src->stride;
+           alpha_itr += src->stride;
+           dst_itr += dst->stride;
+        }
+}
+
+static inline void
+_soft8_image_draw_unscaled_mul_color(Soft8_Image * src, Soft8_Image * dst,
+                                     RGBA_Draw_Context * dc,
+                                     int src_offset, int dst_offset,
+                                     int width, int height,
+                                     DATA8 r, DATA8 g, DATA8 b, DATA8 a)
+{
+   if (src->cache_entry.flags.alpha && (!dst->cache_entry.flags.alpha))
+      _soft8_image_draw_unscaled_transp_solid_mul_color
+          (src, dst, dc, src_offset, dst_offset, width, height, r, g, b, a);
+   else if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha))
+      _soft8_image_draw_unscaled_solid_solid_mul_color
+          (src, dst, dc, src_offset, dst_offset, width, height, r, g, b, a);
+   else
+      ERR("Unsupported draw of unscaled images src->cache_entry.flags.alpha=%d, "
+          "dst->cache_entry.flags.alpha=%d, WITH COLOR MUL 0x%08x",
+          src->cache_entry.flags.alpha, dst->cache_entry.flags.alpha, dc->mul.col);
+}
+
+static inline void
+_soft8_image_draw_unscaled_mul(Soft8_Image * src, Soft8_Image * dst,
+                               RGBA_Draw_Context * dc,
+                               int src_offset, int dst_offset,
+                               int width, int height, DATA8 r, DATA8 g,
+                               DATA8 b, DATA8 a)
+{
+   if ((a == r) && (a == g) && (a == b))
+      _soft8_image_draw_unscaled_mul_alpha(src, dst, dc, src_offset,
+                                           dst_offset, width, height, a);
+   else
+      _soft8_image_draw_unscaled_mul_color(src, dst, dc, src_offset,
+                                           dst_offset, width, height,
+                                           r, g, b, a);
+}
+
+void
+soft8_image_draw_unscaled(Soft8_Image * src, Soft8_Image * dst,
+                          RGBA_Draw_Context * dc,
+                          const Eina_Rectangle sr,
+                          const Eina_Rectangle dr, const Eina_Rectangle cr)
+{
+   int src_offset_rows, src_offset, dst_offset;
+   DATA8 mul_gry8;
+   DATA8 r, g, b, a;
+
+   if (!dc->mul.use)
+     {
+        r = g = b = a = 0xff;
+        mul_gry8 = 0xff;
+     }
+   else
+     {
+        a = A_VAL(&dc->mul.col);
+        if (a == 0)
+           return;
+
+        r = R_VAL(&dc->mul.col);
+        g = G_VAL(&dc->mul.col);
+        b = B_VAL(&dc->mul.col);
+
+        if (r > a)
+           r = a;
+        if (g > a)
+           g = a;
+        if (b > a)
+           b = a;
+
+        mul_gry8 = GRY_8_FROM_COMPONENTS(r, g, b);
+     }
+
+   src_offset_rows = (cr.y - dr.y) + sr.y;
+   src_offset = (src_offset_rows * src->stride) + (cr.x - dr.x) + sr.x;
+
+   dst_offset = cr.x + (cr.y * dst->stride);
+
+   if (mul_gry8 == 0xff)
+      _soft8_image_draw_unscaled_no_mul(src, dst, dc, src_offset, dst_offset,
+                                        cr.w, cr.h);
+   else
+      _soft8_image_draw_unscaled_mul(src, dst, dc, src_offset, dst_offset,
+                                     cr.w, cr.h, r, g, b, a);
+}
diff --git a/src/lib/engines/common_8/evas_soft8_line.c b/src/lib/engines/common_8/evas_soft8_line.c
new file mode 100644 (file)
index 0000000..4135acf
--- /dev/null
@@ -0,0 +1,426 @@
+#include "evas_common_soft8.h"
+#include "evas_soft8_scanline_fill.c"
+
+/*
+ * All functions except by soft8_line_draw() expect x0 <= x1.
+ */
+
+static inline int
+_in_range(int value, int min, int max)
+{
+   return min <= value && value <= max;
+}
+
+static inline int
+_is_xy_inside_clip(int x, int y, const struct RGBA_Draw_Context_clip clip)
+{
+   if (!clip.use)
+      return 1;
+
+   if (!_in_range(x, clip.x, clip.x + clip.w - 1))
+      return 0;
+
+   if (!_in_range(y, clip.y, clip.y + clip.h - 1))
+      return 0;
+
+   return 1;
+}
+
+static inline int
+_is_x_inside_clip(int x, const struct RGBA_Draw_Context_clip clip)
+{
+   if (!clip.use)
+      return 1;
+
+   return _in_range(x, clip.x, clip.x + clip.w - 1);
+}
+
+static inline int
+_is_y_inside_clip(int y, const struct RGBA_Draw_Context_clip clip)
+{
+   if (!clip.use)
+      return 1;
+
+   return _in_range(y, clip.y, clip.y + clip.h - 1);
+}
+
+static inline int
+_is_xy_inside_rect(int x, int y, int w, int h)
+{
+   return _in_range(x, 0, w - 1) && _in_range(y, 0, h - 1);
+}
+
+static inline int
+_is_empty_clip(const struct RGBA_Draw_Context_clip clip)
+{
+   return clip.w < 1 || clip.h < 1;
+}
+
+static void
+_soft8_line_point(Soft8_Image * dst, RGBA_Draw_Context * dc, int x, int y)
+{
+   DATA8 gry8, *dst_itr;
+   DATA8 alpha;
+
+   if (!_is_xy_inside_rect(x, y, dst->cache_entry.w, dst->cache_entry.h))
+      return;
+
+   if (!_is_xy_inside_clip(x, y, dc->clip))
+      return;
+
+   dst_itr = dst->pixels + (dst->stride * y) + x;
+   alpha = A_VAL(&dc->col.col);
+   gry8 = GRY_8_FROM_RGB(&dc->col.col);
+
+   if (alpha == 0xff)
+      _soft8_pt_fill_solid_solid(dst_itr, gry8);
+   else if (alpha > 0)
+     {
+        alpha++;
+        _soft8_pt_fill_transp_solid(dst_itr, gry8, alpha);
+     }
+}
+
+static void
+_soft8_line_horiz(Soft8_Image * dst, RGBA_Draw_Context * dc, int x0, int x1,
+                  int y)
+{
+   DATA8 gry8, *dst_itr;
+   DATA8 alpha;
+   int w;
+
+   if (!_is_y_inside_clip(y, dc->clip))
+      return;
+
+   if (x0 < dc->clip.x)
+      x0 = dc->clip.x;
+
+   if (x1 >= dc->clip.x + dc->clip.w)
+      x1 = dc->clip.x + dc->clip.w - 1;
+
+   w = x1 - x0;
+   if (w < 1)
+      return;
+
+   dst_itr = dst->pixels + (dst->stride * y) + x0;
+   alpha = A_VAL(&dc->col.col);
+   gry8 = GRY_8_FROM_RGB(&dc->col.col);
+
+   if (alpha == 0xff)
+      _soft8_scanline_fill_solid_solid(dst_itr, w, gry8);
+   else if (alpha > 0)
+     {
+        alpha++;
+        _soft8_scanline_fill_transp_solid(dst_itr, w, gry8, alpha);
+     }
+}
+
+static void
+_soft8_line_vert(Soft8_Image * dst, RGBA_Draw_Context * dc, int x, int y0,
+                 int y1)
+{
+   DATA8 gry8, *dst_itr;
+   DATA8 alpha;
+   int h;
+
+   if (!_is_x_inside_clip(x, dc->clip))
+      return;
+
+   if (y1 < y0)
+     {
+        int t;
+        t = y0;
+        y0 = y1;
+        y1 = t;
+     }
+
+   if (y0 < dc->clip.y)
+      y0 = dc->clip.y;
+
+   if (y1 >= dc->clip.y + dc->clip.h)
+      y1 = dc->clip.y + dc->clip.h - 1;
+
+   h = y1 - y0;
+   if (h < 1)
+      return;
+
+   dst_itr = dst->pixels + (dst->stride * y0) + x;
+   alpha = A_VAL(&dc->col.col);
+   gry8 = GRY_8_FROM_RGB(&dc->col.col);
+
+   if (alpha == 0xff)
+     {
+        for (; h > 0; h--, dst_itr += dst->stride)
+           _soft8_pt_fill_solid_solid(dst_itr, gry8);
+     }
+   else if (alpha > 0)
+     {
+        alpha++;
+
+        for (; h > 0; h--, dst_itr += dst->stride)
+           _soft8_pt_fill_transp_solid(dst_itr, gry8, alpha);
+     }
+}
+
+static inline void
+_soft8_line_45deg_adjust_boundaries(const struct RGBA_Draw_Context_clip clip,
+                                    int *p_x0, int *p_y0, int *p_x1, int *p_y1)
+{
+   int diff, dy, x0, y0, x1, y1;
+
+   x0 = *p_x0;
+   y0 = *p_y0;
+   x1 = *p_x1;
+   y1 = *p_y1;
+
+   dy = y1 - y0;
+
+   diff = clip.x - x0;
+   if (diff > 0)
+     {
+        x0 = clip.x;
+        y0 += (dy > 0) ? diff : -diff;
+     }
+
+   diff = x1 - (clip.x + clip.w);
+   if (diff > 0)
+     {
+        x1 = clip.x + clip.w;
+        y1 += (dy > 0) ? -diff : diff;
+     }
+
+   if (dy > 0)
+     {
+        diff = clip.y - y0;
+        if (diff > 0)
+          {
+             y0 = clip.y;
+             x0 += diff;
+          }
+
+        diff = y1 - (clip.y + clip.h);
+        if (diff > 0)
+          {
+             y1 = clip.y + clip.h;
+             x1 -= diff;
+          }
+     }
+   else
+     {
+        diff = clip.y - y1;
+        if (diff > 0)
+          {
+             y1 = clip.y;
+             x1 -= diff;
+          }
+
+        diff = y0 - (clip.y + clip.h - 1);
+        if (diff > 0)
+          {
+             y0 = clip.y + clip.h - 1;
+             x0 += diff;
+          }
+     }
+
+   *p_x0 = x0;
+   *p_y0 = y0;
+   *p_x1 = x1;
+   *p_y1 = y1;
+}
+
+static void
+_soft8_line_45deg(Soft8_Image * dst, RGBA_Draw_Context * dc, int x0, int y0,
+                  int x1, int y1)
+{
+   int dy, step_dst_itr, len;
+   DATA8 alpha;
+   DATA8 *dst_itr, gry8;
+
+   alpha = A_VAL(&dc->col.col);
+   if (alpha < 1)
+      return;
+
+   gry8 = GRY_8_FROM_RGB(&dc->col.col);
+
+   dy = y1 - y0;
+   step_dst_itr = 1 + ((dy > 0) ? dst->stride : -dst->stride);
+
+   _soft8_line_45deg_adjust_boundaries(dc->clip, &x0, &y0, &x1, &y1);
+
+   len = (dy > 0) ? (y1 - y0) : (y0 - y1);
+   if (len < 1)
+      return;
+
+   dst_itr = dst->pixels + dst->stride * y0 + x0;
+   if (alpha == 0xff)
+     {
+        for (; len > 0; len--, dst_itr += step_dst_itr)
+           _soft8_pt_fill_solid_solid(dst_itr, gry8);
+     }
+   else
+     {
+        alpha++;
+        for (; len > 0; len--, dst_itr += step_dst_itr)
+           _soft8_pt_fill_transp_solid(dst_itr, gry8, alpha);
+     }
+}
+
+static always_inline void
+_soft8_line_aliased_pt(DATA8 * dst_itr, DATA8 gry8, DATA8 alpha)
+{
+   if (alpha == 32)
+      _soft8_pt_fill_solid_solid(dst_itr, gry8);
+   else
+      _soft8_pt_fill_transp_solid(dst_itr, gry8, alpha);
+}
+
+static void
+_soft8_line_aliased(Soft8_Image * dst, RGBA_Draw_Context * dc, int x0, int y0,
+                    int x1, int y1)
+{
+   int dx, dy, step_y, step_dst_itr;
+   DATA8 gry8;
+   DATA8 alpha;
+
+   alpha = A_VAL(&dc->col.col);
+   if (alpha == 0)
+      return;
+   alpha++;
+
+   gry8 = GRY_8_FROM_RGB(&dc->col.col);
+
+   dx = x1 - x0;
+   dy = y1 - y0;
+
+   if (dy >= 0)
+     {
+        step_y = 1;
+        step_dst_itr = dst->stride;
+     }
+   else
+     {
+        dy = -dy;
+        step_y = -1;
+        step_dst_itr = -dst->stride;
+     }
+
+   if (dx > dy)
+     {
+        DATA8 *dst_itr;
+        int e, x, y;
+
+        e = -(dx / 2);
+        y = y0;
+        dst_itr = dst->pixels + dst->stride * y0 + x0;
+        for (x = x0; x <= x1; x++, dst_itr++)
+          {
+             if (_is_xy_inside_clip(x, y, dc->clip))
+                _soft8_line_aliased_pt(dst_itr, gry8, alpha);
+
+             e += dy;
+             if (e >= 0)
+               {
+                  dst_itr += step_dst_itr;
+                  y += step_y;
+                  e -= dx;
+               }
+          }
+     }
+   else
+     {
+        DATA8 *dst_itr;
+        int e, x, y;
+
+        e = -(dy / 2);
+        x = x0;
+        dst_itr = dst->pixels + dst->stride * y0 + x0;
+        for (y = y0; y != y1; y += step_y, dst_itr += step_dst_itr)
+          {
+             if (_is_xy_inside_clip(x, y, dc->clip))
+                _soft8_line_aliased_pt(dst_itr, gry8, alpha);
+
+             e += dx;
+             if (e >= 0)
+               {
+                  dst_itr++;
+                  x++;
+                  e -= dy;
+               }
+          }
+     }
+}
+
+void
+soft8_line_draw(Soft8_Image * dst, RGBA_Draw_Context * dc, int x0, int y0,
+                int x1, int y1)
+{
+   struct RGBA_Draw_Context_clip c_bkp, c_tmp;
+   int dx, dy;
+   int x, y, w, h;
+
+   c_tmp.use = 1;
+   c_tmp.x = 0;
+   c_tmp.y = 0;
+   c_tmp.w = dst->cache_entry.w;
+   c_tmp.h = dst->cache_entry.h;
+
+   /* save out clip info */
+   c_bkp = dc->clip;
+   if (c_bkp.use)
+     {
+        RECTS_CLIP_TO_RECT(c_tmp.x, c_tmp.y, c_tmp.w, c_tmp.h,
+                           c_bkp.x, c_bkp.y, c_bkp.w, c_bkp.h);
+        if (_is_empty_clip(c_tmp))
+           return;
+     }
+
+   x = MIN(x0, x1);
+   y = MIN(y0, y1);
+   w = MAX(x0, x1) - x + 1;
+   h = MAX(y0, y1) - y + 1;
+
+   RECTS_CLIP_TO_RECT(c_tmp.x, c_tmp.y, c_tmp.w, c_tmp.h, x, y, w, h);
+   if (_is_empty_clip(c_tmp))
+      return;
+
+   /* Check if the line doesn't cross the clip area */
+   if (x0 < c_tmp.x && x1 < c_tmp.x)
+      return;
+   if (x0 >= c_tmp.x + c_tmp.w && x1 >= c_tmp.x + c_tmp.w)
+      return;
+   if (y0 < c_tmp.y && y1 < c_tmp.y)
+      return;
+   if (y0 >= c_tmp.y + c_tmp.h && y1 >= c_tmp.y + c_tmp.h)
+      return;
+
+   dc->clip = c_tmp;
+   dx = x1 - x0;
+   dy = y1 - y0;
+
+   if (dx < 0)
+     {
+        int t;
+
+        t = x0;
+        x0 = x1;
+        x1 = t;
+
+        t = y0;
+        y0 = y1;
+        y1 = t;
+     }
+
+   if (dx == 0 && dy == 0)
+      _soft8_line_point(dst, dc, x0, y0);
+   else if (dx == 0)
+      _soft8_line_vert(dst, dc, x0, y0, y1);
+   else if (dy == 0)
+      _soft8_line_horiz(dst, dc, x0, x1, y0);
+   else if (dy == dx || dy == -dx)
+      _soft8_line_45deg(dst, dc, x0, y0, x1, y1);
+   else
+      _soft8_line_aliased(dst, dc, x0, y0, x1, y1);
+
+   /* restore clip info */
+   dc->clip = c_bkp;
+}
diff --git a/src/lib/engines/common_8/evas_soft8_main.c b/src/lib/engines/common_8/evas_soft8_main.c
new file mode 100644 (file)
index 0000000..4072a20
--- /dev/null
@@ -0,0 +1,659 @@
+#include "evas_common_soft8.h"
+
+static Evas_Cache_Image *eci = NULL;
+static int reference = 0;
+
+static Image_Entry *_evas_common_soft8_image_new(void);
+static void _evas_common_soft8_image_delete(Image_Entry * ie);
+
+static int _evas_common_soft8_image_surface_alloc(Image_Entry * ie, int w,
+                                                  int h);
+static void _evas_common_soft8_image_surface_delete(Image_Entry * ie);
+static DATA32 *_evas_common_soft8_image_surface_pixels(Image_Entry * ie);
+
+static int _evas_common_load_soft8_image_from_file(Image_Entry * ie);
+static void _evas_common_soft8_image_unload(Image_Entry * ie);
+
+static void _evas_common_soft8_image_dirty_region(Image_Entry * im, int x,
+                                                  int y, int w, int h);
+static int _evas_common_soft8_image_dirty(Image_Entry * ie_dst,
+                                          const Image_Entry * ie_src);
+
+static int _evas_common_soft8_image_ram_usage(Image_Entry * ie);
+
+static int _evas_common_soft8_image_size_set(Image_Entry * ie_dst,
+                                             const Image_Entry * ie_im, int w,
+                                             int h);
+static int _evas_common_soft8_image_from_copied_data(Image_Entry * ie_dst,
+                                                     int w, int h,
+                                                     DATA32 * image_data,
+                                                     int alpha, int cspace);
+static int _evas_common_soft8_image_from_data(Image_Entry * ie_dst, int w,
+                                              int h, DATA32 * image_data,
+                                              int alpha, int cspace);
+static int _evas_common_soft8_image_colorspace_set(Image_Entry * ie_dst,
+                                                   int cspace);
+
+static int _evas_common_load_soft8_image_data_from_file(Image_Entry * ie);
+
+/*
+static void
+_evas_common_soft8_image_debug(const char* context, Image_Entry *eim)
+{
+   DBG("[8] %p = [%s] {%s,%s} %i [%i|%i]\n", eim, context, eim->file, eim->key, eim->references, eim->w, eim->h);
+}
+*/
+
+static const Evas_Cache_Image_Func _evas_common_soft8_image_func = {
+   _evas_common_soft8_image_new,
+   _evas_common_soft8_image_delete,
+   _evas_common_soft8_image_surface_alloc,
+   _evas_common_soft8_image_surface_delete,
+   _evas_common_soft8_image_surface_pixels,
+   _evas_common_load_soft8_image_from_file,
+   _evas_common_soft8_image_unload,
+   _evas_common_soft8_image_dirty_region,
+   _evas_common_soft8_image_dirty,
+   _evas_common_soft8_image_size_set,
+   _evas_common_soft8_image_from_copied_data,
+   _evas_common_soft8_image_from_data,
+   _evas_common_soft8_image_colorspace_set,
+   _evas_common_load_soft8_image_data_from_file,
+   _evas_common_soft8_image_ram_usage,
+/*    _evas_common_soft8_image_debug */
+   NULL
+};
+
+EAPI void
+evas_common_soft8_image_init(void)
+{
+   if (!eci)
+      eci = evas_cache_image_init(&_evas_common_soft8_image_func);
+   reference++;
+}
+
+EAPI void
+evas_common_soft8_image_shutdown(void)
+{
+   if (--reference == 0)
+     {
+// DISABLE for now - something wrong with cache shutdown freeing things
+// still in use - rage_thumb segv's now.
+//
+// actually - i think i see it. cache ref goes to 0 (and thus gets freed)
+// because in eng_setup() when a buffer changes size it is FIRST freed
+// THEN allocated again - thus brignhjing ref to 0 then back to 1 immediately
+// where it should stay at 1. - see evas_engine.c in the buffer enigne for
+// example. eng_output_free() is called BEFORE _output_setup(). although this
+// is only a SIGNE of the problem. we can patch this up with either freeing
+// after the setup (so we just pt a ref of 2 then back to 1), or just 
+// evas_common_image_init() at the start and evas_common_image_shutdown()
+// after it all. really ref 0 should only be reached when no more canvases
+// with no more objects exist anywhere.
+
+// ENABLE IT AGAIN, hope it is fixed. Gustavo @ January 22nd, 2009.
+        //evas_cache_image_shutdown(eci);
+        //eci = NULL;
+     }
+}
+
+EAPI Evas_Cache_Image *
+evas_common_soft8_image_cache_get(void)
+{
+   return eci;
+}
+
+static Image_Entry *
+_evas_common_soft8_image_new(void)
+{
+   Soft8_Image *im;
+
+   im = calloc(1, sizeof(Soft8_Image));
+   if (!im)
+      return NULL;
+
+   im->stride = -1;
+
+   return (Image_Entry *) im;
+}
+
+static void
+_evas_common_soft8_image_delete(Image_Entry * ie)
+{
+   memset(ie, 0xFF, sizeof(Soft8_Image));
+   free(ie);
+}
+
+static int
+_evas_common_soft8_image_surface_alloc(Image_Entry * ie, int w, int h)
+{
+   Soft8_Image *im = (Soft8_Image *) ie;
+
+   if (im->stride < 0)
+      im->stride = _calc_stride(w);
+
+   im->pixels =
+       realloc(im->pixels, IMG_BYTE_SIZE(im->stride, h, ie->flags.alpha));
+   if (!im->pixels)
+      return -1;
+
+   if (ie->flags.alpha)
+     {
+        im->alpha = (DATA8 *) (im->pixels + (im->stride * h));
+        im->flags.free_alpha = 0;
+     }
+   im->flags.free_pixels = 1;
+
+   return 0;
+}
+
+static void
+_evas_common_soft8_image_surface_delete(Image_Entry * ie)
+{
+   Soft8_Image *im = (Soft8_Image *) ie;
+
+   if (im->flags.free_pixels)
+      free(im->pixels);
+   im->pixels = NULL;
+   im->flags.free_pixels = 0;
+
+   if (im->flags.free_alpha)
+      free(im->alpha);
+   im->alpha = NULL;
+   im->flags.free_alpha = 0;
+}
+
+static DATA32 *
+_evas_common_soft8_image_surface_pixels(Image_Entry * ie __UNUSED__)
+{
+   abort();
+
+   return NULL;
+}
+
+static int
+_evas_common_load_soft8_image_from_file(Image_Entry * ie)
+{
+   Soft8_Image *sim = (Soft8_Image *) ie;
+   RGBA_Image *im;
+   int error = 0;
+
+   im = (RGBA_Image *) evas_cache_image_request(evas_common_image_cache_get(),
+                                                sim->cache_entry.file,
+                                                sim->cache_entry.key,
+                                                &sim->cache_entry.load_opts,
+                                                &error);
+   sim->source = im;
+   if (!sim->source)
+      return -1;
+
+   sim->cache_entry.w = sim->source->cache_entry.w;
+   sim->cache_entry.h = sim->source->cache_entry.h;
+   ie->flags.alpha = im->cache_entry.flags.alpha;
+   if (sim->stride < 0)
+      sim->stride = _calc_stride(sim->cache_entry.w);
+
+   return 0;
+}
+
+static void
+_evas_common_soft8_image_unload(Image_Entry * ie __UNUSED__)
+{
+}
+
+static void
+_evas_common_soft8_image_dirty_region(Image_Entry * im __UNUSED__,
+                                      int x __UNUSED__, int y __UNUSED__,
+                                      int w __UNUSED__, int h __UNUSED__)
+{
+}
+
+static int
+_evas_common_soft8_image_dirty(Image_Entry * ie_dst, const Image_Entry * ie_src)
+{
+   Soft8_Image *dst = (Soft8_Image *) ie_dst;
+   Soft8_Image *src = (Soft8_Image *) ie_src;
+
+   evas_cache_image_load_data(&src->cache_entry);
+   evas_cache_image_surface_alloc(&dst->cache_entry,
+                                  src->cache_entry.w, src->cache_entry.h);
+
+/*    evas_common_blit_rectangle(src, dst, 0, 0, src->cache_entry.w, src->cache_entry.h, 0, 0); */
+
+   return 0;
+}
+
+static int
+_evas_common_soft8_image_ram_usage(Image_Entry * ie)
+{
+   Soft8_Image *im = (Soft8_Image *) ie;
+
+   if (im->pixels && im->flags.free_pixels)
+      return IMG_BYTE_SIZE(im->stride, im->cache_entry.h, ie->flags.alpha);
+   return 0;
+}
+
+static int
+_evas_common_soft8_image_size_set(Image_Entry * ie_dst,
+                                  const Image_Entry * ie_im, int w __UNUSED__,
+                                  int h __UNUSED__)
+{
+   Soft8_Image *dst = (Soft8_Image *) ie_dst;
+   Soft8_Image *im = (Soft8_Image *) ie_im;
+
+   dst->flags = im->flags;
+
+   return 0;
+}
+
+static int
+_evas_common_soft8_image_from_data(Image_Entry * ie_dst, int w, int h,
+                                   DATA32 * image_data, int alpha,
+                                   int cspace __UNUSED__)
+{
+   Soft8_Image *im = (Soft8_Image *) ie_dst;
+
+   /* FIXME: handle colorspace */
+   ie_dst->w = w;
+   ie_dst->h = h;
+   ie_dst->flags.alpha = alpha;
+
+   im->flags.free_pixels = 0;
+   im->flags.free_alpha = 0;
+   if (im->stride < 0)
+      im->stride = _calc_stride(w);
+
+   /* FIXME: That's bad, the application must be aware of the engine internal. */
+   im->pixels = (DATA8 *) image_data;
+   if (ie_dst->flags.alpha)
+      im->alpha = (DATA8 *) (im->pixels + (im->stride * h));
+
+   return 0;
+}
+
+static int
+_evas_common_soft8_image_from_copied_data(Image_Entry * ie_dst,
+                                          int w __UNUSED__, int h,
+                                          DATA32 * image_data,
+                                          int alpha __UNUSED__,
+                                          int cspace __UNUSED__)
+{
+   Soft8_Image *im = (Soft8_Image *) ie_dst;
+
+   /* FIXME: handle colorspace */
+   if (image_data)
+      memcpy(im->pixels, image_data,
+             IMG_BYTE_SIZE(im->stride, h, ie_dst->flags.alpha));
+   else
+      memset(im->pixels, 0, IMG_BYTE_SIZE(im->stride, h, ie_dst->flags.alpha));
+
+   return 0;
+}
+
+static int
+_evas_common_soft8_image_colorspace_set(Image_Entry * ie_dst,
+                                        int cspace __UNUSED__)
+{
+   /* FIXME: handle colorspace */
+   return 0;
+}
+
+static int
+_evas_common_load_soft8_image_data_from_file(Image_Entry * ie)
+{
+   Soft8_Image *im = (Soft8_Image *) ie;
+
+   if (im->pixels)
+      return 0;
+   if (!im->source)
+      return -1;
+
+   evas_cache_image_load_data(&im->source->cache_entry);
+   if (im->source->image.data)
+     {
+        DATA32 *sp;
+
+        evas_cache_image_surface_alloc(&im->cache_entry,
+                                       im->source->cache_entry.w,
+                                       im->source->cache_entry.h);
+
+        sp = im->source->image.data;
+        if (im->alpha)
+           soft8_image_convert_from_rgba(im, sp);
+        else
+           soft8_image_convert_from_rgb(im, sp);
+     }
+   evas_cache_image_drop(&im->source->cache_entry);
+   im->source = NULL;
+
+   return 0;
+}
+
+/* Soft16_Image * */
+/* soft16_image_new(int w, int h, int stride, int have_alpha, DATA16 *pixels, */
+/*              int copy) */
+/* { */
+/*    Soft16_Image *im; */
+
+/*    if (stride < 0) stride = _calc_stride(w); */
+
+/*    im = soft16_image_alloc(w, h, stride, have_alpha, copy); */
+/*    if (!im) return NULL; */
+
+/*    if (pixels) */
+/*      { */
+/*     if (copy) */
+/*       memcpy(im->pixels, pixels, IMG_BYTE_SIZE(stride, h, have_alpha)); */
+/*     else */
+/*       { */
+/*          im->pixels = pixels; */
+/*          if (have_alpha) im->alpha = (DATA8 *)(im->pixels + (stride * h)); */
+/*       } */
+/*      } */
+/*    return im; */
+/* } */
+
+static inline void
+_get_clip(const RGBA_Draw_Context * dc, const Soft8_Image * im,
+          Eina_Rectangle * clip)
+{
+   if (dc->clip.use)
+     {
+        EINA_RECTANGLE_SET(clip, dc->clip.x, dc->clip.y, dc->clip.w,
+                           dc->clip.h);
+        if (clip->x < 0)
+          {
+             clip->w += clip->x;
+             clip->x = 0;
+          }
+        if (clip->y < 0)
+          {
+             clip->h += clip->y;
+             clip->y = 0;
+          }
+        if ((clip->x + clip->w) > im->cache_entry.w)
+           clip->w = im->cache_entry.w - clip->x;
+        if ((clip->y + clip->h) > im->cache_entry.h)
+           clip->h = im->cache_entry.h - clip->y;
+     }
+   else
+     {
+        EINA_RECTANGLE_SET(clip, 0, 0, im->cache_entry.w, im->cache_entry.h);
+     }
+}
+
+static inline int
+_is_empty_rectangle(const Eina_Rectangle * r)
+{
+   return (r->w < 1) || (r->h < 1);
+}
+
+static inline void
+_shrink(int *s_pos, int *s_size, int pos, int size)
+{
+   int d;
+
+   d = (*s_pos) - pos;
+   if (d < 0)
+     {
+        (*s_size) += d;
+        (*s_pos) = pos;
+     }
+
+   d = size + pos - (*s_pos);
+   if ((*s_size) > d)
+      (*s_size) = d;
+}
+
+static int
+_soft8_adjust_areas(Eina_Rectangle * src,
+                    int src_max_x, int src_max_y,
+                    Eina_Rectangle * dst,
+                    int dst_max_x, int dst_max_y, Eina_Rectangle * dst_clip)
+{
+   if (_is_empty_rectangle(src) ||
+       _is_empty_rectangle(dst) || _is_empty_rectangle(dst_clip))
+      return 0;
+
+   /* shrink clip */
+   _shrink(&dst_clip->x, &dst_clip->w, dst->x, dst->w);
+   _shrink(&dst_clip->y, &dst_clip->h, dst->y, dst->h);
+   if (_is_empty_rectangle(dst_clip))
+      return 0;
+
+   /* sanitise x */
+   if (src->x < 0)
+     {
+        dst->x -= (src->x * dst->w) / src->w;
+        dst->w += (src->x * dst->w) / src->w;
+        src->w += src->x;
+        src->x = 0;
+     }
+   if (src->x >= src_max_x)
+      return 0;
+   if ((src->x + src->w) > src_max_x)
+     {
+        dst->w = (dst->w * (src_max_x - src->x)) / (src->w);
+        src->w = src_max_x - src->x;
+     }
+   if (dst->w <= 0)
+      return 0;
+   if (src->w <= 0)
+      return 0;
+   if (dst_clip->x < 0)
+     {
+        dst_clip->w += dst_clip->x;
+        dst_clip->x = 0;
+     }
+   if (dst_clip->w <= 0)
+      return 0;
+   if (dst_clip->x >= dst_max_x)
+      return 0;
+
+   _shrink(&dst_clip->x, &dst_clip->w, 0, dst_max_x);
+   if (dst_clip->w <= 0)
+      return 0;
+
+   /* sanitise y */
+   if (src->y < 0)
+     {
+        dst->y -= (src->y * dst->h) / src->h;
+        dst->h += (src->y * dst->h) / src->h;
+        src->h += src->y;
+        src->y = 0;
+     }
+   if (src->y >= src_max_y)
+      return 0;
+   if ((src->y + src->h) > src_max_y)
+     {
+        dst->h = (dst->h * (src_max_y - src->y)) / (src->h);
+        src->h = src_max_y - src->y;
+     }
+   if (dst->h <= 0)
+      return 0;
+   if (src->h <= 0)
+      return 0;
+   if (dst_clip->y < 0)
+     {
+        dst_clip->h += dst_clip->y;
+        dst_clip->y = 0;
+     }
+   if (dst_clip->h <= 0)
+      return 0;
+   if (dst_clip->y >= dst_max_y)
+      return 0;
+
+   _shrink(&dst_clip->y, &dst_clip->h, 0, dst_max_y);
+   if (dst_clip->h <= 0)
+      return 0;
+
+   return 1;
+}
+
+static void
+_soft8_image_draw_sampled_int(Soft8_Image * src, Soft8_Image * dst,
+                              RGBA_Draw_Context * dc,
+                              Eina_Rectangle sr, Eina_Rectangle dr)
+{
+   Eina_Rectangle cr;
+
+   if (!
+       (RECTS_INTERSECT
+        (dr.x, dr.y, dr.w, dr.h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
+      return;
+   if (!
+       (RECTS_INTERSECT
+        (sr.x, sr.y, sr.w, sr.h, 0, 0, src->cache_entry.w, src->cache_entry.h)))
+      return;
+
+   _get_clip(dc, dst, &cr);
+   if (!_soft8_adjust_areas
+       (&sr, src->cache_entry.w, src->cache_entry.h, &dr, dst->cache_entry.w,
+        dst->cache_entry.h, &cr))
+      return;
+
+   if ((dr.w == sr.w) && (dr.h == sr.h))
+      soft8_image_draw_unscaled(src, dst, dc, sr, dr, cr);
+   else
+      soft8_image_draw_scaled_sampled(src, dst, dc, sr, dr, cr);
+}
+
+EAPI void
+soft8_image_draw(Soft8_Image * src, Soft8_Image * dst,
+                 RGBA_Draw_Context * dc,
+                 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, int smooth)
+{
+   Eina_Rectangle sr, dr;
+   Cutout_Rects *rects;
+   Cutout_Rect *r;
+   struct RGBA_Draw_Context_clip clip_bkp;
+   int i;
+
+   /* handle cutouts here! */
+   EINA_RECTANGLE_SET(&dr, dst_region_x, dst_region_y, dst_region_w,
+                      dst_region_h);
+
+   if (_is_empty_rectangle(&dr))
+      return;
+   if (!
+       (RECTS_INTERSECT
+        (dr.x, dr.y, dr.w, dr.h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
+      return;
+
+   EINA_RECTANGLE_SET(&sr, src_region_x, src_region_y, src_region_w,
+                      src_region_h);
+
+   if (_is_empty_rectangle(&sr))
+      return;
+   if (!
+       (RECTS_INTERSECT
+        (sr.x, sr.y, sr.w, sr.h, 0, 0, src->cache_entry.w, src->cache_entry.h)))
+      return;
+
+   /* no cutouts - cut right to the chase */
+   if (!dc->cutout.rects)
+     {
+        _soft8_image_draw_sampled_int(src, dst, dc, sr, dr);
+        return;
+     }
+
+   /* save out clip info */
+   clip_bkp = dc->clip;
+   evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w,
+                                      dst->cache_entry.h);
+   evas_common_draw_context_clip_clip(dc, dst_region_x, dst_region_y,
+                                      dst_region_w, dst_region_h);
+   /* our clip is 0 size.. abort */
+   if ((dc->clip.w <= 0) || (dc->clip.h <= 0))
+     {
+        dc->clip = clip_bkp;
+        return;
+     }
+   rects = evas_common_draw_context_apply_cutouts(dc);
+   for (i = 0; i < rects->active; i++)
+     {
+        r = rects->rects + i;
+        evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
+        _soft8_image_draw_sampled_int(src, dst, dc, sr, dr);
+     }
+   evas_common_draw_context_apply_clear_cutouts(rects);
+   dc->clip = clip_bkp;
+}
+
+EAPI Soft8_Image *
+soft8_image_alpha_set(Soft8_Image * im, int have_alpha)
+{
+   Soft8_Image *new_im;
+
+   if (im->cache_entry.flags.alpha == have_alpha)
+      return im;
+
+   new_im = (Soft8_Image *) evas_cache_image_alone(&im->cache_entry);
+
+   new_im->cache_entry.flags.alpha = have_alpha;
+
+   if (im->cache_entry.w > 0 && im->cache_entry.h)
+      new_im =
+          (Soft8_Image *) evas_cache_image_size_set(&new_im->cache_entry,
+                                                    im->cache_entry.w,
+                                                    im->cache_entry.h);
+
+   return new_im;
+}
+
+/* Soft16_Image * */
+/* soft16_image_size_set(Soft16_Image *old_im, int w, int h) */
+/* { */
+/*    Soft16_Image *new_im; */
+/*    DATA16 *dp, *sp; */
+/*    int i, cw, ch, ew; */
+
+/*    if ((old_im->cache_entry.w == w) && (old_im->cache_entry.h == h)) return old_im; */
+
+/*    new_im = soft16_image_new(w, h, -1, old_im->flags.have_alpha, NULL, 1); */
+
+/*    if (old_im->cache_entry.w < new_im->cache_entry.w) */
+/*      cw = old_im->cache_entry.w; */
+/*    else */
+/*      cw = new_im->cache_entry.w; */
+
+/*    ew = new_im->cache_entry.w - cw; */
+
+/*    if (old_im->cache_entry.h < new_im->cache_entry.h) */
+/*      ch = old_im->cache_entry.h; */
+/*    else */
+/*      ch = new_im->cache_entry.h; */
+
+/*    dp = new_im->pixels; */
+/*    sp = old_im->pixels; */
+/*    for (i = 0; i < ch; i++) */
+/*      { */
+/*     memcpy(dp, sp, cw * sizeof(DATA16)); */
+/*     if (ew > 0) memset(dp, 0, ew * sizeof(DATA16)); */
+
+/*     dp += new_im->stride; */
+/*     sp += old_im->stride; */
+/*      } */
+
+/*    if (old_im->flags.have_alpha) */
+/*      { */
+/*     DATA8 *dp, *sp; */
+
+/*     dp = new_im->alpha; */
+/*     sp = old_im->alpha; */
+/*     for (i = 0; i < ch; i++) */
+/*       { */
+/*          memcpy(dp, sp, cw * sizeof(DATA8)); */
+/*          if (ew > 0) memset(dp, 0, ew * sizeof(DATA8)); */
+
+/*          dp += new_im->stride; */
+/*          sp += old_im->stride; */
+/*       } */
+/*      } */
+
+/*    evas_cache_image_drop(&old_im->cache_entry); */
+/*    return new_im; */
+/* } */
diff --git a/src/lib/engines/common_8/evas_soft8_polygon.c b/src/lib/engines/common_8/evas_soft8_polygon.c
new file mode 100644 (file)
index 0000000..e4d7766
--- /dev/null
@@ -0,0 +1,230 @@
+#include <evas_common_soft8.h>
+#include "evas_soft8_scanline_fill.c"
+#include <math.h>
+
+typedef struct _RGBA_Edge RGBA_Edge;
+typedef struct _RGBA_Vertex RGBA_Vertex;
+
+struct _RGBA_Edge {
+   float x, dx;
+   int i;
+};
+
+struct _RGBA_Vertex {
+   float x, y;
+   int i;
+};
+
+#define POLY_EDGE_DEL(_i)                                               \
+{                                                                       \
+   int _j;                                                              \
+                                                                        \
+   for (_j = 0; (_j < num_active_edges) && (edges[_j].i != _i); _j++);  \
+   if (_j < num_active_edges)                                           \
+     {                                                                  \
+       num_active_edges--;                                             \
+       memmove(&(edges[_j]), &(edges[_j + 1]),                         \
+               (num_active_edges - _j) * sizeof(RGBA_Edge));           \
+     }                                                                  \
+}
+
+#define POLY_EDGE_ADD(_i, _y)                                           \
+{                                                                       \
+   int _j;                                                              \
+   float _dx;                                                           \
+   RGBA_Vertex *_p, *_q;                                                \
+   if (_i < (n - 1)) _j = _i + 1;                                       \
+   else _j = 0;                                                         \
+   if (point[_i].y < point[_j].y)                                       \
+     {                                                                  \
+       _p = &(point[_i]);                                              \
+       _q = &(point[_j]);                                              \
+     }                                                                  \
+   else                                                                 \
+     {                                                                  \
+       _p = &(point[_j]);                                              \
+       _q = &(point[_i]);                                              \
+     }                                                                  \
+   edges[num_active_edges].dx = _dx = (_q->x - _p->x) / (_q->y - _p->y); \
+   edges[num_active_edges].x = (_dx * ((float)_y + 0.5 - _p->y)) + _p->x; \
+   edges[num_active_edges].i = _i;                                      \
+   num_active_edges++;                                                  \
+}
+
+static int
+polygon_point_sorter(const void *a, const void *b)
+{
+   RGBA_Vertex *p, *q;
+
+   p = (RGBA_Vertex *) a;
+   q = (RGBA_Vertex *) b;
+   if (p->y <= q->y)
+      return -1;
+   return 1;
+}
+
+static int
+polygon_edge_sorter(const void *a, const void *b)
+{
+   RGBA_Edge *p, *q;
+
+   p = (RGBA_Edge *) a;
+   q = (RGBA_Edge *) b;
+   if (p->x <= q->x)
+      return -1;
+   return 1;
+}
+
+void
+soft8_polygon_draw(Soft8_Image * dst, RGBA_Draw_Context * dc,
+                   RGBA_Polygon_Point * points, int x, int y)
+{
+   RGBA_Polygon_Point *pt;
+   RGBA_Vertex *point;
+   RGBA_Edge *edges;
+   int num_active_edges;
+   int n;
+   int i, j, k;
+   int y0, y1, yi;
+   int ext_x, ext_y, ext_w, ext_h;
+   int *sorted_index;
+   DATA8 alpha;
+   DATA8 gry8;
+
+   alpha = A_VAL(&dc->col.col);
+   if (alpha == 0)
+      return;
+   alpha++;
+
+   gry8 = GRY_8_FROM_RGB(&dc->col.col);
+
+   ext_x = 0;
+   ext_y = 0;
+   ext_w = dst->cache_entry.w;
+   ext_h = dst->cache_entry.h;
+   if (dc->clip.use)
+      RECTS_CLIP_TO_RECT(ext_x, ext_y, ext_w, ext_h,
+                         dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
+
+   if ((ext_w <= 0) || (ext_h <= 0))
+      return;
+
+   n = 0;
+   EINA_INLIST_FOREACH(points, pt) n++;
+
+   if (n < 3)
+      return;
+
+   edges = malloc(sizeof(RGBA_Edge) * n);
+   if (!edges)
+      return;
+
+   point = malloc(sizeof(RGBA_Vertex) * n);
+   if (!point)
+     {
+        free(edges);
+        return;
+     }
+
+   sorted_index = malloc(sizeof(int) * n);
+   if (!sorted_index)
+     {
+        free(edges);
+        free(point);
+        return;
+     }
+
+   k = 0;
+   EINA_INLIST_FOREACH(points, pt)
+   {
+      point[k].x = pt->x + x;
+      point[k].y = pt->y + y;
+      point[k].i = k;
+      k++;
+   }
+   qsort(point, n, sizeof(RGBA_Vertex), polygon_point_sorter);
+
+   for (k = 0; k < n; k++)
+      sorted_index[k] = point[k].i;
+
+   k = 0;
+   EINA_INLIST_FOREACH(points, pt)
+   {
+      point[k].x = pt->x + x;
+      point[k].y = pt->y + y;
+      point[k].i = k;
+      k++;
+   }
+
+   y0 = MAX(ext_y, ceil(point[sorted_index[0]].y - 0.5));
+   y1 = MIN(ext_y + ext_h - 1, floor(point[sorted_index[n - 1]].y - 0.5));
+
+   k = 0;
+   num_active_edges = 0;
+
+   for (yi = y0; yi <= y1; yi++)
+     {
+        for (; (k < n) && (point[sorted_index[k]].y <= ((float)yi + 0.5)); k++)
+          {
+             i = sorted_index[k];
+
+             if (i > 0)
+                j = i - 1;
+             else
+                j = n - 1;
+             if (point[j].y <= ((float)yi - 0.5))
+               {
+               POLY_EDGE_DEL(j)}
+             else if (point[j].y > ((float)yi + 0.5))
+               {
+               POLY_EDGE_ADD(j, yi)}
+             if (i < (n - 1))
+                j = i + 1;
+             else
+                j = 0;
+             if (point[j].y <= ((float)yi - 0.5))
+               {
+               POLY_EDGE_DEL(i)}
+             else if (point[j].y > ((float)yi + 0.5))
+               {
+               POLY_EDGE_ADD(i, yi)}
+          }
+
+        qsort(edges, num_active_edges, sizeof(RGBA_Edge), polygon_edge_sorter);
+
+        for (j = 0; j < num_active_edges; j += 2)
+          {
+             int x0, x1;
+
+             x0 = ceil(edges[j].x - 0.5);
+             if (j < (num_active_edges - 1))
+                x1 = floor(edges[j + 1].x - 0.5);
+             else
+                x1 = x0;
+             if ((x1 >= ext_x) && (x0 < (ext_x + ext_w)) && (x0 <= x1))
+               {
+                  DATA8 *dst_itr;
+                  int w;
+
+                  if (x0 < ext_x)
+                     x0 = ext_x;
+                  if (x1 >= (ext_x + ext_w))
+                     x1 = ext_x + ext_w - 1;
+
+                  w = (x1 - x0) + 1;
+                  dst_itr = dst->pixels + (yi * dst->stride) + x0;
+
+                  if (alpha == 0xff)
+                     _soft8_scanline_fill_solid_solid(dst_itr, w, gry8);
+                  else
+                     _soft8_scanline_fill_transp_solid(dst_itr, w, gry8, alpha);
+               }
+             edges[j].x += edges[j].dx;
+             edges[j + 1].x += edges[j + 1].dx;
+          }
+     }
+
+   free(edges);
+   free(point);
+   free(sorted_index);
+}
diff --git a/src/lib/engines/common_8/evas_soft8_rectangle.c b/src/lib/engines/common_8/evas_soft8_rectangle.c
new file mode 100644 (file)
index 0000000..20c48e2
--- /dev/null
@@ -0,0 +1,125 @@
+#include "evas_common_soft8.h"
+#include "evas_soft8_scanline_fill.c"
+
+static inline int
+_is_empty_rectangle(const Eina_Rectangle * r)
+{
+   return (r->w < 1) || (r->h < 1);
+}
+
+static inline void
+_soft8_rectangle_draw_solid_solid(Soft8_Image * dst, int offset, int w, int h,
+                                  DATA8 gry8)
+{
+   DATA8 *dst_itr;
+   int i;
+
+   dst_itr = dst->pixels + offset;
+
+   for (i = 0; i < h; i++, dst_itr += dst->stride)
+      _soft8_scanline_fill_solid_solid(dst_itr, w, gry8);
+}
+
+static inline void
+_soft8_rectangle_draw_transp_solid(Soft8_Image * dst, int offset, int w, int h,
+                                   DATA8 gry8, DATA8 alpha)
+{
+   DATA8 *dst_itr;
+   int i;
+
+   dst_itr = dst->pixels + offset;
+   alpha++;
+
+   for (i = 0; i < h; i++, dst_itr += dst->stride)
+      _soft8_scanline_fill_transp_solid(dst_itr, w, gry8, alpha);
+}
+
+static void
+_soft8_rectangle_draw_int(Soft8_Image * dst, RGBA_Draw_Context * dc,
+                          Eina_Rectangle dr)
+{
+   int dst_offset;
+
+   if (_is_empty_rectangle(&dr))
+      return;
+   RECTS_CLIP_TO_RECT(dr.x, dr.y, dr.w, dr.h, 0, 0, dst->cache_entry.w,
+                      dst->cache_entry.h);
+   if (_is_empty_rectangle(&dr))
+      return;
+
+   if (dc->clip.use)
+      RECTS_CLIP_TO_RECT(dr.x, dr.y, dr.w, dr.h, dc->clip.x,
+                         dc->clip.y, dc->clip.w, dc->clip.h);
+   if (_is_empty_rectangle(&dr))
+      return;
+   if (A_VAL(&dc->col.col) == 0)
+      return;
+
+   dst_offset = dr.x + (dr.y * dst->stride);
+
+   if (!dst->cache_entry.flags.alpha)
+     {
+        DATA8 gry8;
+        DATA8 alpha;
+
+        alpha = A_VAL(&dc->col.col);
+        gry8 = GRY_8_FROM_RGB(&dc->col.col);
+
+        if (alpha == 0xff)
+           _soft8_rectangle_draw_solid_solid(dst, dst_offset, dr.w, dr.h, gry8);
+        else if (alpha > 0)
+           _soft8_rectangle_draw_transp_solid
+               (dst, dst_offset, dr.w, dr.h, gry8, alpha);
+     }
+   else
+      ERR("Unsupported feature: drawing rectangle to non-opaque destination.");
+}
+
+void
+soft8_rectangle_draw(Soft8_Image * dst, RGBA_Draw_Context * dc,
+                     int x, int y, int w, int h)
+{
+   Eina_Rectangle dr;
+   Cutout_Rects *rects;
+   Cutout_Rect *r;
+   struct RGBA_Draw_Context_clip c_bkp;
+   int i;
+
+   /* handle cutouts here! */
+   EINA_RECTANGLE_SET(&dr, x, y, w, h);
+
+   if (_is_empty_rectangle(&dr))
+      return;
+   if (!
+       (RECTS_INTERSECT
+        (dr.x, dr.y, dr.w, dr.h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
+      return;
+
+   /* no cutouts - cut right to the chase */
+   if (!dc->cutout.rects)
+     {
+        _soft8_rectangle_draw_int(dst, dc, dr);
+        return;
+     }
+
+   c_bkp = dc->clip;
+
+   evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w,
+                                      dst->cache_entry.h);
+   evas_common_draw_context_clip_clip(dc, x, y, w, h);
+   /* our clip is 0 size.. abort */
+   if ((dc->clip.w <= 0) || (dc->clip.h <= 0))
+     {
+        dc->clip = c_bkp;
+        return;
+     }
+   rects = evas_common_draw_context_apply_cutouts(dc);
+   for (i = 0; i < rects->active; ++i)
+     {
+        r = rects->rects + i;
+        evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
+        _soft8_rectangle_draw_int(dst, dc, dr);
+     }
+   evas_common_draw_context_apply_clear_cutouts(rects);
+   dc->clip = c_bkp;
+}
diff --git a/src/lib/engines/common_8/evas_soft8_scanline_blend.c b/src/lib/engines/common_8/evas_soft8_scanline_blend.c
new file mode 100644 (file)
index 0000000..ee4427a
--- /dev/null
@@ -0,0 +1,447 @@
+/** NOTE: This file is meant to be included by users **/
+
+/** NOTE2: r, g, b parameters are 16bits, so you can pass 0 to 256 inclusive.
+ **        this is due our division by 256 when multiplying the color.
+ **/
+
+/*****************************************************************************
+ * Scanline processing
+ *
+ *    _soft8_scanline_<description>_<src>_<dst>[_<modifier>]()
+ *
+ ****************************************************************************/
+
+static always_inline void
+_soft8_pt_blend_transp_solid(DATA8 * p_dst, DATA8 src, DATA8 alpha)
+{
+   if (alpha == 0xff)
+      *p_dst = src;
+   else if (alpha != 0)
+     {
+        *p_dst = GRY_8_BLEND(src, *p_dst, alpha);
+     }
+}
+
+/***********************************************************************
+ * Regular blend operations
+ */
+static void
+_soft8_scanline_blend_transp_solid(DATA8 * src, DATA8 * alpha, DATA8 * dst,
+                                   int size)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   end = start + (size & ~7);
+
+   pld(alpha, 0);
+   pld(src, 0);
+
+   /* work on 8 pixels per time, do data preload */
+   while (start < end)
+     {
+        DATA8 alpha1, alpha2;
+
+        alpha1 = alpha[0];
+        alpha += 8;
+
+        /* empirical tests show these give the best performance */
+        pld(alpha, 8);
+        pld(src, 32);
+
+        src += 8;
+        start += 8;
+
+        alpha2 = alpha[-7];
+        _soft8_pt_blend_transp_solid(start - 8, src[-8], alpha1);
+
+        alpha1 = alpha[-6];
+        _soft8_pt_blend_transp_solid(start - 7, src[-7], alpha2);
+
+        alpha2 = alpha[-5];
+        _soft8_pt_blend_transp_solid(start - 6, src[-6], alpha1);
+
+        alpha1 = alpha[-4];
+        _soft8_pt_blend_transp_solid(start - 5, src[-5], alpha2);
+
+        alpha2 = alpha[-3];
+        _soft8_pt_blend_transp_solid(start - 4, src[-4], alpha1);
+
+        alpha1 = alpha[-2];
+        _soft8_pt_blend_transp_solid(start - 3, src[-3], alpha2);
+
+        alpha2 = alpha[-1];
+        _soft8_pt_blend_transp_solid(start - 2, src[-2], alpha1);
+
+        _soft8_pt_blend_transp_solid(start - 1, src[-1], alpha2);
+     }
+
+   /* remaining pixels (up to 7) */
+   end = start + (size & 7);
+   for (; start < end; start++, src++, alpha++)
+      _soft8_pt_blend_transp_solid(start, *src, *alpha);
+}
+
+static always_inline void
+_soft8_pt_blend_solid_solid(DATA8 * p_dst, DATA8 src)
+{
+   *p_dst = src;
+}
+
+static inline void
+_soft8_scanline_blend_solid_solid(DATA8 * src, DATA8 * dst, int size)
+{
+   memcpy(dst, src, size * sizeof(DATA8));
+}
+
+/***********************************************************************
+ * Blend operations taking an extra alpha (fade in, out)
+ */
+
+static inline void
+_soft8_pt_blend_transp_solid_mul_alpha(DATA8 * p_dst, DATA8 src, DATA8 alpha,
+                                       DATA8 rel_alpha)
+{
+   alpha = alpha * rel_alpha;
+   if (alpha == 0)
+      return;
+
+   alpha++;
+   *p_dst = GRY_8_BLEND((src * rel_alpha) & 0xff, *p_dst, alpha);
+}
+
+static void
+_soft8_scanline_blend_transp_solid_mul_alpha(DATA8 * src, DATA8 * alpha,
+                                             DATA8 * dst, int size,
+                                             const DATA8 rel_alpha)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   end = start + (size & ~7);
+
+   pld(alpha, 0);
+   pld(src, 0);
+
+   while (start < end)
+     {
+        DATA8 alpha1, alpha2;
+
+        alpha1 = alpha[0];
+        alpha += 8;
+
+        pld(alpha, 8);
+        pld(src, 32);
+
+        src += 8;
+        start += 8;
+
+        alpha2 = alpha[-7];
+        _soft8_pt_blend_transp_solid_mul_alpha
+            (start - 8, src[-8], alpha1, rel_alpha);
+
+        alpha1 = alpha[-6];
+        _soft8_pt_blend_transp_solid_mul_alpha
+            (start - 7, src[-7], alpha2, rel_alpha);
+
+        alpha2 = alpha[-5];
+        _soft8_pt_blend_transp_solid_mul_alpha
+            (start - 6, src[-6], alpha1, rel_alpha);
+
+        alpha1 = alpha[-4];
+        _soft8_pt_blend_transp_solid_mul_alpha
+            (start - 5, src[-5], alpha2, rel_alpha);
+
+        alpha2 = alpha[-3];
+        _soft8_pt_blend_transp_solid_mul_alpha
+            (start - 4, src[-4], alpha1, rel_alpha);
+
+        alpha1 = alpha[-2];
+        _soft8_pt_blend_transp_solid_mul_alpha
+            (start - 3, src[-3], alpha2, rel_alpha);
+
+        alpha2 = alpha[-1];
+        _soft8_pt_blend_transp_solid_mul_alpha
+            (start - 2, src[-2], alpha1, rel_alpha);
+
+        _soft8_pt_blend_transp_solid_mul_alpha
+            (start - 1, src[-1], alpha2, rel_alpha);
+     }
+
+   end = start + (size & 7);
+   for (; start < end; start++, src++, alpha++)
+      _soft8_pt_blend_transp_solid_mul_alpha(start, *src, *alpha, rel_alpha);
+}
+
+static always_inline void
+_soft8_pt_blend_solid_solid_mul_alpha(DATA8 * p_dst, DATA8 src, DATA8 rel_alpha)
+{
+   *p_dst = GRY_8_BLEND_UNMUL(src, *p_dst, rel_alpha);
+}
+
+static void
+_soft8_scanline_blend_solid_solid_mul_alpha(DATA8 * src, DATA8 * dst, int size,
+                                            DATA8 rel_alpha)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   end = start + (size & ~7);
+
+   pld(src, 0);
+
+   while (start < end)
+     {
+        pld(src, 32);
+        UNROLL8(
+                  {
+                  _soft8_pt_blend_solid_solid_mul_alpha(start, *src, rel_alpha);
+                  start++; src++;}
+        );
+     }
+
+   end = start + (size & 7);
+   for (; start < end; start++, src++)
+      _soft8_pt_blend_solid_solid_mul_alpha(start, *src, rel_alpha);
+}
+
+/***********************************************************************
+ * Blend operations with extra alpha and multiply color
+ */
+
+static always_inline void
+_soft8_pt_blend_transp_solid_mul_color_transp(DATA8 * p_dst, DATA8 src,
+                                              DATA8 alpha, DATA8 rel_alpha,
+                                              DATA8 r, DATA8 g, DATA8 b)
+{
+   alpha = alpha * rel_alpha;
+   if (alpha == 0)
+      return;
+
+   alpha++;
+
+   DATA8 gry8 = (src * GRY_8_FROM_COMPONENTS(r, g, b)) >> 8;
+   *p_dst = GRY_8_BLEND(gry8, *p_dst, alpha);
+}
+
+static void
+_soft8_scanline_blend_transp_solid_mul_color_transp(DATA8 * src, DATA8 * alpha,
+                                                    DATA8 * dst, int size,
+                                                    DATA8 rel_alpha, DATA8 r,
+                                                    DATA8 g, DATA8 b)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   end = start + (size & ~7);
+
+   pld(alpha, 0);
+   pld(src, 0);
+
+   while (start < end)
+     {
+        DATA8 alpha1, alpha2;
+
+        alpha1 = alpha[0];
+        alpha += 8;
+
+        pld(src, 32);
+        pld(start, 32);
+
+        src += 8;
+        start += 8;
+
+        alpha2 = alpha[-7];
+        _soft8_pt_blend_transp_solid_mul_color_transp
+            (start - 8, src[-8], alpha1, rel_alpha, r, g, b);
+
+        alpha1 = alpha[-6];
+        _soft8_pt_blend_transp_solid_mul_color_transp
+            (start - 7, src[-7], alpha2, rel_alpha, r, g, b);
+
+        alpha2 = alpha[-5];
+        _soft8_pt_blend_transp_solid_mul_color_transp
+            (start - 6, src[-6], alpha1, rel_alpha, r, g, b);
+
+        alpha1 = alpha[-4];
+        _soft8_pt_blend_transp_solid_mul_color_transp
+            (start - 5, src[-5], alpha2, rel_alpha, r, g, b);
+
+        alpha2 = alpha[-3];
+        _soft8_pt_blend_transp_solid_mul_color_transp
+            (start - 4, src[-4], alpha1, rel_alpha, r, g, b);
+
+        alpha1 = alpha[-2];
+        _soft8_pt_blend_transp_solid_mul_color_transp
+            (start - 3, src[-3], alpha2, rel_alpha, r, g, b);
+
+        alpha2 = alpha[-1];
+        _soft8_pt_blend_transp_solid_mul_color_transp
+            (start - 2, src[-2], alpha1, rel_alpha, r, g, b);
+
+        _soft8_pt_blend_transp_solid_mul_color_transp
+            (start - 1, src[-1], alpha2, rel_alpha, r, g, b);
+     }
+
+   end = start + (size & 7);
+   for (; start < end; start++, src++, alpha++)
+      _soft8_pt_blend_transp_solid_mul_color_transp
+          (start, *src, *alpha, rel_alpha, r, g, b);
+}
+
+static always_inline void
+_soft8_pt_blend_solid_solid_mul_color_transp(DATA8 * p_dst, DATA8 src,
+                                             DATA8 rel_alpha, DATA8 r, DATA8 g,
+                                             DATA8 b)
+{
+   DATA8 gry8 = (src * GRY_8_FROM_COMPONENTS(r, g, b)) >> 8;
+   *p_dst = GRY_8_BLEND(gry8, *p_dst, rel_alpha);
+}
+
+static void
+_soft8_scanline_blend_solid_solid_mul_color_transp(DATA8 * src, DATA8 * dst,
+                                                   int size, DATA8 rel_alpha,
+                                                   DATA8 r, DATA8 g, DATA8 b)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   end = start + (size & ~7);
+
+   pld(src, 0);
+
+   while (start < end)
+     {
+        pld(src, 32);
+        UNROLL8(
+                  {
+                  _soft8_pt_blend_solid_solid_mul_color_transp
+                  (start, *src, rel_alpha, r, g, b); start++; src++;}
+        );
+     }
+
+   end = start + (size & 7);
+   for (; start < end; start++, src++)
+      _soft8_pt_blend_solid_solid_mul_color_transp
+          (start, *src, rel_alpha, r, g, b);
+}
+
+/***********************************************************************
+ * Blend operations with extra multiply color
+ */
+static always_inline void
+_soft8_pt_blend_transp_solid_mul_color_solid(DATA8 * p_dst, DATA8 src,
+                                             DATA8 alpha, DATA8 r, DATA8 g,
+                                             DATA8 b)
+{
+   if (alpha == 0)
+      return;
+
+   DATA8 gry8 = (src * GRY_8_FROM_COMPONENTS(r, g, b)) >> 8;
+
+   if (alpha == 0xff)
+      *p_dst = gry8;
+   else
+     {
+        *p_dst = GRY_8_BLEND(gry8, *p_dst, alpha);
+     }
+}
+
+static void
+_soft8_scanline_blend_transp_solid_mul_color_solid(DATA8 * src, DATA8 * alpha,
+                                                   DATA8 * dst, int size,
+                                                   DATA8 r, DATA8 g, DATA8 b)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   end = start + (size & ~7);
+
+   pld(alpha, 0);
+   pld(src, 0);
+
+   while (start < end)
+     {
+        DATA8 alpha1, alpha2;
+
+        alpha1 = alpha[0];
+        alpha += 8;
+
+        pld(alpha, 8);
+        pld(src, 32);
+
+        src += 8;
+        start += 8;
+
+        alpha2 = alpha[-7];
+        _soft8_pt_blend_transp_solid_mul_color_solid
+            (start - 8, src[-8], alpha1, r, g, b);
+
+        alpha1 = alpha[-6];
+        _soft8_pt_blend_transp_solid_mul_color_solid
+            (start - 7, src[-7], alpha2, r, g, b);
+
+        alpha2 = alpha[-5];
+        _soft8_pt_blend_transp_solid_mul_color_solid
+            (start - 6, src[-6], alpha1, r, g, b);
+
+        alpha1 = alpha[-4];
+        _soft8_pt_blend_transp_solid_mul_color_solid
+            (start - 5, src[-5], alpha2, r, g, b);
+
+        alpha2 = alpha[-3];
+        _soft8_pt_blend_transp_solid_mul_color_solid
+            (start - 4, src[-4], alpha1, r, g, b);
+
+        alpha1 = alpha[-2];
+        _soft8_pt_blend_transp_solid_mul_color_solid
+            (start - 3, src[-3], alpha2, r, g, b);
+
+        alpha2 = alpha[-1];
+        _soft8_pt_blend_transp_solid_mul_color_solid
+            (start - 2, src[-2], alpha1, r, g, b);
+
+        _soft8_pt_blend_transp_solid_mul_color_solid
+            (start - 1, src[-1], alpha2, r, g, b);
+     }
+
+   end = start + (size & 7);
+   for (; start < end; start++, src++, alpha++)
+      _soft8_pt_blend_transp_solid_mul_color_solid
+          (start, *src, *alpha, r, g, b);
+}
+
+static always_inline void
+_soft8_pt_blend_solid_solid_mul_color_solid(DATA8 * p_dst, DATA8 src, DATA8 r,
+                                            DATA8 g, DATA8 b)
+{
+   *p_dst = (src * GRY_8_FROM_COMPONENTS(r, g, b)) >> 8;
+}
+
+static void
+_soft8_scanline_blend_solid_solid_mul_color_solid(DATA8 * src, DATA8 * dst,
+                                                  int size, DATA8 r, DATA8 g,
+                                                  DATA8 b)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   end = start + (size & ~7);
+
+   pld(src, 0);
+
+   while (start < end)
+     {
+        pld(src, 32);
+        UNROLL8(
+                  {
+                  _soft8_pt_blend_solid_solid_mul_color_solid(start, *src, r, g,
+                                                              b); start++;
+                  src++;}
+        );
+     }
+
+   end = start + (size & 7);
+   for (; start < end; start++, src++)
+      _soft8_pt_blend_solid_solid_mul_color_solid(start, *src, r, g, b);
+}
diff --git a/src/lib/engines/common_8/evas_soft8_scanline_fill.c b/src/lib/engines/common_8/evas_soft8_scanline_fill.c
new file mode 100644 (file)
index 0000000..0d2f18b
--- /dev/null
@@ -0,0 +1,53 @@
+/** NOTE: This file is meant to be included by users **/
+
+/*****************************************************************************
+ * Point processing
+ *
+ *    _soft8_pt_<description>_<src>_<dst>[_<modifier>]()
+ *
+ * Scanline processing
+ *
+ *    _soft8_scanline_<description>_<src>_<dst>[_<modifier>]()
+ *
+ ****************************************************************************/
+static always_inline void
+_soft8_pt_fill_solid_solid(DATA8 * dst, DATA8 gry8)
+{
+   *dst = gry8;
+}
+
+static always_inline void
+_soft8_scanline_fill_solid_solid(DATA8 * dst, int size, DATA8 gry8)
+{
+   memset(dst, gry8, size);
+}
+
+static always_inline void
+_soft8_pt_fill_transp_solid(DATA8 * dst, DATA8 gry8, DATA8 alpha)
+{
+   *dst = GRY_8_BLEND(gry8, *dst, alpha);
+}
+
+static void
+_soft8_scanline_fill_transp_solid(DATA8 * dst, int size, DATA8 gry8,
+                                  DATA8 alpha)
+{
+   DATA8 *start, *end;
+
+   start = dst;
+   pld(start, 0);
+   end = start + (size & ~7);
+
+   while (start < end)
+     {
+        pld(start, 32);
+        UNROLL8(
+                  {
+                  _soft8_pt_fill_transp_solid(start, gry8, alpha); start++;}
+        );
+     }
+
+   end = start + (size & 7);
+   for (; start < end; start++)
+      _soft8_pt_fill_transp_solid(start, gry8, alpha);
+}
index 9d8cfbc..22c9313 100644 (file)
@@ -105,6 +105,8 @@ EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_ddraw);
 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_sdl);
 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_wince);
 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_x11);
+EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_8);
+EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_8_x11);
 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_ddraw);
 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_gdi);
 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_generic);
@@ -176,6 +178,12 @@ static const struct {
 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_GDI
   EVAS_EINA_STATIC_MODULE_USE(engine, software_gdi),
 #endif
+#ifdef EVAS_STATIC_BUILD_SOFTWARE_8
+  EVAS_EINA_STATIC_MODULE_USE(engine, software_8),
+#endif
+#ifdef EVAS_STATIC_BUILD_SOFTWARE_8_X11
+  EVAS_EINA_STATIC_MODULE_USE(engine, software_8_x11),
+#endif
 #ifdef EVAS_STATIC_BUILD_SOFTWARE_GENERIC
   EVAS_EINA_STATIC_MODULE_USE(engine, software_generic),
 #endif
@@ -466,10 +474,9 @@ evas_module_clean(void)
    if (noclean == -1)
      {
        if (getenv("EVAS_NOCLEAN"))
-         {
-            noclean = 1;
-         }
-       noclean = 0;
+          noclean = 1;
+       else 
+          noclean = 0;
      }
    if (noclean == 1) return;
 
index ee07371..23aa788 100644 (file)
@@ -145,7 +145,7 @@ evas_imaging_font_load(const char *file, const char *key, int size)
        font = evas_common_font_hinting_load((char *)file, size, _evas_hinting);
      }
    if (!font) return NULL;
-   fn = calloc(1, sizeof(RGBA_Font));
+   fn = calloc(1, sizeof(Evas_Imaging_Font));
    if (!fn) return NULL;
    fn->font = font;
    return fn;
@@ -197,36 +197,94 @@ evas_imaging_font_line_advance_get(const Evas_Imaging_Font *fn)
 EAPI void
 evas_imaging_font_string_advance_get(const Evas_Imaging_Font *fn, const char *str, int *x, int *y)
 {
+   Evas_BiDi_Props bidi_props;
+   Evas_BiDi_Paragraph_Props bidi_par_props;
+   bidi_props.props = &bidi_par_props;
+   Eina_Unicode *ustr;
    if (!fn) return;
-   evas_common_font_query_advance(fn->font, str, x, y);
+   ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
+#ifdef BIDI_SUPPORT
+   evas_bidi_update_props(ustr, &bidi_par_props);
+#endif
+   evas_common_font_query_advance(fn->font, ustr, &bidi_props, x, y);
+#ifdef BIDI_SUPPORT
+   evas_bidi_props_clean(&bidi_props);
+#endif
+   if (ustr) free(ustr);
 }
 
 EAPI void
 evas_imaging_font_string_size_query(const Evas_Imaging_Font *fn, const char *str, int *w, int *h)
 {
+   Evas_BiDi_Props intl_props;
+   Evas_BiDi_Paragraph_Props bidi_paragraph_props;
+   intl_props.props = &bidi_paragraph_props;
+   Eina_Unicode *ustr;
    if (!fn) return;
-   evas_common_font_query_size(fn->font, str, w, h);
+   ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
+#ifdef BIDI_SUPPORT
+   evas_bidi_update_props(ustr, &bidi_paragraph_props);
+#endif
+   evas_common_font_query_size(fn->font, ustr, &intl_props, w, h);
+#ifdef BIDI_SUPPORT
+   evas_bidi_props_clean(&intl_props);
+#endif
+   if (ustr) free(ustr);
 }
 
 EAPI int
 evas_imaging_font_string_inset_get(const Evas_Imaging_Font *fn, const char *str)
 {
+   Eina_Unicode *ustr;
+   int ret;
+   
    if (!fn) return 0;
-   return evas_common_font_query_inset(fn->font, str);
+   ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
+   ret = evas_common_font_query_inset(fn->font, ustr);
+   if (ustr) free(ustr);
+   return ret;
 }
 
 EAPI int
 evas_imaging_font_string_char_coords_get(const Evas_Imaging_Font *fn, const char *str, int pos, int *cx, int *cy, int *cw, int *ch)
 {
+   int ret;
+   Evas_BiDi_Props intl_props;
+   Evas_BiDi_Paragraph_Props bidi_paragraph_props;
+   intl_props.props = &bidi_paragraph_props;
+   Eina_Unicode *ustr;
    if (!fn) return 0;
-   return evas_common_font_query_char_coords(fn->font, str, pos, cx, cy, cw, ch);
+   ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
+#ifdef BIDI_SUPPORT
+   evas_bidi_update_props(ustr, &bidi_paragraph_props);
+#endif
+   ret = evas_common_font_query_char_coords(fn->font, ustr, &intl_props, pos, cx, cy, cw, ch);
+#ifdef BIDI_SUPPORT
+   evas_bidi_props_clean(&intl_props);
+#endif
+   if (ustr) free(ustr);
+   return ret;
 }
 
 EAPI int
 evas_imaging_font_string_char_at_coords_get(const Evas_Imaging_Font *fn, const char *str, int x, int y, int *cx, int *cy, int *cw, int *ch)
 {
+   int ret;
+   Evas_BiDi_Props intl_props;
+   Evas_BiDi_Paragraph_Props bidi_paragraph_props;
+   intl_props.props = &bidi_paragraph_props;
+   Eina_Unicode *ustr;
    if (!fn) return -1;
-   return evas_common_font_query_text_at_pos(fn->font, str, x, y, cx, cy, cw, ch);
+   ustr = evas_common_encoding_utf8_to_unicode(str, NULL);
+#ifdef BIDI_SUPPORT
+   evas_bidi_update_props(ustr, &bidi_paragraph_props);
+#endif
+   ret = evas_common_font_query_char_at_coords(fn->font, ustr, &intl_props, x, y, cx, cy, cw, ch);
+#ifdef BIDI_SUPPORT
+   evas_bidi_props_clean(&intl_props);
+#endif
+   if (ustr) free(ustr);
+   return ret;
 }
 
 EAPI void
index 1570bf4..5c986c2 100644 (file)
@@ -8,5 +8,6 @@ evas_options.h \
 evas_macros.h \
 evas_mmx.h \
 evas_common.h \
+evas_common_soft8.h \
 evas_common_soft16.h \
 evas_blend_ops.h
index aad5161..cdc5e96 100644 (file)
@@ -23,7 +23,6 @@ typedef struct _Evas_Cairo_Context                   Evas_Cairo_Context;
 typedef struct _Evas_Cairo_Image                     Evas_Cairo_Image;
 typedef struct _Evas_Cairo_Polygon                   Evas_Cairo_Polygon;
 typedef struct _Evas_Cairo_Polygon_Point             Evas_Cairo_Polygon_Point;
-typedef struct _Evas_Cairo_Gradient                  Evas_Cairo_Gradient;
 
 struct _Evas_Cairo_Context
 {
@@ -114,11 +113,6 @@ struct _Evas_Cairo_Polygon_Point
 {
    int x, y;
 };
-
-struct _Evas_Cairo_Gradient
-{
-   RGBA_Gradient   *grad;
-};
 #endif
 
 /*
@@ -150,16 +144,12 @@ void              evas_gl_common_image_dirty(Evas_GL_Image *im);
 Evas_GL_Polygon  *evas_gl_common_poly_point_add(Evas_GL_Polygon *poly, int x, int y);
 Evas_GL_Polygon  *evas_gl_common_poly_points_clear(Evas_GL_Polygon *poly);
 
-Evas_GL_Gradient *evas_gl_common_gradient_color_add(Evas_GL_Gradient *gr, int r, int g, int b, int a, int distance);
-Evas_GL_Gradient *evas_gl_common_gradient_colors_clear(Evas_GL_Gradient *gr);
-
 void              evas_gl_common_swap_rect(Evas_GL_Context *gc, int x, int y, int w, int h);
 
 void              evas_gl_common_rect_draw(Evas_GL_Context *gc, RGBA_Draw_Context *dc, int x, int y, int w, int h);
 void              evas_gl_common_image_draw(Evas_GL_Context *gc, RGBA_Draw_Context *dc, 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_common_line_draw(Evas_GL_Context *gc, RGBA_Draw_Context *dc, int x1, int y1, int x2, int y2);
 void              evas_gl_common_poly_draw(Evas_GL_Context *gc, RGBA_Draw_Context *dc, Evas_GL_Polygon *poly);
-void              evas_gl_common_gradient_draw(Evas_GL_Context *gc, RGBA_Draw_Context *dc, Evas_GL_Gradient *gr, int x, int y, int w, int h, double angle);
 
 Evas_GL_Font_Texture *evas_gl_font_texture_new(Evas_GL_Context *gc, RGBA_Font_Glyph *fg);
 void                  evas_gl_font_texture_free(Evas_GL_Font_Texture *ft);
index d2669ca..b6fd5c1 100644 (file)
@@ -1,7 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-
 #ifndef EVAS_COMMON_H
 #define EVAS_COMMON_H
 
@@ -53,7 +49,9 @@ 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"
 
@@ -250,18 +248,20 @@ void *alloca (size_t);
 # define DM_BITS      4
 # define DM_DIV       16
 # define USE_DITHER_44 1
-# define DM_MSK       (DM_SIZE - 1)
-# define DM_SHF(_b)   (DM_BITS - (8 - _b))
 #else
 # define DM_TABLE     _evas_dither_128128
 # define DM_SIZE      128
 # define DM_BITS      6
 # define DM_DIV       64
 # define USE_DITHER_128128 1
-# define DM_MSK       (DM_SIZE - 1)
-# define DM_SHF(_b)   (DM_BITS - (8 - _b))
 #endif
 
+#define DM_MSK       (DM_SIZE - 1)
+#define DM_SHF(_b)   (DM_BITS - (8 - _b))
+/* Supports negative right shifts */
+#define DM_SHR(x, _b)   ((DM_SHF(_b) >= 0) ? \
+      ((x) >> DM_SHF(_b)) : ((x) << -DM_SHF(_b)))
+
 /* if more than 1/ALPHA_SPARSE_INV_FRACTION is "alpha" (1-254) then sparse
  * alpha flag gets set */
 #define ALPHA_SPARSE_INV_FRACTION 3
@@ -379,13 +379,6 @@ typedef struct _RGBA_Pipe_Thread_Info RGBA_Pipe_Thread_Info;
 typedef struct _RGBA_Image            RGBA_Image;
 typedef struct _RGBA_Image_Span       RGBA_Image_Span;
 typedef struct _RGBA_Draw_Context     RGBA_Draw_Context;
-typedef struct _RGBA_Gradient         RGBA_Gradient;
-typedef struct _RGBA_Gradient_Color_Stop   RGBA_Gradient_Color_Stop;
-typedef struct _RGBA_Gradient_Alpha_Stop   RGBA_Gradient_Alpha_Stop;
-typedef struct _RGBA_Gradient_Type    RGBA_Gradient_Type;
-typedef struct _RGBA_Gradient2         RGBA_Gradient2;
-typedef struct _RGBA_Gradient2_Type    RGBA_Gradient2_Type;
-typedef struct _RGBA_Gradient2_Color_Np_Stop   RGBA_Gradient2_Color_Np_Stop;
 typedef struct _RGBA_Polygon_Point    RGBA_Polygon_Point;
 typedef struct _RGBA_Map_Point        RGBA_Map_Point;
 typedef struct _RGBA_Font             RGBA_Font;
@@ -427,16 +420,6 @@ typedef void (*Gfx_Func_Copy)    (DATA32 *src, DATA32 *dst, int len);
 
 typedef void (*Gfx_Func_Convert) (DATA32 *src, DATA8 *dst, int src_jump, int dst_jump, int w, int h, int dith_x, int dith_y, DATA8 *pal);
 
-typedef void (*Gfx_Func_Gradient_Fill)(DATA32 *src, int src_len,
-                                         DATA32 *dst, DATA8 *mask, int len,
-                                         int x, int y, int axx, int axy, int ayx, int ayy,
-                                         void *geom_data);
-
-typedef void (*Gfx_Func_Gradient2_Fill)(DATA32 *src, int src_len,
-                                         DATA32 *dst, DATA8 *mask, int len,
-                                         int x, int y,
-                                         void *geom_data);
-
 #include "../cache/evas_cache.h"
 
 /*****************************************************************************/
@@ -551,6 +534,16 @@ struct _Image_Entry
    LK(lock_references);   // needed for accessing references
 #endif
 
+#ifdef BUILD_PIPE_RENDER
+   RGBA_Pipe           *pipe;
+#ifdef EVAS_FRAME_QUEUING
+   LK(ref_fq_add);
+   LK(ref_fq_del);
+   pthread_cond_t cond_fq_del;
+   int ref_fq[2];              // ref_fq[0] is for addition, ref_fq[1] is for deletion
+#endif
+#endif
+
    unsigned char          scale;
 
    RGBA_Image_Loadopts    load_opts;
@@ -660,6 +653,7 @@ struct _RGBA_Draw_Context
 
 #ifdef BUILD_PIPE_RENDER
 #include "../engines/common/evas_map_image.h"
+#include "../engines/common/evas_bidi_utils.h"
 
 struct _RGBA_Pipe_Op
 {
@@ -678,17 +672,10 @@ struct _RGBA_Pipe_Op
         RGBA_Polygon_Point *points;
       } poly;
       struct {
-        RGBA_Gradient      *grad;
-        int                 x, y, w, h;
-      } grad;
-      struct {
-        RGBA_Gradient2      *grad;
-        int                 x, y, w, h;
-      } grad2;
-      struct {
         RGBA_Font          *font;
         int                 x, y;
-        char               *text;
+        Eina_Unicode       *text;
+         const Evas_BiDi_Props    *intl_props;
       } text;
       struct {
         RGBA_Image         *src;
@@ -736,15 +723,6 @@ struct _RGBA_Image
      } info;
 
    void                *extended_info;
-#ifdef BUILD_PIPE_RENDER
-   RGBA_Pipe           *pipe;
-#ifdef EVAS_FRAME_QUEUING
-   LK(ref_fq_add);
-   LK(ref_fq_del);
-   pthread_cond_t cond_fq_del;
-   int ref_fq[2];              // ref_fq[0] is for addition, ref_fq[1] is for deletion
-#endif
-#endif
    int                  ref;
 
 /*    unsigned char        scale; */
@@ -773,150 +751,6 @@ struct _RGBA_Image
    } cache;
 };
 
-struct _RGBA_Gradient_Color_Stop
-{
-   EINA_INLIST;
-   int               r, g, b, a;
-   int               dist;
-};
-
-struct _RGBA_Gradient_Alpha_Stop
-{
-   EINA_INLIST;
-   int               a;
-   int               dist;
-};
-
-struct _RGBA_Gradient
-{
-   struct
-     {
-       DATA32        *data;
-       int            len;
-       float          angle;
-       int            direction;
-       float          offset;
-       Eina_Bool      has_alpha : 1;
-     } map;
-
-   struct {
-       Eina_Inlist *stops;
-       DATA32           *data;
-       int               nstops;
-       int               len;
-   }  color;
-   struct {
-       Eina_Inlist *stops;
-       DATA8            *data;
-       int               nstops;
-       int               len;
-   }  alpha;
-
-   struct
-     {
-       int            x, y, w, h;
-       int            spread;
-       float          angle;
-     } fill;
-   struct
-     {
-       char          *name;
-       char          *params;
-       RGBA_Gradient_Type *geometer;
-       void          *gdata;
-     } type;
-
-   int references;
-#ifdef EVAS_FRAME_QUEUING
-   LK(ref_fq_add);
-   LK(ref_fq_del);
-   pthread_cond_t cond_fq_del;
-   int ref_fq[2];      //ref_fq[0] is for addition,
-                         //ref_fq[1] is for deletion
-#endif
-
-   Eina_Bool imported_data : 1;
-   Eina_Bool has_alpha : 1;
-};
-
-struct _RGBA_Gradient_Type
-{
-   const char              *name;
-   void                    (*init)(void);
-   void                    (*shutdown)(void);
-   void                    (*geom_init)(RGBA_Gradient *gr);
-   void                    (*geom_set)(RGBA_Gradient *gr);
-   void                    (*geom_free)(void *gdata);
-   int                     (*has_alpha)(RGBA_Gradient *gr, int render_op);
-   int                     (*has_mask)(RGBA_Gradient *gr, int render_op);
-   int                     (*get_map_len)(RGBA_Gradient *gr);
-   Gfx_Func_Gradient_Fill  (*get_fill_func)(RGBA_Gradient *gr, int render_op, unsigned char aa);
-};
-
-struct _RGBA_Gradient2_Color_Np_Stop
-{
-   EINA_INLIST;
-   int               r, g, b, a;
-   float             pos;
-   int               dist;
-};
-
-struct _RGBA_Gradient2
-{
-   struct
-     {
-       DATA32        *data;
-       int            len;
-       Eina_Bool      has_alpha : 1;
-     } map;
-
-   struct {
-       Eina_Inlist *stops;
-       int               nstops;
-       DATA32           *cdata;
-       DATA8            *adata;
-       int               len;
-   }  stops;
-
-   struct
-     {
-       Evas_Common_Transform  transform;
-       int                    spread;
-     } fill;
-   struct
-     {
-        int                 id;
-       RGBA_Gradient2_Type *geometer;
-       void                *gdata;
-     } type;
-
-   int references;
-#ifdef EVAS_FRAME_QUEUING
-   LK(ref_fq_add);
-   LK(ref_fq_del);
-   pthread_cond_t cond_fq_del;
-   int ref_fq[2];      //ref_fq[0] is for addition,
-                         //ref_fq[1] is for deletion
-#endif
-
-   Eina_Bool has_alpha : 1;
-};
-
-struct _RGBA_Gradient2_Type
-{
-   const char              *name;
-   void                    (*init)(void);
-   void                    (*shutdown)(void);
-   void                    (*geom_init)(RGBA_Gradient2 *gr);
-   void                    (*geom_update)(RGBA_Gradient2 *gr);
-   void                    (*geom_free)(void *gdata);
-   int                     (*has_alpha)(RGBA_Gradient2 *gr, int render_op);
-   int                     (*has_mask)(RGBA_Gradient2 *gr, int render_op);
-   int                     (*get_map_len)(RGBA_Gradient2 *gr);
-   Gfx_Func_Gradient2_Fill  (*get_fill_func)(RGBA_Gradient2 *gr, int render_op);
-};
-
-
 struct _RGBA_Polygon_Point
 {
    EINA_INLIST;
@@ -1280,7 +1114,6 @@ EAPI void     evas_common_blit_init               (void);
 EAPI void     evas_common_blit_rectangle          (const RGBA_Image *src, RGBA_Image *dst, int src_x, int src_y, int w, int h, int dst_x, int dst_y);
 
 /****/
-#include "../engines/common/evas_gradient.h"
 #include "../engines/common/evas_font.h"
 
 /****/
@@ -1331,4 +1164,5 @@ void              evas_font_dir_cache_free(void);
 #ifdef __cplusplus
 }
 #endif
+
 #endif
diff --git a/src/lib/include/evas_common_soft8.h b/src/lib/include/evas_common_soft8.h
new file mode 100644 (file)
index 0000000..a762022
--- /dev/null
@@ -0,0 +1,194 @@
+#ifndef EVAS_COMMON_SOFT8_H
+#define EVAS_COMMON_SOFT8_H
+
+#include "evas_common.h"
+#include "evas_private.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef always_inline
+#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
+#    define always_inline __attribute__((always_inline)) inline
+#else
+#    define always_inline inline
+#endif
+#endif
+
+#define GRY_8_BLEND(a, b, alpha)       \
+   ((b) + (a) - ((((b) * ((alpha) + 1)) >> 8) & 0xff))
+
+#define GRY_8_BLEND_UNMUL(a, b, alpha) \
+   ((b) + ((((a) - (b)) * ((alpha) + 1)) >> 8))
+
+#if 0
+#define GRY_8_FROM_COMPONENTS(r, g, b) \
+     (((307 * (r)) +   \
+       (604 * (g)) +   \
+       (113 * (b))) >> 10)
+
+#define GRY_8_FROM_RGB(rgb)    \
+     GRY_8_FROM_COMPONENTS(R_VAL(rgb), G_VAL(rgb), B_VAL(rgb))
+#endif
+
+//Y = R * 0.2126 + G * 0.7152 + B * 0.0722
+
+#define GRY_8_FROM_COMPONENTS(r, g, b) \
+     (((218 * (r)) +   \
+       (732 * (g)) +   \
+       (74  * (b))) >> 10)
+
+#define GRY_8_FROM_RGB(rgb)    \
+     GRY_8_FROM_COMPONENTS(R_VAL(rgb), G_VAL(rgb), B_VAL(rgb))
+
+#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)
+
+#if defined(__ARM_ARCH_3M__)
+# define __ARM_ARCH__ 40
+#endif
+#if defined(__ARM_ARCH_4__)
+# define __ARM_ARCH__ 40
+#endif
+#if defined(__ARM_ARCH_4T__)
+# define __ARM_ARCH__ 41
+#endif
+
+#if defined(__ARM_ARCH_5__)
+# define __ARM_ARCH__ 50
+#endif
+#if defined(__ARM_ARCH_5T__)
+# define __ARM_ARCH__ 51
+#endif
+#if defined(__ARM_ARCH_5E__)
+# define __ARM_ARCH__ 52
+#endif
+#if defined(__ARM_ARCH_5TE__)
+# define __ARM_ARCH__ 53
+#endif
+#if defined(__ARM_ARCH_5TEJ__)
+# define __ARM_ARCH__ 54
+#endif
+
+#if defined(__ARM_ARCH_6__)
+# define __ARM_ARCH__ 60
+#endif
+#if defined(__ARM_ARCH_6J__)
+# define __ARM_ARCH__ 61
+#endif
+#if defined(__ARM_ARCH_6K__)
+# define __ARM_ARCH__ 62
+#endif
+#if defined(__ARM_ARCH_6Z__)
+# define __ARM_ARCH__ 63
+#endif
+#if defined(__ARM_ARCH_6ZK__)
+# define __ARM_ARCH__ 64
+#endif
+#if defined(__ARM_ARCH_6T2__)
+# define __ARM_ARCH__ 65
+#endif
+
+#if defined(__ARM_ARCH_7__)
+# define __ARM_ARCH__ 70
+#endif
+#if defined(__ARM_ARCH_7A__)
+# define __ARM_ARCH__ 71
+#endif
+#if defined(__ARM_ARCH_7R__)
+# define __ARM_ARCH__ 72
+#endif
+#if defined(__ARM_ARCH_7M__)
+# define __ARM_ARCH__ 73
+#endif
+
+#if defined(__ARM_ARCH__) && (__ARM_ARCH__ >= 52)
+/* tested on ARMv6 (arm1136j-s), Nokia N800 CPU */
+#define pld(addr, off)                                                  \
+   __asm__("pld [%[address], %[offset]]"::                              \
+           [address] "r" (addr), [offset] "i" (off))
+#else
+#define pld(addr, off)
+#endif /* __ARMEL__ */
+
+static inline int
+_calc_stride(int w)
+{
+   int pad;
+
+   pad = w % 4;
+   if (!pad)  return w;
+   else return w + 4 - pad;
+}
+
+#define IMG_BYTE_SIZE(stride, height, has_alpha)                       \
+   ((stride) * (height) * (!(has_alpha) ? 1 : 2))
+
+typedef struct _Soft8_Image Soft8_Image;
+struct _Soft8_Image
+{
+   Image_Entry    cache_entry;
+
+   RGBA_Image    *source;
+
+   int            stride;     // pixel stride
+   DATA8        *pixels;      // 8bpp pixels gry8
+   DATA8         *alpha;      // 8bit alpha mask - optional. points into pixels
+
+   void                *extended_info;
+
+   struct
+   {
+/*      unsigned char  have_alpha  : 1; // 1 if we have halpha */
+     unsigned char  free_pixels : 1; // 1 if pixels should be freed
+     unsigned char  free_alpha  : 1; // 1 if alpha mask should be freed
+   } flags;
+};
+
+/**
+ * Image (evas_soft8_main.c)
+ */
+EAPI void                evas_common_soft8_image_init(void);
+EAPI void                evas_common_soft8_image_shutdown(void);
+EAPI Evas_Cache_Image   *evas_common_soft8_image_cache_get(void);
+
+EAPI void                soft8_image_draw(Soft8_Image *src, Soft8_Image *dst, RGBA_Draw_Context *dc, 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, int smooth);
+EAPI Soft8_Image       *soft8_image_alpha_set(Soft8_Image *im, int have_alpha);
+
+void                     soft8_image_draw_unscaled(Soft8_Image *src, Soft8_Image *dst, RGBA_Draw_Context *dc, const Eina_Rectangle sr, const Eina_Rectangle dr, const Eina_Rectangle cr);
+void                     soft8_image_draw_scaled_sampled(Soft8_Image *src, Soft8_Image *dst, RGBA_Draw_Context *dc, const Eina_Rectangle sr, const Eina_Rectangle dr, const Eina_Rectangle cr);
+
+/* convert/dither functions */
+void                     soft8_image_convert_from_rgb(Soft8_Image *im, const DATA32 *src);
+void                     soft8_image_convert_from_rgba(Soft8_Image *im, const DATA32 *src);
+
+/**
+ * Rectangle (evas_soft8_rectangle.c)
+ */
+EAPI void                soft8_rectangle_draw(Soft8_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h);
+
+/**
+ * Polygon (evas_soft8_polygon.c)
+ */
+EAPI void                soft8_polygon_draw(Soft8_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points, int x, int y);
+
+/**
+ * Line (evas_soft8_line.c)
+ */
+EAPI void                soft8_line_draw(Soft8_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1);
+
+/**
+ * Font (evas_soft8_font.c)
+ */
+EAPI void               *soft8_font_glyph_new(void *data, RGBA_Font_Glyph *fg);
+EAPI void                soft8_font_glyph_free(void *ext_dat);
+EAPI void                soft8_font_glyph_draw(void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index 2c01857..99540a6 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "../file/evas_module.h"
 #include "../file/evas_path.h"
+#include "../engines/common/evas_bidi_utils.h"
 
 #ifdef EVAS_MAGIC_DEBUG
 /* complain when peole pass in wrong object types etc. */
@@ -56,15 +57,12 @@ typedef struct _Evas_Post_Callback          Evas_Post_Callback;
 #define MAGIC_OBJ                  0x71777770
 #define MAGIC_OBJ_RECTANGLE        0x71777771
 #define MAGIC_OBJ_LINE             0x71777772
-#define MAGIC_OBJ_GRADIENT         0x71777773
 #define MAGIC_OBJ_POLYGON          0x71777774
 #define MAGIC_OBJ_IMAGE            0x71777775
 #define MAGIC_OBJ_TEXT             0x71777776
 #define MAGIC_OBJ_SMART            0x71777777
 #define MAGIC_OBJ_TEXTBLOCK        0x71777778
 #define MAGIC_SMART                0x72777770
-#define MAGIC_OBJ_GRADIENT_LINEAR  0x72777771
-#define MAGIC_OBJ_GRADIENT_RADIAL  0x72777772
 #define MAGIC_OBJ_SHAPE            0x72777773
 #define MAGIC_OBJ_CONTAINER        0x72777774
 #define MAGIC_OBJ_CUSTOM           0x72777775
@@ -623,49 +621,6 @@ struct _Evas_Func
    void *(*polygon_points_clear)           (void *data, void *context, void *polygon);
    void (*polygon_draw)                    (void *data, void *context, void *surface, void *polygon, int x, int y);
 
-   void (*gradient2_color_np_stop_insert)   (void *data, void *gradient, int r, int g, int b, int a, float pos);
-   void (*gradient2_clear)                  (void *data, void *gradient);
-   void (*gradient2_fill_transform_set)     (void *data, void *gradient, void *transform);
-   void (*gradient2_fill_spread_set)        (void *data, void *gradient, int spread);
-
-   void *(*gradient2_linear_new)                   (void *data);
-   void (*gradient2_linear_free)                   (void *data, void *linear_gradient);
-   void (*gradient2_linear_fill_set)               (void *data, void *linear_gradient, float x0, float y0, float x1, float y1);
-   int  (*gradient2_linear_is_opaque)              (void *data, void *context, void *linear_gradient, int x, int y, int w, int h);
-   int  (*gradient2_linear_is_visible)             (void *data, void *context, void *linear_gradient, int x, int y, int w, int h);
-   void (*gradient2_linear_render_pre)             (void *data, void *context, void *linear_gradient);
-   void (*gradient2_linear_render_post)            (void *data, void *linear_gradient);
-   void (*gradient2_linear_draw)                   (void *data, void *context, void *surface, void *linear_gradient, int x, int y, int w, int h);
-
-   void *(*gradient2_radial_new)                   (void *data);
-   void (*gradient2_radial_free)                   (void *data, void *radial_gradient);
-   void (*gradient2_radial_fill_set)               (void *data, void *radial_gradient, float cx, float cy, float rx, float ry);
-   int  (*gradient2_radial_is_opaque)              (void *data, void *context, void *radial_gradient, int x, int y, int w, int h);
-   int  (*gradient2_radial_is_visible)             (void *data, void *context, void *radial_gradient, int x, int y, int w, int h);
-   void (*gradient2_radial_render_pre)             (void *data, void *context, void *radial_gradient);
-   void (*gradient2_radial_render_post)            (void *data, void *radial_gradient);
-   void (*gradient2_radial_draw)                   (void *data, void *context, void *surface, void *radial_gradient, int x, int y, int w, int h);
-
-   void *(*gradient_new)                   (void *data);
-   void (*gradient_free)                   (void *data, void *gradient);
-   void (*gradient_color_stop_add)         (void *data, void *gradient, int r, int g, int b, int a, int delta);
-   void (*gradient_alpha_stop_add)         (void *data, void *gradient, int a, int delta);
-   void (*gradient_color_data_set)         (void *data, void *gradient, void *map, int len, int alpha_flag);
-   void (*gradient_alpha_data_set)         (void *data, void *gradient, void *alpha_map, int len);
-   void (*gradient_clear)                  (void *data, void *gradient);
-   void (*gradient_fill_set)               (void *data, void *gradient, int x, int y, int w, int h);
-   void (*gradient_fill_angle_set)         (void *data, void *gradient, double fill_angle);
-   void (*gradient_fill_spread_set)        (void *data, void *gradient, int spread);
-   void (*gradient_angle_set)              (void *data, void *gradient, double angle);
-   void (*gradient_offset_set)             (void *data, void *gradient, float offset);
-   void (*gradient_direction_set)          (void *data, void *gradient, int direction);
-   void (*gradient_type_set)               (void *data, void *gradient, char *name, char *params);
-   int  (*gradient_is_opaque)              (void *data, void *context, void *gradient, int x, int y, int w, int h);
-   int  (*gradient_is_visible)             (void *data, void *context, void *gradient, int x, int y, int w, int h);
-   void (*gradient_render_pre)             (void *data, void *context, void *gradient);
-   void (*gradient_render_post)            (void *data, void *gradient);
-   void (*gradient_draw)                   (void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h);
-
    void *(*image_load)                     (void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo);
    void *(*image_new_from_data)            (void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
    void *(*image_new_from_copied_data)     (void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
@@ -687,7 +642,7 @@ struct _Evas_Func
    char *(*image_format_get)               (void *data, void *image);
    void (*image_colorspace_set)            (void *data, void *image, int cspace);
    int  (*image_colorspace_get)            (void *data, void *image);
-   void (*image_native_set)                (void *data, void *image, void *native);
+   void *(*image_native_set)               (void *data, void *image, void *native);
    void *(*image_native_get)               (void *data, void *image);
 
    void (*image_cache_flush)               (void *data);
@@ -703,13 +658,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 char *text, int *w, int *h);
-   int  (*font_inset_get)                  (void *data, void *font, const char *text);
-   int  (*font_h_advance_get)              (void *data, void *font, const char *text);
-   int  (*font_v_advance_get)              (void *data, void *font, const char *text);
-   int  (*font_char_coords_get)            (void *data, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch);
-   int  (*font_char_at_coords_get)         (void *data, void *font, const char *text, 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 char *text);
+   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_cache_flush)                (void *data);
    void (*font_cache_set)                  (void *data, int bytes);
@@ -724,11 +679,14 @@ 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 char *text, int x, int y);
+   int  (*font_last_up_to_pos)             (void *data, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int x, int y);
 
    void (*image_map4_draw)                 (void *data, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level);
    void *(*image_map_surface_new)          (void *data, int w, int h, int alpha);
    void (*image_map_surface_free)          (void *data, void *surface);
+
+   void (*image_content_hint_set)          (void *data, void *surface, int hint);
+   int  (*image_content_hint_get)          (void *data, void *surface);
 };
 
 struct _Evas_Image_Load_Func
index a7e9f29..7e3383d 100644 (file)
@@ -106,7 +106,7 @@ evas_debug_error(void)
        _evas_debug_init = 1;
      }
    if (_evas_debug_show)
-     DBG("*** EVAS ERROR: Evas Magic Check Failed!!!");
+     CRIT("Evas Magic Check Failed!!!");
 }
 
 void
@@ -119,7 +119,7 @@ evas_debug_input_null(void)
        _evas_debug_init = 1;
      }
    if (_evas_debug_show)
-     DBG("Input object pointer is NULL!");
+     CRIT("Input object pointer is NULL!");
    if (_evas_debug_abort) abort();
 }
 
@@ -133,7 +133,7 @@ evas_debug_magic_null(void)
        _evas_debug_init = 1;
      }
    if (_evas_debug_show)
-     DBG("Input object is zero'ed out (maybe a freed object or zero-filled RAM)!");
+     CRIT("Input object is zero'ed out (maybe a freed object or zero-filled RAM)!");
    if (_evas_debug_abort) abort();
 }
 
@@ -147,11 +147,11 @@ evas_debug_magic_wrong(DATA32 expected, DATA32 supplied)
        _evas_debug_init = 1;
      }
    if (_evas_debug_show)
-     DBG("  Input object is wrong type\n"
-          "    Expected: %08x - %s\n"
-          "    Supplied: %08x - %s",
-          expected, evas_debug_magic_string_get(expected),
-          supplied, evas_debug_magic_string_get(supplied));
+     CRIT("Input object is wrong type\n"
+         "    Expected: %08x - %s\n"
+         "    Supplied: %08x - %s",
+         expected, evas_debug_magic_string_get(expected),
+         supplied, evas_debug_magic_string_get(supplied));
    if (_evas_debug_abort) abort();
 }
 
@@ -165,8 +165,7 @@ evas_debug_generic(const char *str)
        _evas_debug_init = 1;
      }
    if (_evas_debug_show)
-     DBG("*** EVAS ERROR:\n"
-          "%s", (char *)str);
+     CRIT("%s", str);
    if (_evas_debug_abort) abort();
 }
 
@@ -187,9 +186,6 @@ evas_debug_magic_string_get(DATA32 magic)
       case MAGIC_OBJ_LINE:
        return "Evas_Object (Line)";
        break;
-      case MAGIC_OBJ_GRADIENT:
-       return "Evas_Object (Gradient)";
-       break;
       case MAGIC_OBJ_POLYGON:
        return "Evas_Object (Polygon)";
        break;
index 1db0e21..bdc9ba1 100644 (file)
@@ -29,6 +29,12 @@ endif
 if !EVAS_STATIC_BUILD_QUARTZ
 SUBDIRS += quartz
 endif
+if !EVAS_STATIC_BUILD_SOFTWARE_8
+SUBDIRS += software_8
+endif
+if !EVAS_STATIC_BUILD_SOFTWARE_8_X11
+SUBDIRS += software_8_x11
+endif
 if !EVAS_STATIC_BUILD_SOFTWARE_16
 SUBDIRS += software_16
 endif
index 371eabd..45d92cd 100644 (file)
@@ -19,7 +19,8 @@ evas_outbuf.c
 
 pkgdir = $(libdir)/evas/modules/engines/buffer/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Buffer.h
+includes_HEADERS = Evas_Engine_Buffer.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_BUFFER
 
index 0add001..ec10c25 100644 (file)
@@ -74,7 +74,6 @@ _output_setup(int w,
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
index e861db2..33153ff 100644 (file)
@@ -20,7 +20,8 @@ CAIRO_X11_LIBADD = @evas_engine_cairo_x11_libs@ $(top_builddir)/src/modules/engi
 
 pkgdir = $(libdir)/evas/modules/engines/cairo_x11/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Cairo_X11.h
+includes_HEADERS = Evas_Engine_Cairo_X11.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_CAIRO_X11
 
index 36c834d..3040473 100644 (file)
@@ -1,6 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
 #include <X11/Xlib.h>
 #include "evas_common.h"
 #include "evas_private.h"
@@ -54,26 +51,6 @@ static void *eng_polygon_point_add(void *data, void *context, void *polygon, int
 static void *eng_polygon_points_clear(void *data, void *context, void *polygon);
 static void eng_polygon_draw(void *data, void *context, void *surface, void *polygon, int x, int y);
 
-static void *eng_gradient_new(void *data);
-static void eng_gradient_free(void *data, void *gradient);
-static void eng_gradient_color_stop_add(void *data, void *gradient, int r, int g, int b, int a, int delta);
-static void eng_gradient_alpha_stop_add(void *data, void *gradient, int a, int delta);
-static void eng_gradient_color_data_set(void *data, void *gradient, void *map, int len, int has_alpha);
-static void eng_gradient_alpha_data_set(void *data, void *gradient, void *alpha_map, int len);
-static void eng_gradient_clear(void *data, void *gradient);
-static void eng_gradient_fill_set(void *data, void *gradient, int x, int y, int w, int h);
-static void eng_gradient_fill_angle_set(void *data, void *gradient, double angle);
-static void eng_gradient_fill_spread_set(void *data, void *gradient, int spread);
-static void eng_gradient_angle_set(void *data, void *gradient, double angle);
-static void eng_gradient_offset_set(void *data, void *gradient, float offset);
-static void eng_gradient_direction_set(void *data, void *gradient, int direction);
-static void eng_gradient_type_set(void *data, void *gradient, char *name, char *params);
-static int eng_gradient_is_opaque(void *data, void *context, void *gradient, int x, int y, int w, int h);
-static int eng_gradient_is_visible(void *data, void *context, void *gradient, int x, int y, int w, int h);
-static void eng_gradient_render_pre(void *data, void *context, void *gradient);
-static void eng_gradient_render_post(void *data, void *gradient);
-static void eng_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h);
-
 static void *eng_image_load(void *data, char *file, char *key, int *error, Evas_Image_Load_Opts *lo);
 static void *eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
 static void *eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
@@ -177,26 +154,6 @@ static Evas_Func eng_func =
      eng_polygon_point_add,
      eng_polygon_points_clear,
      eng_polygon_draw,
-     /* gradient draw funcs */
-     eng_gradient_new,
-     eng_gradient_free,
-     eng_gradient_color_stop_add,
-     eng_gradient_alpha_stop_add,
-     eng_gradient_color_data_set,
-     eng_gradient_alpha_data_set,
-     eng_gradient_clear,
-     eng_gradient_fill_set,
-     eng_gradient_fill_angle_set,
-     eng_gradient_fill_spread_set,
-     eng_gradient_angle_set,
-     eng_gradient_offset_set,
-     eng_gradient_direction_set,
-     eng_gradient_type_set,
-     eng_gradient_is_opaque,
-     eng_gradient_is_visible,
-     eng_gradient_render_pre,
-     eng_gradient_render_post,
-     eng_gradient_draw,
      /* image draw funcs */
      eng_image_load,
      eng_image_new_from_data,
@@ -331,7 +288,6 @@ eng_output_setup(int w, int h, Display *disp, Drawable draw, Visual *vis, Colorm
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
@@ -801,117 +757,6 @@ eng_polygon_draw(void *data, void *context, void *surface, void *polygon, int x,
 }
 
 static void *
-eng_gradient_new(void *data)
-{
-   return evas_common_gradient_new();
-}
-
-static void
-eng_gradient_color_stop_add(void *data, void *gradient, int r, int g, int b, int a, int delta)
-{
-   evas_common_gradient_color_stop_add(gradient, r, g, b, a, delta);
-}
-
-static void
-eng_gradient_alpha_stop_add(void *data, void *gradient, int a, int delta)
-{
-   evas_common_gradient_alpha_stop_add(gradient, a, delta);
-}
-
-static void
-eng_gradient_clear(void *data, void *gradient)
-{
-   evas_common_gradient_clear(gradient);
-}
-
-static void
-eng_gradient_color_data_set(void *data, void *gradient, void *map, int len, int has_alpha)
-{
-   evas_common_gradient_color_data_set(gradient, map, len, has_alpha);
-}
-
-static void
-eng_gradient_alpha_data_set(void *data, void *gradient, void *alpha_map, int len)
-{
-   evas_common_gradient_alpha_data_set(gradient, alpha_map, len);
-}
-
-static void
-eng_gradient_free(void *data, void *gradient)
-{
-   evas_common_gradient_free(gradient);
-}
-
-static void
-eng_gradient_fill_set(void *data, void *gradient, int x, int y, int w, int h)
-{
-   evas_common_gradient_fill_set(gradient, x, y, w, h);
-}
-
-static void
-eng_gradient_fill_angle_set(void *data, void *gradient, double angle)
-{
-   evas_common_gradient_fill_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_fill_spread_set(void *data, void *gradient, int spread)
-{
-   evas_common_gradient_fill_spread_set(gradient, spread);
-}
-
-static void
-eng_gradient_angle_set(void *data, void *gradient, double angle)
-{
-   evas_common_gradient_map_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_offset_set(void *data, void *gradient, float offset)
-{
-   evas_common_gradient_map_offset_set(gradient, offset);
-}
-
-static void
-eng_gradient_direction_set(void *data, void *gradient, int direction)
-{
-   evas_common_gradient_map_direction_set(gradient, direction);
-}
-
-static void
-eng_gradient_type_set(void *data, void *gradient, char *name, char *params)
-{
-   evas_common_gradient_type_set(gradient, name, params);
-}
-
-static int
-eng_gradient_is_opaque(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   return 0;
-}
-
-static int
-eng_gradient_is_visible(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   return 0;
-}
-
-static void
-eng_gradient_render_pre(void *data, void *context, void *gradient)
-{
-}
-
-static void
-eng_gradient_render_post(void *data, void *gradient)
-{
-}
-
-static void
-eng_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h)
-{
-}
-
-static void *
 eng_image_load(void *data, char *file, char *key, int *error, Evas_Image_Load_Opts *lo)
 {
    Render_Engine *re;
index 6b1412d..5847494 100644 (file)
@@ -31,7 +31,8 @@ DIRECT3D_LIBADD = @evas_engine_direct3d_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/direct3d/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Direct3D.h
+includes_HEADERS = Evas_Engine_Direct3D.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_DIRECT3D
 
index 5fcd89d..6d6912d 100644 (file)
@@ -1,3 +1,4 @@
+#include "evas_common.h" /* Also includes international specific stuff */
 #include "evas_engine.h"
 #include "evas_private.h"
 #include "Evas_Engine_Direct3D.h"
@@ -50,7 +51,6 @@ _output_setup(int width, int height, int rotation, HWND window, int depth, int f
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
@@ -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 char *text)
+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)
 {
    Render_Engine *re = (Render_Engine *)data;
        RGBA_Image im;
@@ -402,7 +402,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
       evas_direct3d_font_texture_new,
       evas_direct3d_font_texture_free,
       evas_direct3d_font_texture_draw);
-   evas_common_font_draw(&im, context, font, x, y, text);
+   evas_common_font_draw(&im, context, font, x, y, text, intl_props);
    evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL);
 }
 
@@ -414,119 +414,6 @@ eng_font_free(void *data, void *font)
    evas_direct3d_font_free(re->d3d, font);
 }
 
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Gradients
-//
-
-static void
-eng_gradient2_color_np_stop_insert(void *data, void *gradient, int r, int g, int b, int a, float pos)
-{
-}
-
-static void
-eng_gradient2_clear(void *data, void *gradient)
-{
-}
-
-static void
-eng_gradient2_fill_transform_set(void *data, void *gradient, void *transform)
-{
-}
-
-static void
-eng_gradient2_fill_spread_set(void *data, void *gradient, int spread)
-{
-}
-
-static void *
-eng_gradient2_linear_new(void *data)
-{
-   return NULL;
-}
-
-static void
-eng_gradient2_linear_free(void *data, void *linear_gradient)
-{
-}
-
-static void
-eng_gradient2_linear_fill_set(void *data, void *linear_gradient, int x0, int y0, int x1, int y1)
-{
-}
-
-static int
-eng_gradient2_linear_is_opaque(void *data, void *context, void *linear_gradient, int x, int y, int w, int h)
-{
-   return 1;
-}
-
-static int
-eng_gradient2_linear_is_visible(void *data, void *context, void *linear_gradient, int x, int y, int w, int h)
-{
-   return 1;
-}
-
-static void
-eng_gradient2_linear_render_pre(void *data, void *context, void *linear_gradient)
-{
-}
-
-static void
-eng_gradient2_linear_render_post(void *data, void *linear_gradient)
-{
-}
-
-static void
-eng_gradient2_linear_draw(void *data, void *context, void *surface, void *linear_gradient, int x, int y, int w, int h)
-{
-}
-
-static void *
-eng_gradient2_radial_new(void *data)
-{
-   return NULL;
-}
-
-static void
-eng_gradient2_radial_free(void *data, void *radial_gradient)
-{
-}
-
-static void
-eng_gradient2_radial_fill_set(void *data, void *radial_gradient, float cx, float cy, float rx, float ry)
-{
-}
-
-static int
-eng_gradient2_radial_is_opaque(void *data, void *context, void *radial_gradient, int x, int y, int w, int h)
-{
-   return 1;
-}
-
-static int
-eng_gradient2_radial_is_visible(void *data, void *context, void *radial_gradient, int x, int y, int w, int h)
-{
-   return 1;
-}
-
-static void
-eng_gradient2_radial_render_pre(void *data, void *context, void *radial_gradient)
-{
-}
-
-static void
-eng_gradient2_radial_render_post(void *data, void *radial_gradient)
-{
-}
-
-static void
-eng_gradient2_radial_draw(void *data, void *context, void *surface, void *radial_gradient, int x, int y, int w, int h)
-{
-}
-
-
 /* module advertising code */
 static int
 module_open(Evas_Module *em)
@@ -585,28 +472,6 @@ module_open(Evas_Module *em)
 //   ORD(image_map_surface_new);
 //   ORD(image_map_surface_free);
 
-/*
-   ORD(gradient2_color_np_stop_insert);
-   ORD(gradient2_clear);
-   ORD(gradient2_fill_transform_set);
-   ORD(gradient2_fill_spread_set);
-   ORD(gradient2_linear_new);
-   ORD(gradient2_linear_free);
-   ORD(gradient2_linear_fill_set);
-   ORD(gradient2_linear_is_opaque);
-   ORD(gradient2_linear_is_visible);
-   ORD(gradient2_linear_render_pre);
-   ORD(gradient2_linear_render_post);
-   ORD(gradient2_linear_draw);
-   ORD(gradient2_radial_new);
-   ORD(gradient2_radial_free);
-   ORD(gradient2_radial_fill_set);
-   ORD(gradient2_radial_is_opaque);
-   ORD(gradient2_radial_is_visible);
-   ORD(gradient2_radial_render_pre);
-   ORD(gradient2_radial_render_post);
-   ORD(gradient2_radial_draw);
-*/
    /* now advertise out own api */
    em->functions = (void *)(&func);
    return 1;
index c4b7a5e..ff571b5 100644 (file)
@@ -19,7 +19,8 @@ DIRECTFB_LIBADD = @evas_engine_directfb_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/directfb/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_DirectFB.h
+includes_HEADERS = Evas_Engine_DirectFB.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_DIRECTFB
 
index 1960c22..6c5a2c8 100644 (file)
@@ -4,6 +4,7 @@
 #include <sys/time.h>
 #include <time.h>
 #include "evas_engine.h"
+#include "evas_common.h" /* Also includes international specific stuff */
 
 /* Uses Evas own image_draw primitive, for comparison purposes only. */
 //#define DFB_USE_EVAS_IMAGE_DRAW 1
@@ -737,7 +738,6 @@ _evas_common_init(void)
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
@@ -1041,7 +1041,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 char *text)
+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)
 {
    DirectFB_Engine_Image_Entry *eim = surface;
    IDirectFBSurface *screen;
@@ -1053,7 +1053,7 @@ evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font,
    if (!_dfb_lock_and_sync_image(screen, im, DSLF_READ | DSLF_WRITE))
      return;
 
-   evas_common_font_draw(im, context, font, x, y, text);
+   evas_common_font_draw(im, context, font, x, y, text, intl_props);
    evas_common_cpu_end_opt();
 
    im->image.data = NULL;
@@ -1167,29 +1167,6 @@ evas_engine_dfb_polygon_draw(void *data, void *context, void *surface, void *pol
 }
 #endif
 
-static void
-evas_engine_dfb_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h)
-{
-   DirectFB_Engine_Image_Entry *eim = surface;
-   IDirectFBSurface *screen;
-   Render_Engine *re = data;
-   RGBA_Image *dst, *src;
-
-   dst = (RGBA_Image *)eim->cache_entry.src;
-   screen = eim->surface;
-   if (!_dfb_lock_and_sync_image(screen, dst, DSLF_READ | DSLF_WRITE))
-     return;
-
-   evas_common_gradient_draw(dst, context, x, y, w, h, gradient);
-   evas_common_cpu_end_opt();
-
-   dst->image.data = NULL;
-
-   screen->Unlock(screen);
-
-   return;
-}
-
 /** Image Object *******************************************************/
 static void *
 evas_engine_dfb_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo)
@@ -1741,7 +1718,6 @@ module_open(Evas_Module *em)
    ORD(line_draw);
    ORD(rectangle_draw);
    ORD(polygon_draw);
-   ORD(gradient_draw);
    ORD(image_scale_hint_set);
    ORD(image_scale_hint_get);
 
index 6779773..58c70ca 100644 (file)
@@ -21,7 +21,8 @@ FB_LIBADD = @evas_engine_fb_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/fb/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_FB.h
+includes_HEADERS = Evas_Engine_FB.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_FB
 
index a0b5e3d..28821ce 100644 (file)
@@ -54,7 +54,6 @@ _output_setup(int w, int h, int rot, int vt, int dev, int refresh)
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
index e9dfbeb..1b77a18 100644 (file)
 #endif
 
 #ifndef GL_TEXTURE_RECTANGLE_NV
-#define GL_TEXTURE_RECTANGLE_NV 0x84F5
+# define GL_TEXTURE_RECTANGLE_NV 0x84F5
 #endif
 #ifndef GL_BGRA
-#define GL_BGRA 0x80E1
+# define GL_BGRA 0x80E1
+#endif
+
+#ifndef EGL_NO_CONTEXT
+# define EGL_NO_CONTEXT 0
+#endif
+#ifndef EGL_NONE
+# define EGL_NONE 0x3038
+#endif
+#ifndef EGL_TRUE
+# define EGL_TRUE 1
+#endif
+#ifndef EGL_FALSE
+# define EGL_FALSE 0
+#endif
+
+#ifndef EGL_MAP_GL_TEXTURE_2D_SEC
+# define EGL_MAP_GL_TEXTURE_2D_SEC 0x3201
+#endif
+#ifndef  EGL_MAP_GL_TEXTURE_HEIGHT_SEC
+# define EGL_MAP_GL_TEXTURE_HEIGHT_SEC 0x3202
+#endif
+#ifndef EGL_MAP_GL_TEXTURE_WIDTH_SEC
+# define EGL_MAP_GL_TEXTURE_WIDTH_SEC 0x3203
+#endif
+#ifndef EGL_MAP_GL_TEXTURE_FORMAT_SEC
+# define EGL_MAP_GL_TEXTURE_FORMAT_SEC 0x3204
+#endif
+#ifndef EGL_MAP_GL_TEXTURE_RGB_SEC
+# define EGL_MAP_GL_TEXTURE_RGB_SEC 0x3205
+#endif
+#ifndef EGL_MAP_GL_TEXTURE_RGBA_SEC
+# define EGL_MAP_GL_TEXTURE_RGBA_SEC 0x3206
+#endif
+#ifndef EGL_MAP_GL_TEXTURE_PIXEL_TYPE_SEC
+# define EGL_MAP_GL_TEXTURE_PIXEL_TYPE_SEC 0x3206
+#endif
+#ifndef EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC
+# define EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC 0x3207
+#endif
+#ifndef EGL_MAP_GL_TEXTURE_STRIDE_IN_BYTES_SEC
+# define EGL_MAP_GL_TEXTURE_STRIDE_IN_BYTES_SEC 0x3208
 #endif
 
 #define SHAD_VERTEX 0
@@ -57,6 +98,9 @@
 #define SHAD_TEXUV2 3
 #define SHAD_TEXUV3 4
 
+#define MAX_CUTOUT 512
+#define MAX_PIPES  128
+
 typedef struct _Evas_GL_Program                      Evas_GL_Program;
 typedef struct _Evas_GL_Program_Source               Evas_GL_Program_Source;
 typedef struct _Evas_GL_Shared                       Evas_GL_Shared;
@@ -67,9 +111,6 @@ typedef struct _Evas_GL_Image                        Evas_GL_Image;
 typedef struct _Evas_GL_Font_Texture                 Evas_GL_Font_Texture;
 typedef struct _Evas_GL_Polygon                      Evas_GL_Polygon;
 typedef struct _Evas_GL_Polygon_Point                Evas_GL_Polygon_Point;
-/*
-typedef struct _Evas_GL_Gradient                     Evas_GL_Gradient;
-*/
 
 struct _Evas_GL_Program
 {
@@ -95,6 +136,10 @@ struct _Evas_GL_Shared
       Eina_Bool bgra : 1;
       Eina_Bool tex_npo2 : 1;
       Eina_Bool tex_rect : 1;
+      Eina_Bool sec_image_map : 1;
+      // tuning params - per gpu/cpu combo?
+      int cutout_max;
+      int pipes_max;
    } info;
    
    struct {
@@ -102,6 +147,8 @@ struct _Evas_GL_Shared
       Eina_List       *atlas[33][3];
    } tex;
    
+   Eina_Hash          *native_hash;
+   
    struct {
       Evas_GL_Program  rect;
       Evas_GL_Program  font;
@@ -116,6 +163,14 @@ struct _Evas_GL_Shared
    int rot;
 };
 
+#define RTYPE_RECT  1
+#define RTYPE_IMAGE 2
+#define RTYPE_FONT  3
+#define RTYPE_YUV   4
+#define RTYPE_MAP   5 /* need to merge with image */ 
+
+
+
 struct _Evas_GL_Context
 {
    int                references;
@@ -124,19 +179,10 @@ struct _Evas_GL_Context
    RGBA_Draw_Context  *dc;
    
    Evas_GL_Shared     *shared;
+
+   int flushnum;
    struct {
-      int             x, y, w, h;
-      Eina_Bool       active : 1;
-   } clip;
-   struct {
-      Evas_GL_Image  *surface;
-      GLuint          cur_prog;
-      GLuint          cur_tex, cur_texu, cur_texv;
-      int             render_op;
-      int             cx, cy, cw, ch;
-      Eina_Bool       smooth : 1;
-      Eina_Bool       blend : 1;
-      Eina_Bool       clip : 1;
+      int                top_pipe;
       struct {
          GLuint          cur_prog;
          GLuint          cur_tex, cur_texu, cur_texv;
@@ -146,28 +192,54 @@ struct _Evas_GL_Context
          Eina_Bool       blend : 1;
          Eina_Bool       clip : 1;
       } current;
-   } shader;
+   } state;
+   
    struct {
-      int num;
-      int alloc;
-      GLshort *vertex;
-      GLubyte *color;
-      GLfloat *texuv;
-      GLfloat *texuv2;
-      GLfloat *texuv3;
-      Eina_Bool line : 1;
-      Eina_Bool use_vertex : 1;
-      Eina_Bool use_color : 1;
-      Eina_Bool use_texuv : 1;
-      Eina_Bool use_texuv2 : 1;
-      Eina_Bool use_texuv3 : 1;
-      Evas_GL_Image *im;
-   } array;
+      struct {
+         int             x, y, w, h;
+         int             type;
+      } region;
+      struct {
+         int             x, y, w, h;
+         Eina_Bool       active : 1;
+      } clip;
+      struct {
+         Evas_GL_Image  *surface;
+         GLuint          cur_prog;
+         GLuint          cur_tex, cur_texu, cur_texv;
+         int             render_op;
+         int             cx, cy, cw, ch;
+         Eina_Bool       smooth : 1;
+         Eina_Bool       blend : 1;
+         Eina_Bool       clip : 1;
+      } shader;
+      struct {
+         int num, alloc;
+         GLshort *vertex;
+         GLubyte *color;
+         GLfloat *texuv;
+         GLfloat *texuv2;
+         GLfloat *texuv3;
+         Eina_Bool line : 1;
+         Eina_Bool use_vertex : 1;
+         Eina_Bool use_color : 1;
+         Eina_Bool use_texuv : 1;
+         Eina_Bool use_texuv2 : 1;
+         Eina_Bool use_texuv3 : 1;
+         Evas_GL_Image *im;
+      } array;
+   } pipe[MAX_PIPES];
+   
    struct {
       Eina_Bool size : 1;
    } change;
    
    Evas_GL_Image *def_surface;
+   
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+// FIXME: hack. expose egl display to gl core for egl image sec extn.   
+   void *egldisp;
+#endif   
 };
 
 struct _Evas_GL_Texture_Pool
@@ -178,10 +250,17 @@ struct _Evas_GL_Texture_Pool
    int              w, h;
    int              references;
    int              slot, fslot;
+   struct {
+      void         *img;
+      unsigned int *data;
+      int           w, h;
+      int           stride;
+   } dyn;
    Eina_List       *allocations;
    Eina_Bool        whole : 1;
    Eina_Bool        render : 1;
    Eina_Bool        native : 1;
+   Eina_Bool        dynamic : 1;
 };
 
 struct _Evas_GL_Texture
@@ -224,6 +303,8 @@ struct _Evas_GL_Image
       int           mipmap;
       unsigned char loose : 1;
    } native;
+
+   int scale_hint, content_hint;
    
    unsigned char    dirty : 1;
    unsigned char    cached : 1;
@@ -247,16 +328,6 @@ struct _Evas_GL_Polygon_Point
    int x, y;
 };
 
-/*
-struct _Evas_GL_Gradient
-{
-   RGBA_Gradient   *grad;
-   Evas_GL_Texture *tex;
-   int              tw, th;
-   unsigned char    changed : 1;
-};
-*/
-
 extern Evas_GL_Program_Source shader_rect_frag_src;
 extern Evas_GL_Program_Source shader_rect_vert_src;
 extern Evas_GL_Program_Source shader_font_frag_src;
@@ -334,6 +405,7 @@ void              evas_gl_common_rect_draw(Evas_GL_Context *gc, int x, int y, in
 Evas_GL_Texture  *evas_gl_common_texture_new(Evas_GL_Context *gc, RGBA_Image *im);
 Evas_GL_Texture  *evas_gl_common_texture_native_new(Evas_GL_Context *gc, int w, int h, int alpha, Evas_GL_Image *im);
 Evas_GL_Texture  *evas_gl_common_texture_render_new(Evas_GL_Context *gc, int w, int h, int alpha);
+Evas_GL_Texture  *evas_gl_common_texture_dynamic_new(Evas_GL_Context *gc, Evas_GL_Image *im);
 void              evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im);
 void              evas_gl_common_texture_free(Evas_GL_Texture *tex);
 Evas_GL_Texture  *evas_gl_common_texture_alpha_new(Evas_GL_Context *gc, DATA8 *pixels, int w, int h, int fh);
@@ -350,6 +422,8 @@ Evas_GL_Image    *evas_gl_common_image_new(Evas_GL_Context *gc, int w, int h, in
 Evas_GL_Image    *evas_gl_common_image_alpha_set(Evas_GL_Image *im, int alpha);
 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_free(Evas_GL_Image *im);
 Evas_GL_Image    *evas_gl_common_image_surface_new(Evas_GL_Context *gc, int w, int h, int alpha);
 void              evas_gl_common_image_dirty(Evas_GL_Image *im, int x, int y, int w, int h);
@@ -371,6 +445,15 @@ void (*glsym_glBindFramebuffer)      (GLenum a, GLuint b);
 void (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e);
 void (*glsym_glDeleteFramebuffers)   (GLsizei a, const GLuint *b);
 
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+void          *(*secsym_eglCreateImage)               (void *a, void *b, GLenum c, void *d, const int *e);
+unsigned int   (*secsym_eglDestroyImage)              (void *a, void *b);
+void           (*secsym_glEGLImageTargetTexture2DOES) (int a, void *b);
+void          *(*secsym_eglMapImageSEC)               (void *a, void *b);
+unsigned int   (*secsym_eglUnmapImageSEC)             (void *a, void *b);
+unsigned int   (*secsym_eglGetImageAttribSEC)         (void *a, void *b, int c, int *d);
+#endif
+
 #define GL_ERRORS 1
 
 #ifdef GL_ERRORS
index 098c8b3..fb12e59 100644 (file)
@@ -1,5 +1,7 @@
 #include "evas_gl_private.h"
 
+#define GLPIPES 1
+
 static int sym_done = 0;
 
 void (*glsym_glGenFramebuffers)      (GLsizei a, GLuint *b) = NULL;
@@ -7,6 +9,19 @@ void (*glsym_glBindFramebuffer)      (GLenum a, GLuint b) = NULL;
 void (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e) = NULL;
 void (*glsym_glDeleteFramebuffers)   (GLsizei a, const GLuint *b) = NULL;
 
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+// just used for finding symbols :)
+typedef void (*_eng_fn) (void);
+static _eng_fn  (*secsym_eglGetProcAddress)          (const char *a) = NULL;
+
+void          *(*secsym_eglCreateImage)               (void *a, void *b, GLenum c, void *d, const int *e) = NULL;
+unsigned int   (*secsym_eglDestroyImage)              (void *a, void *b) = NULL;
+void           (*secsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL;
+void          *(*secsym_eglMapImageSEC)               (void *a, void *b) = NULL;
+unsigned int   (*secsym_eglUnmapImageSEC)             (void *a, void *b) = NULL;
+unsigned int   (*secsym_eglGetImageAttribSEC)         (void *a, void *b, int c, int *d) = NULL;
+#endif
+
 static void
 sym_missing(void)
 {
@@ -45,6 +60,44 @@ gl_symbols(void)
    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersEXT");
    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersARB");
    FALLBAK(glsym_glDeleteFramebuffers);
+
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+#undef FINDSYM
+#define FINDSYM(dst, sym) \
+   if ((!dst) && (secsym_eglGetProcAddress)) dst = secsym_eglGetProcAddress(sym); \
+   if (!dst) dst = dlsym(RTLD_DEFAULT, sym)
+// yes - gl core looking for egl stuff. i know it's odd. a reverse-layer thing
+// but it will work as the egl/glx layer calls gl core common stuff and thus
+// these symbols will work. making the glx/egl + x11 layer do this kind-of is
+// wrong as this is not x11 (output) layer specific like the native surface
+// stuff. this is generic zero-copy textures for gl
+
+   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddress");
+   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressEXT");
+   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressARB");
+   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressKHR");
+   
+   FINDSYM(secsym_eglCreateImage, "eglCreateImage");
+   FINDSYM(secsym_eglCreateImage, "eglCreateImageEXT");
+   FINDSYM(secsym_eglCreateImage, "eglCreateImageARB");
+   FINDSYM(secsym_eglCreateImage, "eglCreateImageKHR");
+   
+   FINDSYM(secsym_eglDestroyImage, "eglDestroyImage");
+   FINDSYM(secsym_eglDestroyImage, "eglDestroyImageEXT");
+   FINDSYM(secsym_eglDestroyImage, "eglDestroyImageARB");
+   FINDSYM(secsym_eglDestroyImage, "eglDestroyImageKHR");
+   
+   FINDSYM(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES");
+   
+   FINDSYM(secsym_eglMapImageSEC, "eglMapImageSEC");
+//   FALLBAK(secsym_eglMapImageSEC);
+   
+   FINDSYM(secsym_eglUnmapImageSEC, "eglUnmapImageSEC");
+//   FALLBAK(secsym_eglUnmapImageSEC);
+   
+   FINDSYM(secsym_eglGetImageAttribSEC, "eglGetImageAttribSEC");
+//   FALLBAK(secsym_eglGetImageAttribSEC);
+#endif   
 }
 
 static void shader_array_flush(Evas_GL_Context *gc);
@@ -253,8 +306,9 @@ _evas_gl_common_viewport_set(Evas_GL_Context *gc)
    GLfloat proj[16];
    int w = 1, h = 1, m = 1, rot = 1;
 
-   if ((gc->shader.surface == gc->def_surface) ||
-       (!gc->shader.surface))
+   // surface in pipe 0 will be the same as all pipes
+   if ((gc->pipe[0].shader.surface == gc->def_surface) ||
+       (!gc->pipe[0].shader.surface))
      {
         w = gc->w;
         h = gc->h;
@@ -262,15 +316,16 @@ _evas_gl_common_viewport_set(Evas_GL_Context *gc)
      }
    else
      {
-        w = gc->shader.surface->w;
-        h = gc->shader.surface->h;
+        w = gc->pipe[0].shader.surface->w;
+        h = gc->pipe[0].shader.surface->h;
         rot = 0;
         m = -1;
      }
 
    if ((!gc->change.size) || 
-       ((gc->shared->w == w) && (gc->shared->h == h) && (gc->shared->rot == rot)))
-     return;
+       ((gc->shared->w == w) && (gc->shared->h == h) &&
+           (gc->shared->rot == rot)))
+      return;
    
    gc->shared->w = w;
    gc->shared->h = h;
@@ -342,7 +397,7 @@ _evas_gl_common_viewport_set(Evas_GL_Context *gc)
                       GL_FALSE, proj);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
 
-   glUseProgram(gc->shader.cur_prog);
+   glUseProgram(gc->pipe[0].shader.cur_prog);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
 }
 
@@ -350,6 +405,8 @@ Evas_GL_Context *
 evas_gl_common_context_new(void)
 {
    Evas_GL_Context *gc;
+   const char *s;
+   int i;
 
 #if 1
    if (_evas_gl_common_context)
@@ -368,13 +425,12 @@ evas_gl_common_context_new(void)
    gc->references = 1;
    
    _evas_gl_common_context = gc;
-
-   gc->shader.render_op = EVAS_RENDER_BLEND;
+   
+   for (i = 0; i < MAX_PIPES; i++)
+      gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND;
    
    if (!shared)
      {
-        GLint linked;
-        unsigned int pixel = 0xffffffff;
         const GLubyte *ext;
 
         shared = calloc(1, sizeof(Evas_GL_Shared));
@@ -382,23 +438,42 @@ evas_gl_common_context_new(void)
         if (ext)
           {
              fprintf(stderr, "EXT:\n%s\n", ext);
-             if ((strstr((char*) ext, "GL_ARB_texture_non_power_of_two")) ||
-                 (strstr((char*) ext, "OES_texture_npot")) ||
-                 (strstr((char*) ext, "GL_IMG_texture_npot")))
+             if ((strstr((char *)ext, "GL_ARB_texture_non_power_of_two")) ||
+                 (strstr((char *)ext, "OES_texture_npot")) ||
+                 (strstr((char *)ext, "GL_IMG_texture_npot")))
                shared->info.tex_npo2 = 1;
-             if ((strstr((char*) ext, "GL_NV_texture_rectangle")) ||
-                 (strstr((char*) ext, "GL_EXT_texture_rectangle")) ||
-                 (strstr((char*) ext, "GL_ARB_texture_rectangle")))
+             if ((strstr((char *)ext, "GL_NV_texture_rectangle")) ||
+                 (strstr((char *)ext, "GL_EXT_texture_rectangle")) ||
+                 (strstr((char *)ext, "GL_ARB_texture_rectangle")))
                shared->info.tex_rect = 1;
 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
-             if ((strstr((char*) ext, "GL_EXT_texture_filter_anisotropic")))
+             if ((strstr((char *)ext, "GL_EXT_texture_filter_anisotropic")))
                glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, 
                            &(shared->info.anisotropic));
 #endif
 #ifdef GL_BGRA
-             if ((strstr((char*) ext, "GL_EXT_bgra")) ||
-                 (strstr((char*) ext, "GL_EXT_texture_format_BGRA8888")))
+             if ((strstr((char *)ext, "GL_EXT_bgra")) ||
+                 (strstr((char *)ext, "GL_EXT_texture_format_BGRA8888")))
                shared->info.bgra = 1;
+#endif
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+             // FIXME: there should be an extension name/string to check for
+             // not just symbols in the lib
+             i = 0;
+             if (getenv("EVAS_GL_NO_MAP_IMAGE_SEC"))
+                i = atoi(getenv("EVAS_GL_NO_MAP_IMAGE_SEC"));
+             if (!i)
+               {
+                  // test for all needed symbols - be "conservative" and
+                  // need all of it
+                  if ((secsym_eglCreateImage) &&
+                      (secsym_eglDestroyImage) &&
+                      (secsym_glEGLImageTargetTexture2DOES) &&
+                      (secsym_eglMapImageSEC) &&
+                      (secsym_eglUnmapImageSEC) &&
+                      (secsym_eglGetImageAttribSEC))
+                     shared->info.sec_image_map = 1;
+               }
 #endif             
           }
         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,
@@ -406,19 +481,54 @@ evas_gl_common_context_new(void)
         glGetIntegerv(GL_MAX_TEXTURE_SIZE,
                       &(shared->info.max_texture_size));
         
-        fprintf(stderr, "max tex size %ix%i\n"
+        // magic numbers that are a result of imperical testing and getting
+        // "best case" performance across a range of systems
+        shared->info.cutout_max = 512;
+        shared->info.pipes_max = 32;
+        
+        // per gpu hacks. based on impirical measurement of some known gpu's
+        s = (const char *)glGetString(GL_RENDERER);
+        if (s)
+          {
+             if      (strstr(s, "PowerVR SGX 540"))
+                shared->info.pipes_max = 32;
+             else if (strstr(s, "NVIDIA Tegra"))
+                shared->info.pipes_max = 1;
+          }
+        
+        if (getenv("EVAS_GL_CUTOUT_MAX"))
+           shared->info.cutout_max = atoi(getenv("EVAS_GL_CUTOUT_MAX"));
+        if (getenv("EVAS_GL_PIPES_MAX"))
+          {
+             shared->info.pipes_max = atoi(getenv("EVAS_GL_PIPES_MAX"));
+             if (shared->info.pipes_max > MAX_PIPES)
+                shared->info.pipes_max = MAX_PIPES;
+             else if (shared->info.pipes_max < 1)
+                shared->info.pipes_max = 1;
+          }
+        
+        fprintf(stderr,
+                "max tex size %ix%i\n"
                 "max units %i\n"
                 "non-power-2 tex %i\n"
                 "rect tex %i\n"
                 "bgra : %i\n"
                 "max ansiotropic filtering: %3.3f\n"
+                "egl sec map image: %i\n"
+                "\n"
+                "cutout max: %i\n"
+                "pipes max: %i\n"
                 , 
-                shared->info.max_texture_size, shared->info.max_texture_size,
-                shared->info.max_texture_units,
+                (int)shared->info.max_texture_size, (int)shared->info.max_texture_size,
+                (int)shared->info.max_texture_units,
                 (int)shared->info.tex_npo2,
                 (int)shared->info.tex_rect,
                 (int)shared->info.bgra,
-                (double)shared->info.anisotropic
+                (double)shared->info.anisotropic,
+                (int)shared->info.sec_image_map,
+                
+                (int)shared->info.cutout_max,
+                (int)shared->info.pipes_max
                 );
         
         glDisable(GL_DEPTH_TEST);
@@ -515,7 +625,7 @@ evas_gl_common_context_new(void)
         glUniform1i(glGetUniformLocation(shared->shader.yuv_nomul.prog, "texv"), 2);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
         
-        glUseProgram(gc->shader.cur_prog);
+        glUseProgram(gc->pipe[0].shader.cur_prog);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
         // in shader:
         // uniform sampler2D tex[8];
@@ -524,6 +634,8 @@ evas_gl_common_context_new(void)
         // GLuint texes[8];
         // GLint loc = glGetUniformLocation(prog, "tex");
         // glUniform1iv(loc, 8, texes);
+
+        shared->native_hash = eina_hash_int32_new(NULL);
      }
    gc->shared = shared;
    gc->shared->references++;
@@ -581,16 +693,20 @@ evas_gl_common_context_free(Evas_GL_Context *gc)
                     }
                }
           }
+        eina_hash_free(gc->shared->native_hash);
         free(gc->shared);
         shared = NULL;
      }
    
 
-   if (gc->array.vertex) free(gc->array.vertex);
-   if (gc->array.color) free(gc->array.color);
-   if (gc->array.texuv) free(gc->array.texuv);
-   if (gc->array.texuv2) free(gc->array.texuv2);
-   if (gc->array.texuv3) free(gc->array.texuv3);
+   for (i = 0; i < gc->shared->info.pipes_max; i++)
+     {
+        if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex);
+        if (gc->pipe[i].array.color) free(gc->pipe[i].array.color);
+        if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv);
+        if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2);
+        if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3);
+     }
    
    if (gc == _evas_gl_common_context) _evas_gl_common_context = NULL;
    free(gc);
@@ -607,36 +723,60 @@ evas_gl_common_context_use(Evas_GL_Context *gc)
 void
 evas_gl_common_context_newframe(Evas_GL_Context *gc)
 {
-   gc->clip.x = 0;
-   gc->clip.y = 0;
-   gc->clip.w = 0;
-   gc->clip.h = 0;
-   gc->clip.active = 0;
-   gc->shader.surface = NULL;
-   gc->shader.cur_prog = 0;
-   gc->shader.cur_tex = 0;
-   gc->shader.cur_texu = 0;
-   gc->shader.cur_texv = 0;
-   gc->shader.render_op = EVAS_RENDER_BLEND;
-   gc->shader.cx = 0;
-   gc->shader.cy = 0;
-   gc->shader.cw = 0;
-   gc->shader.ch = 0;
-   gc->shader.smooth = 0;
-   gc->shader.blend = 0;
-   gc->shader.clip = 0;
-   gc->shader.current.cur_prog = 0;
-   gc->shader.current.cur_tex = 0;
-   gc->shader.current.cur_texu = 0;
-   gc->shader.current.cur_texv = 0;
-   gc->shader.current.render_op = 0;
-   gc->shader.current.cx = 0;
-   gc->shader.current.cy = 0;
-   gc->shader.current.cw = 0;
-   gc->shader.current.ch = 0;
-   gc->shader.current.smooth = 0;
-   gc->shader.current.blend = 0;
-   gc->shader.current.clip = 0;
+   int i;
+   static int dbgflushnum = -1;
+
+   if (dbgflushnum < 0)
+     {
+        dbgflushnum = 0;
+        if (getenv("DBGEVAS")) dbgflushnum = 1;
+     }
+   if (dbgflushnum) printf("prev-flushnum: %i\n", gc->flushnum);
+   
+   gc->flushnum = 0;
+   gc->state.current.cur_prog = 0;
+   gc->state.current.cur_tex = 0;
+   gc->state.current.cur_texu = 0;
+   gc->state.current.cur_texv = 0;
+   gc->state.current.render_op = 0;
+   gc->state.current.cx = 0;
+   gc->state.current.cy = 0;
+   gc->state.current.cw = 0;
+   gc->state.current.ch = 0;
+   gc->state.current.smooth = 0;
+   gc->state.current.blend = 0;
+   gc->state.current.clip = 0;
+   gc->state.current.cx = 0;
+   gc->state.current.cy = 0;
+   gc->state.current.cw = 0;
+   gc->state.current.ch = 0;
+   
+   for (i = 0; i < gc->shared->info.pipes_max; i++)
+     {
+        gc->pipe[i].region.x = 0;
+        gc->pipe[i].region.y = 0;
+        gc->pipe[i].region.w = 0;
+        gc->pipe[i].region.h = 0;
+        gc->pipe[i].region.type = 0;
+        gc->pipe[i].clip.active = 0;
+        gc->pipe[i].clip.x = 0;
+        gc->pipe[i].clip.y = 0;
+        gc->pipe[i].clip.w = 0;
+        gc->pipe[i].clip.h = 0;
+        gc->pipe[i].shader.surface = NULL;
+        gc->pipe[i].shader.cur_prog = 0;
+        gc->pipe[i].shader.cur_tex = 0;
+        gc->pipe[i].shader.cur_texu = 0;
+        gc->pipe[i].shader.cur_texv = 0;
+        gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND;
+        gc->pipe[i].shader.smooth = 0;
+        gc->pipe[i].shader.blend = 0;
+        gc->pipe[i].shader.clip = 0;
+        gc->pipe[i].shader.cx = 0;
+        gc->pipe[i].shader.cy = 0;
+        gc->pipe[i].shader.cw = 0;
+        gc->pipe[i].shader.ch = 0;
+     }
    gc->change.size = 1;
    
    glDisable(GL_SCISSOR_TEST);
@@ -678,12 +818,12 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc)
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    glEnableVertexAttribArray(SHAD_COLOR);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUseProgram(gc->shader.cur_prog);
+   glUseProgram(gc->pipe[0].shader.cur_prog);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    
    glActiveTexture(GL_TEXTURE0);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex);
+   glBindTexture(GL_TEXTURE_2D, gc->pipe[0].shader.cur_tex);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
 
    _evas_gl_common_viewport_set(gc);
@@ -704,11 +844,11 @@ void
 evas_gl_common_context_target_surface_set(Evas_GL_Context *gc,
                                           Evas_GL_Image *surface)
 {
-   if (surface == gc->shader.surface) return;
+   if (surface == gc->pipe[0].shader.surface) return;
    
    evas_gl_common_context_flush(gc);
 
-   gc->shader.surface = surface;
+   gc->pipe[0].shader.surface = surface;
    gc->change.size = 1;
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
 # ifndef GL_FRAMEBUFFER
@@ -719,7 +859,7 @@ evas_gl_common_context_target_surface_set(Evas_GL_Context *gc,
 #  define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
 # endif   
 #endif   
-   if (gc->shader.surface == gc->def_surface)
+   if (gc->pipe[0].shader.surface == gc->def_surface)
      {
         glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
@@ -732,45 +872,112 @@ evas_gl_common_context_target_surface_set(Evas_GL_Context *gc,
    _evas_gl_common_viewport_set(gc);
 }
 
-#define PUSH_VERTEX(x, y, z) \
-   gc->array.vertex[nv++] = x; \
-   gc->array.vertex[nv++] = y; \
-   gc->array.vertex[nv++] = z
-#define PUSH_COLOR(r, g, b, a) \
-   gc->array.color[nc++] = r; \
-   gc->array.color[nc++] = g; \
-   gc->array.color[nc++] = b; \
-   gc->array.color[nc++] = a
-#define PUSH_TEXUV(u, v) \
-   gc->array.texuv[nu++] = u; \
-   gc->array.texuv[nu++] = v
-#define PUSH_TEXUV2(u, v) \
-   gc->array.texuv2[nu2++] = u; \
-   gc->array.texuv2[nu2++] = v
-#define PUSH_TEXUV3(u, v) \
-   gc->array.texuv3[nu3++] = u; \
-   gc->array.texuv3[nu3++] = v
+#define PUSH_VERTEX(n, x, y, z) \
+   gc->pipe[n].array.vertex[nv++] = x; \
+   gc->pipe[n].array.vertex[nv++] = y; \
+   gc->pipe[n].array.vertex[nv++] = z
+#define PUSH_COLOR(n, r, g, b, a) \
+   gc->pipe[n].array.color[nc++] = r; \
+   gc->pipe[n].array.color[nc++] = g; \
+   gc->pipe[n].array.color[nc++] = b; \
+   gc->pipe[n].array.color[nc++] = a
+#define PUSH_TEXUV(n, u, v) \
+   gc->pipe[n].array.texuv[nu++] = u; \
+   gc->pipe[n].array.texuv[nu++] = v
+#define PUSH_TEXUV2(n, u, v) \
+   gc->pipe[n].array.texuv2[nu2++] = u; \
+   gc->pipe[n].array.texuv2[nu2++] = v
+#define PUSH_TEXUV3(n, u, v) \
+   gc->pipe[n].array.texuv3[nu3++] = u; \
+   gc->pipe[n].array.texuv3[nu3++] = v
 
 static inline void
-_evas_gl_common_context_array_alloc(Evas_GL_Context *gc)
+array_alloc(Evas_GL_Context *gc, int n)
+{
+   if (gc->pipe[n].array.num <= gc->pipe[n].array.alloc) return;
+   gc->pipe[n].array.alloc += 6 * 1024;
+   if (gc->pipe[n].array.use_vertex)
+     gc->pipe[n].array.vertex = realloc(gc->pipe[n].array.vertex,
+                                gc->pipe[n].array.alloc * sizeof(GLshort) * 3);
+   if (gc->pipe[n].array.use_color)
+     gc->pipe[n].array.color  = realloc(gc->pipe[n].array.color,
+                                gc->pipe[n].array.alloc * sizeof(GLubyte) * 4);
+   if (gc->pipe[n].array.use_texuv)
+     gc->pipe[n].array.texuv  = realloc(gc->pipe[n].array.texuv,
+                                gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
+   if (gc->pipe[n].array.use_texuv2)
+     gc->pipe[n].array.texuv2  = realloc(gc->pipe[n].array.texuv2,
+                               gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
+   if (gc->pipe[n].array.use_texuv3)
+     gc->pipe[n].array.texuv3  = realloc(gc->pipe[n].array.texuv3,
+                                 gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
+}
+
+static int
+pipe_region_intersects(Evas_GL_Context *gc, int n,
+                       int x, int y, int w, int h)
+{
+   int i, rx, ry, rw, rh, ii;
+   
+   rx = gc->pipe[n].region.x;
+   ry = gc->pipe[n].region.y;
+   rw = gc->pipe[n].region.w;
+   rh = gc->pipe[n].region.h;
+   if (!RECTS_INTERSECT(x, y, w, h, rx, ry, rw, rh))
+      return 0;
+   
+   // a hack for now. map pipes use their whole bounding box for intersects
+   // which at worst case reduces to old pipeline flushes, but cheaper than
+   // full quad region or triangle intersects right now
+   if (gc->pipe[n].region.type == RTYPE_MAP) return 1;
+   
+   for (i = 0, 
+        ii = 0; 
+        
+        i < gc->pipe[n].array.num; 
+        
+        i += (3 * 2), 
+        ii += (3 * 3 * 2))
+     {  // tri 1...
+        // 0, 1, 2 < top left
+        // 3, 4, 5 < top right
+        // 6. 7, 8 < bottom left
+        rx = gc->pipe[n].array.vertex[ii + 0];
+        ry = gc->pipe[n].array.vertex[ii + 1];
+        rw = gc->pipe[n].array.vertex[ii + 3] - rx;
+        rh = gc->pipe[n].array.vertex[ii + 7] - ry;
+        if (RECTS_INTERSECT(x, y, w, h, rx, ry, rw, rh))
+           return 1;
+     }
+   return 0;
+}
+
+static void
+pipe_region_expand(Evas_GL_Context *gc, int n,
+                   int x, int y, int w, int h)
 {
-   if (gc->array.num <= gc->array.alloc) return;
-   gc->array.alloc += 6 * 1024;
-   if (gc->array.use_vertex)
-     gc->array.vertex = realloc(gc->array.vertex,
-                                gc->array.alloc * sizeof(GLshort) * 3);
-   if (gc->array.use_color)
-     gc->array.color  = realloc(gc->array.color,
-                                gc->array.alloc * sizeof(GLubyte) * 4);
-   if (gc->array.use_texuv)
-     gc->array.texuv  = realloc(gc->array.texuv,
-                                gc->array.alloc * sizeof(GLfloat) * 2);
-   if (gc->array.use_texuv2)
-     gc->array.texuv2  = realloc(gc->array.texuv2,
-                               gc->array.alloc * sizeof(GLfloat) * 2);
-   if (gc->array.use_texuv3)
-     gc->array.texuv3  = realloc(gc->array.texuv3,
-                                 gc->array.alloc * sizeof(GLfloat) * 2);
+   int x1, y1, x2, y2;
+   
+   if (gc->pipe[n].region.w <= 0)
+     {
+        gc->pipe[n].region.x = x;
+        gc->pipe[n].region.y = y;
+        gc->pipe[n].region.w = w;
+        gc->pipe[n].region.h = h;
+        return;
+     }
+   x1 = gc->pipe[n].region.x;
+   y1 = gc->pipe[n].region.y;
+   x2 = gc->pipe[n].region.x + gc->pipe[n].region.w;
+   y2 = gc->pipe[n].region.y + gc->pipe[n].region.h;
+   if (x < x1) x1 = x;
+   if (y < y1) y1 = y;
+   if ((x + w) > x2) x2 = x + w;
+   if ((y + h) > y2) y2 = y + h;
+   gc->pipe[n].region.x = x1;
+   gc->pipe[n].region.y = y1;
+   gc->pipe[n].region.w = x2 - x1;
+   gc->pipe[n].region.h = y2 - y1;
 }
 
 void
@@ -782,48 +989,50 @@ evas_gl_common_context_line_push(Evas_GL_Context *gc,
    int pnum, nv, nc, nu, nt, i;
    Eina_Bool blend = 0;
    GLuint prog = gc->shared->shader.rect.prog;
-   
-   shader_array_flush(gc);
+   int pn = 0;
    
    if (a < 255) blend = 1;
    if (gc->dc->render_op == EVAS_RENDER_COPY) blend = 0;
-   gc->shader.cur_tex = 0;
-   gc->shader.cur_prog = prog;
-   gc->shader.blend = blend;
-   gc->shader.render_op = gc->dc->render_op;
-   gc->shader.clip = clip;
-   gc->shader.cx = cx;
-   gc->shader.cy = cy;
-   gc->shader.cw = cw;
-   gc->shader.ch = ch;
-   
-   gc->array.line = 1;
-   gc->array.use_vertex = 1;
-   gc->array.use_color = 1;
-   gc->array.use_texuv = 0;
-   gc->array.use_texuv2 = 0;
-   gc->array.use_texuv3 = 0;
-   
-   pnum = gc->array.num;
+   
+   shader_array_flush(gc);
+   pn = gc->state.top_pipe;
+   gc->pipe[pn].shader.cur_tex = 0;
+   gc->pipe[pn].shader.cur_prog = prog;
+   gc->pipe[pn].shader.blend = blend;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = clip;
+   gc->pipe[pn].shader.cx = cx;
+   gc->pipe[pn].shader.cy = cy;
+   gc->pipe[pn].shader.cw = cw;
+   gc->pipe[pn].shader.ch = ch;
+   
+   gc->pipe[pn].array.line = 1;
+   gc->pipe[pn].array.use_vertex = 1;
+   gc->pipe[pn].array.use_color = 1;
+   gc->pipe[pn].array.use_texuv = 0;
+   gc->pipe[pn].array.use_texuv2 = 0;
+   gc->pipe[pn].array.use_texuv3 = 0;
+   
+   pnum = gc->pipe[pn].array.num;
    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
-   gc->array.num += 1;
-   _evas_gl_common_context_array_alloc(gc);
+   gc->pipe[pn].array.num += 1;
+   array_alloc(gc, pn);
   
-   PUSH_VERTEX(x1, y1, 0);
-   PUSH_VERTEX(x2, y2, 0);
+   PUSH_VERTEX(pn, x1, y1, 0);
+   PUSH_VERTEX(pn, x2, y2, 0);
    
    for (i = 0; i < 2; i++)
      {
-        PUSH_COLOR(r, g, b, a);
+        PUSH_COLOR(pn, r, g, b, a);
      }
    
    shader_array_flush(gc);
-   gc->array.line = 0;
-   gc->array.use_vertex = 0;
-   gc->array.use_color = 0;
-   gc->array.use_texuv = 0;
-   gc->array.use_texuv2 = 0;
-   gc->array.use_texuv3 = 0;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 0;
+   gc->pipe[pn].array.use_color = 0;
+   gc->pipe[pn].array.use_texuv = 0;
+   gc->pipe[pn].array.use_texuv2 = 0;
+   gc->pipe[pn].array.use_texuv3 = 0;
 }
 
 void
@@ -834,48 +1043,128 @@ evas_gl_common_context_rectangle_push(Evas_GL_Context *gc,
    int pnum, nv, nc, nu, nt, i;
    Eina_Bool blend = 0;
    GLuint prog = gc->shared->shader.rect.prog;
+   int pn = 0;
    
    if (a < 255) blend = 1;
    if (gc->dc->render_op == EVAS_RENDER_COPY) blend = 0;
    
-   if ((gc->shader.cur_tex != 0)
-       || (gc->shader.cur_prog != prog)
-       || (gc->shader.blend != blend)
-       || (gc->shader.render_op != gc->dc->render_op)
-       || (gc->shader.clip != 0)
+again:
+   pn = gc->state.top_pipe;
+#ifdef GLPIPES
+   if ((pn == 0) && (gc->pipe[pn].array.num == 0))
+     {
+        gc->pipe[pn].region.type = RTYPE_RECT;
+        gc->pipe[pn].shader.cur_tex = 0;
+        gc->pipe[pn].shader.cur_prog = prog;
+        gc->pipe[pn].shader.blend = blend;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = 0;
+        gc->pipe[pn].shader.cx = 0;
+        gc->pipe[pn].shader.cy = 0;
+        gc->pipe[pn].shader.cw = 0;
+        gc->pipe[pn].shader.ch = 0;
+        gc->pipe[pn].array.line = 0;
+        gc->pipe[pn].array.use_vertex = 1;
+        gc->pipe[pn].array.use_color = 1;
+        gc->pipe[pn].array.use_texuv = 0;
+        gc->pipe[pn].array.use_texuv2 = 0;
+        gc->pipe[pn].array.use_texuv3 = 0;
+     }
+   else
+     {
+        int found = 0;
+        
+        for (i = pn; i >= 0; i--)
+          {
+             if ((gc->pipe[i].region.type == RTYPE_RECT)
+                 && (gc->pipe[i].shader.cur_tex == 0)
+                 && (gc->pipe[i].shader.cur_prog == prog)
+                 && (gc->pipe[i].shader.blend == blend)
+                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
+                 && (gc->pipe[i].shader.clip == 0)
+                )
+               {
+                  found = 1;
+                  pn = i;
+                  break;
+               }
+             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
+          }
+        if (!found)
+          {
+             pn = gc->state.top_pipe + 1;
+             if (pn >= gc->shared->info.pipes_max)
+               {
+                  shader_array_flush(gc);
+                  goto again;
+               }
+             gc->state.top_pipe = pn;
+             gc->pipe[pn].region.type = RTYPE_RECT;
+             gc->pipe[pn].shader.cur_tex = 0;
+             gc->pipe[pn].shader.cur_prog = prog;
+             gc->pipe[pn].shader.blend = blend;
+             gc->pipe[pn].shader.render_op = gc->dc->render_op;
+             gc->pipe[pn].shader.clip = 0;
+             gc->pipe[pn].shader.cx = 0;
+             gc->pipe[pn].shader.cy = 0;
+             gc->pipe[pn].shader.cw = 0;
+             gc->pipe[pn].shader.ch = 0;
+             gc->pipe[pn].array.line = 0;
+             gc->pipe[pn].array.use_vertex = 1;
+             gc->pipe[pn].array.use_color = 1;
+             gc->pipe[pn].array.use_texuv = 0;
+             gc->pipe[pn].array.use_texuv2 = 0;
+             gc->pipe[pn].array.use_texuv3 = 0;
+         }
+     }
+#else   
+   if ((gc->pipe[pn].shader.cur_tex != 0)
+       || (gc->pipe[pn].shader.cur_prog != prog)
+       || (gc->pipe[pn].shader.blend != blend)
+       || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
+       || (gc->pipe[pn].shader.clip != 0)
        )
      {
         shader_array_flush(gc);
-        gc->shader.cur_tex = 0;
-        gc->shader.cur_prog = prog;
-        gc->shader.blend = blend;
-        gc->shader.render_op = gc->dc->render_op;
-        gc->shader.clip = 0;
-
+        pn = gc->state.top_pipe;
+        gc->pipe[pn].shader.cur_tex = 0;
+        gc->pipe[pn].shader.cur_prog = prog;
+        gc->pipe[pn].shader.blend = blend;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = 0;
+        gc->pipe[pn].shader.cx = 0;
+        gc->pipe[pn].shader.cy = 0;
+        gc->pipe[pn].shader.cw = 0;
+        gc->pipe[pn].shader.ch = 0;
      }
-   gc->array.line = 0;
-   gc->array.use_vertex = 1;
-   gc->array.use_color = 1;
-   gc->array.use_texuv = 0;
-   gc->array.use_texuv2 = 0;
-   gc->array.use_texuv3 = 0;
-   
-   pnum = gc->array.num;
+   
+   gc->pipe[pn].region.type = RTYPE_RECT;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 1;
+   gc->pipe[pn].array.use_color = 1;
+   gc->pipe[pn].array.use_texuv = 0;
+   gc->pipe[pn].array.use_texuv2 = 0;
+   gc->pipe[pn].array.use_texuv3 = 0;
+#endif
+   
+   pipe_region_expand(gc, pn, x, y, w, h);
+   
+   pnum = gc->pipe[pn].array.num;
    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
-   gc->array.num += 6;
-   _evas_gl_common_context_array_alloc(gc);
+   gc->pipe[pn].array.num += 6;
+   array_alloc(gc, pn);
   
-   PUSH_VERTEX(x    , y    , 0);
-   PUSH_VERTEX(x + w, y    , 0);
-   PUSH_VERTEX(x    , y + h, 0);
+   PUSH_VERTEX(pn, x    , y    , 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
    
-   PUSH_VERTEX(x + w, y    , 0);
-   PUSH_VERTEX(x + w, y + h, 0);
-   PUSH_VERTEX(x    , y + h, 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x + w, y + h, 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
    
    for (i = 0; i < 6; i++)
      {
-        PUSH_COLOR(r, g, b, a);
+        PUSH_COLOR(pn, r, g, b, a);
      }
 }
 
@@ -891,16 +1180,27 @@ evas_gl_common_context_image_push(Evas_GL_Context *gc,
    GLfloat tx1, tx2, ty1, ty2;
    Eina_Bool blend = 1;
    GLuint prog = gc->shared->shader.img.prog;
+   int pn = 0;
 
    if (!tex->alpha) blend = 0;
    if (a < 255) blend = 1;
    
    if (tex_only)
      {
-        if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-          prog = gc->shared->shader.tex_nomul.prog;
+        if (tex->pt->dyn.img)
+          {
+             if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
+                prog = gc->shared->shader.img_nomul.prog;
+             else
+                prog = gc->shared->shader.img.prog;
+          }
         else
-          prog = gc->shared->shader.tex.prog;
+          {
+             if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
+                prog = gc->shared->shader.tex_nomul.prog;
+             else
+                prog = gc->shared->shader.tex.prog;
+          }
      }
    else
      {
@@ -920,44 +1220,155 @@ evas_gl_common_context_image_push(Evas_GL_Context *gc,
           }
      }
 
-   if ((gc->shader.cur_tex != tex->pt->texture)
-       || (gc->shader.cur_prog != prog)
-       || (gc->shader.smooth != smooth)
-       || (gc->shader.blend != blend)
-       || (gc->shader.render_op != gc->dc->render_op)
-       || (gc->shader.clip != 0)
+again:
+   pn = gc->state.top_pipe;
+#ifdef GLPIPES
+   if ((pn == 0) && (gc->pipe[pn].array.num == 0))
+     {
+        gc->pipe[pn].region.type = RTYPE_IMAGE;
+        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+        gc->pipe[pn].shader.cur_prog = prog;
+        gc->pipe[pn].shader.smooth = smooth;
+        gc->pipe[pn].shader.blend = blend;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = 0;
+        gc->pipe[pn].shader.cx = 0;
+        gc->pipe[pn].shader.cy = 0;
+        gc->pipe[pn].shader.cw = 0;
+        gc->pipe[pn].shader.ch = 0;
+        gc->pipe[pn].array.line = 0;
+        gc->pipe[pn].array.use_vertex = 1;
+        // if nomul... dont need this
+        gc->pipe[pn].array.use_color = 1;
+        gc->pipe[pn].array.use_texuv = 1;
+        gc->pipe[pn].array.use_texuv2 = 0;
+        gc->pipe[pn].array.use_texuv3 = 0;
+     }
+   else
+     {
+        int found = 0;
+        
+        for (i = pn; i >= 0; i--)
+          {
+             if ((gc->pipe[i].region.type == RTYPE_IMAGE)
+                 && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
+                 && (gc->pipe[i].shader.cur_prog == prog)
+                 && (gc->pipe[i].shader.smooth == smooth)
+                 && (gc->pipe[i].shader.blend == blend)
+                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
+                 && (gc->pipe[i].shader.clip == 0)
+                )
+               {
+                  found = 1;
+                  pn = i;
+                  break;
+               }
+             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
+          }
+        if (!found)
+          {
+             pn = gc->state.top_pipe + 1;
+             if (pn >= gc->shared->info.pipes_max)
+               {
+                  shader_array_flush(gc);
+                  goto again;
+               }
+             gc->state.top_pipe = pn;
+             gc->pipe[pn].region.type = RTYPE_IMAGE;
+             gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+             gc->pipe[pn].shader.cur_prog = prog;
+             gc->pipe[pn].shader.smooth = smooth;
+             gc->pipe[pn].shader.blend = blend;
+             gc->pipe[pn].shader.render_op = gc->dc->render_op;
+             gc->pipe[pn].shader.clip = 0;
+             gc->pipe[pn].shader.cx = 0;
+             gc->pipe[pn].shader.cy = 0;
+             gc->pipe[pn].shader.cw = 0;
+             gc->pipe[pn].shader.ch = 0;
+             gc->pipe[pn].array.line = 0;
+             gc->pipe[pn].array.use_vertex = 1;
+             // if nomul... dont need this
+             gc->pipe[pn].array.use_color = 1;
+             gc->pipe[pn].array.use_texuv = 1;
+             gc->pipe[pn].array.use_texuv2 = 0;
+             gc->pipe[pn].array.use_texuv3 = 0;
+   
+         }
+     }
+   if ((tex->im) && (tex->im->native.data))
+     {
+        if (gc->pipe[pn].array.im != tex->im)
+          {
+             shader_array_flush(gc);
+             pn = gc->state.top_pipe;
+             gc->pipe[pn].array.im = tex->im;
+             goto again;
+          }
+     }
+   if (tex->pt->dyn.img)
+     {
+        if (gc->pipe[pn].array.im != tex->im)
+          {
+             shader_array_flush(gc);
+             pn = gc->state.top_pipe;
+             gc->pipe[pn].array.im = tex->im;
+             goto again;
+          }
+     }
+#else   
+   if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
+       || (gc->pipe[pn].shader.cur_prog != prog)
+       || (gc->pipe[pn].shader.smooth != smooth)
+       || (gc->pipe[pn].shader.blend != blend)
+       || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
+       || (gc->pipe[pn].shader.clip != 0)
        )
      {
         shader_array_flush(gc);
-        gc->shader.cur_tex = tex->pt->texture;
-        gc->shader.cur_prog = prog;
-        gc->shader.smooth = smooth;
-        gc->shader.blend = blend;
-        gc->shader.render_op = gc->dc->render_op;
-        gc->shader.clip = 0;
+        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+        gc->pipe[pn].shader.cur_prog = prog;
+        gc->pipe[pn].shader.smooth = smooth;
+        gc->pipe[pn].shader.blend = blend;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = 0;
+        gc->pipe[pn].shader.cx = 0;
+        gc->pipe[pn].shader.cy = 0;
+        gc->pipe[pn].shader.cw = 0;
+        gc->pipe[pn].shader.ch = 0;
      } 
    if ((tex->im) && (tex->im->native.data))
      {
-        if (gc->array.im != tex->im)
+        if (gc->pipe[pn].array.im != tex->im)
           {
              shader_array_flush(gc);
-             gc->array.im = tex->im;
+             gc->pipe[pn].array.im = tex->im;
           }
      }
-   
-   gc->array.line = 0;
-   gc->array.use_vertex = 1;
+   if (tex->pt->dyn.img)
+     {
+        if (gc->pipe[pn].array.im != tex->im)
+          {
+             shader_array_flush(gc);
+             gc->pipe[pn].array.im = tex->im;
+          }
+     }
+
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 1;
    // if nomul... dont need this
-   gc->array.use_color = 1;
-   gc->array.use_texuv = 1;
-   gc->array.use_texuv2 = 0;
-   gc->array.use_texuv3 = 0;
+   gc->pipe[pn].array.use_color = 1;
+   gc->pipe[pn].array.use_texuv = 1;
+   gc->pipe[pn].array.use_texuv2 = 0;
+   gc->pipe[pn].array.use_texuv3 = 0;
+#endif
+
+   pipe_region_expand(gc, pn, x, y, w, h);
   
-   pnum = gc->array.num;
+   pnum = gc->pipe[pn].array.num;
    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
    nt = pnum * 4;
-   gc->array.num += 6;
-   _evas_gl_common_context_array_alloc(gc);
+   gc->pipe[pn].array.num += 6;
+   array_alloc(gc, pn);
 
    if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
      {
@@ -974,26 +1385,26 @@ evas_gl_common_context_image_push(Evas_GL_Context *gc,
         ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
      }
 
-   PUSH_VERTEX(x    , y    , 0);
-   PUSH_VERTEX(x + w, y    , 0);
-   PUSH_VERTEX(x    , y + h, 0);
+   PUSH_VERTEX(pn, x    , y    , 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
    
-   PUSH_TEXUV(tx1, ty1);
-   PUSH_TEXUV(tx2, ty1);
-   PUSH_TEXUV(tx1, ty2);
+   PUSH_TEXUV(pn, tx1, ty1);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx1, ty2);
    
-   PUSH_VERTEX(x + w, y    , 0);
-   PUSH_VERTEX(x + w, y + h, 0);
-   PUSH_VERTEX(x    , y + h, 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x + w, y + h, 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
    
-   PUSH_TEXUV(tx2, ty1);
-   PUSH_TEXUV(tx2, ty2);
-   PUSH_TEXUV(tx1, ty2);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx2, ty2);
+   PUSH_TEXUV(pn, tx1, ty2);
 
    // if nomul... dont need this
    for (i = 0; i < 6; i++)
      {
-        PUSH_COLOR(r, g, b, a);
+        PUSH_COLOR(pn, r, g, b, a);
      }
 }
 
@@ -1006,34 +1417,117 @@ evas_gl_common_context_font_push(Evas_GL_Context *gc,
 {
    int pnum, nv, nc, nu, nt, i;
    GLfloat tx1, tx2, ty1, ty2;
+   int pn = 0;
 
-   if ((gc->shader.cur_tex != tex->pt->texture)
-       || (gc->shader.cur_prog != gc->shared->shader.font.prog)
-       || (gc->shader.smooth != 0)
-       || (gc->shader.blend != 1)
-       || (gc->shader.render_op != gc->dc->render_op)
-       || (gc->shader.clip != 0)
+again:
+   pn = gc->state.top_pipe;
+#ifdef GLPIPES
+   if ((pn == 0) && (gc->pipe[pn].array.num == 0))
+     {
+        gc->pipe[pn].region.type = RTYPE_FONT;
+        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+        gc->pipe[pn].shader.cur_prog = gc->shared->shader.font.prog;
+        gc->pipe[pn].shader.smooth = 0;
+        gc->pipe[pn].shader.blend = 1;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = 0;
+        gc->pipe[pn].shader.cx = 0;
+        gc->pipe[pn].shader.cy = 0;
+        gc->pipe[pn].shader.cw = 0;
+        gc->pipe[pn].shader.ch = 0;
+        gc->pipe[pn].array.line = 0;
+        gc->pipe[pn].array.use_vertex = 1;
+        gc->pipe[pn].array.use_color = 1;
+        gc->pipe[pn].array.use_texuv = 1;
+        gc->pipe[pn].array.use_texuv2 = 0;
+        gc->pipe[pn].array.use_texuv3 = 0;
+     }
+   else
+     {
+        int found = 0;
+        
+        for (i = pn; i >= 0; i--)
+          {
+             if ((gc->pipe[i].region.type == RTYPE_FONT)
+                 && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
+                 && (gc->pipe[i].shader.cur_prog == gc->shared->shader.font.prog)
+                 && (gc->pipe[i].shader.smooth == 0)
+                 && (gc->pipe[i].shader.blend == 1)
+                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
+                 && (gc->pipe[i].shader.clip == 0)
+                )
+               {
+                  found = 1;
+                  pn = i;
+                  break;
+               }
+             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
+          }
+        if (!found)
+          {
+             pn = gc->state.top_pipe + 1;
+             if (pn >= gc->shared->info.pipes_max)
+               {
+                  shader_array_flush(gc);
+                  goto again;
+               }
+             gc->state.top_pipe = pn;
+             gc->pipe[pn].region.type = RTYPE_FONT;
+             gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+             gc->pipe[pn].shader.cur_prog = gc->shared->shader.font.prog;
+             gc->pipe[pn].shader.smooth = 0;
+             gc->pipe[pn].shader.blend = 1;
+             gc->pipe[pn].shader.render_op = gc->dc->render_op;
+             gc->pipe[pn].shader.clip = 0;
+             gc->pipe[pn].shader.cx = 0;
+             gc->pipe[pn].shader.cy = 0;
+             gc->pipe[pn].shader.cw = 0;
+             gc->pipe[pn].shader.ch = 0;
+             gc->pipe[pn].array.line = 0;
+             gc->pipe[pn].array.use_vertex = 1;
+             gc->pipe[pn].array.use_color = 1;
+             gc->pipe[pn].array.use_texuv = 1;
+             gc->pipe[pn].array.use_texuv2 = 0;
+             gc->pipe[pn].array.use_texuv3 = 0;
+         }
+     }
+#else   
+   if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
+       || (gc->pipe[pn].shader.cur_prog != gc->shared->shader.font.prog)
+       || (gc->pipe[pn].shader.smooth != 0)
+       || (gc->pipe[pn].shader.blend != 1)
+       || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
+       || (gc->pipe[pn].shader.clip != 0)
        )
      {
         shader_array_flush(gc);
-        gc->shader.cur_tex = tex->pt->texture;
-        gc->shader.cur_prog = gc->shared->shader.font.prog;
-        gc->shader.smooth = 0;
-        gc->shader.blend = 1;
-        gc->shader.render_op = gc->dc->render_op;
-        gc->shader.clip = 0;
+        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+        gc->pipe[pn].shader.cur_prog = gc->shared->shader.font.prog;
+        gc->pipe[pn].shader.smooth = 0;
+        gc->pipe[pn].shader.blend = 1;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = 0;
+        gc->pipe[pn].shader.cx = 0;
+        gc->pipe[pn].shader.cy = 0;
+        gc->pipe[pn].shader.cw = 0;
+        gc->pipe[pn].shader.ch = 0;
      }
-   gc->array.line = 0;
-   gc->array.use_vertex = 1;
-   gc->array.use_color = 1;
-   gc->array.use_texuv = 1;
-   gc->array.use_texuv2 = 0;
-   gc->array.use_texuv3 = 0;
-   
-   pnum = gc->array.num;
+
+   gc->pipe[pn].region.type = RTYPE_FONT;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 1;
+   gc->pipe[pn].array.use_color = 1;
+   gc->pipe[pn].array.use_texuv = 1;
+   gc->pipe[pn].array.use_texuv2 = 0;
+   gc->pipe[pn].array.use_texuv3 = 0;
+#endif
+   
+   pipe_region_expand(gc, pn, x, y, w, h);
+   
+   pnum = gc->pipe[pn].array.num;
    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
-   gc->array.num += 6;
-   _evas_gl_common_context_array_alloc(gc);
+   gc->pipe[pn].array.num += 6;
+   array_alloc(gc, pn);
 
    if (sw == 0.0)
      {
@@ -1050,25 +1544,25 @@ evas_gl_common_context_font_push(Evas_GL_Context *gc,
         ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
      }
    
-   PUSH_VERTEX(x    , y    , 0);
-   PUSH_VERTEX(x + w, y    , 0);
-   PUSH_VERTEX(x    , y + h, 0);
+   PUSH_VERTEX(pn, x    , y    , 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
    
-   PUSH_TEXUV(tx1, ty1);
-   PUSH_TEXUV(tx2, ty1);
-   PUSH_TEXUV(tx1, ty2);
+   PUSH_TEXUV(pn, tx1, ty1);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx1, ty2);
    
-   PUSH_VERTEX(x + w, y    , 0);
-   PUSH_VERTEX(x + w, y + h, 0);
-   PUSH_VERTEX(x    , y + h, 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x + w, y + h, 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
    
-   PUSH_TEXUV(tx2, ty1);
-   PUSH_TEXUV(tx2, ty2);
-   PUSH_TEXUV(tx1, ty2);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx2, ty2);
+   PUSH_TEXUV(pn, tx1, ty2);
 
    for (i = 0; i < 6; i++)
      {
-        PUSH_COLOR(r, g, b, a);
+        PUSH_COLOR(pn, r, g, b, a);
      }
 }
 
@@ -1084,6 +1578,7 @@ evas_gl_common_context_yuv_push(Evas_GL_Context *gc,
    GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
    Eina_Bool blend = 0;
    GLuint prog = gc->shared->shader.yuv.prog;
+   int pn = 0;
 
    if (a < 255) blend = 1;
    
@@ -1092,36 +1587,122 @@ evas_gl_common_context_yuv_push(Evas_GL_Context *gc,
    else
      prog = gc->shared->shader.yuv.prog;
    
-   if ((gc->shader.cur_tex != tex->pt->texture)
-       || (gc->shader.cur_prog != prog)
-       || (gc->shader.smooth != smooth)
-       || (gc->shader.blend != blend)
-       || (gc->shader.render_op != gc->dc->render_op)
-       || (gc->shader.clip != 0)
+again:
+   pn = gc->state.top_pipe;
+#ifdef GLPIPES
+   if ((pn == 0) && (gc->pipe[pn].array.num == 0))
+     {
+        gc->pipe[pn].region.type = RTYPE_YUV;
+        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+        gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
+        gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
+        gc->pipe[pn].shader.cur_prog = prog;
+        gc->pipe[pn].shader.smooth = smooth;
+        gc->pipe[pn].shader.blend = blend;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = 0;
+        gc->pipe[pn].shader.cx = 0;
+        gc->pipe[pn].shader.cy = 0;
+        gc->pipe[pn].shader.cw = 0;
+        gc->pipe[pn].shader.ch = 0;
+        gc->pipe[pn].array.line = 0;
+        gc->pipe[pn].array.use_vertex = 1;
+        gc->pipe[pn].array.use_color = 1;
+        gc->pipe[pn].array.use_texuv = 1;
+        gc->pipe[pn].array.use_texuv2 = 1;
+        gc->pipe[pn].array.use_texuv3 = 1;
+     }
+   else
+     {
+        int found = 0;
+        
+        for (i = pn; i >= 0; i--)
+          {
+             if ((gc->pipe[i].region.type == RTYPE_YUV)
+                 && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
+                 && (gc->pipe[i].shader.cur_prog == gc->shared->shader.font.prog)
+                 && (gc->pipe[i].shader.smooth == smooth)
+                 && (gc->pipe[i].shader.blend == blend)
+                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
+                 && (gc->pipe[i].shader.clip == 0)
+                )
+               {
+                  found = 1;
+                  pn = i;
+                  break;
+               }
+             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
+          }
+        if (!found)
+          {
+             pn = gc->state.top_pipe + 1;
+             if (pn >= gc->shared->info.pipes_max)
+               {
+                  shader_array_flush(gc);
+                  goto again;
+               }
+             gc->state.top_pipe = pn;
+             gc->pipe[pn].region.type = RTYPE_YUV;
+             gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+             gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
+             gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
+             gc->pipe[pn].shader.cur_prog = prog;
+             gc->pipe[pn].shader.smooth = smooth;
+             gc->pipe[pn].shader.blend = blend;
+             gc->pipe[pn].shader.render_op = gc->dc->render_op;
+             gc->pipe[pn].shader.clip = 0;
+             gc->pipe[pn].shader.cx = 0;
+             gc->pipe[pn].shader.cy = 0;
+             gc->pipe[pn].shader.cw = 0;
+             gc->pipe[pn].shader.ch = 0;
+             gc->pipe[pn].array.line = 0;
+             gc->pipe[pn].array.use_vertex = 1;
+             gc->pipe[pn].array.use_color = 1;
+             gc->pipe[pn].array.use_texuv = 1;
+             gc->pipe[pn].array.use_texuv2 = 1;
+             gc->pipe[pn].array.use_texuv3 = 1;
+         }
+     }
+#else   
+   if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
+       || (gc->pipe[pn].shader.cur_prog != prog)
+       || (gc->pipe[pn].shader.smooth != smooth)
+       || (gc->pipe[pn].shader.blend != blend)
+       || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
+       || (gc->pipe[pn].shader.clip != 0)
        )
      {
         shader_array_flush(gc);
-        gc->shader.cur_tex = tex->pt->texture;
-        gc->shader.cur_texu = tex->ptu->texture;
-        gc->shader.cur_texv = tex->ptv->texture;
-        gc->shader.cur_prog = prog;
-        gc->shader.smooth = smooth;
-        gc->shader.blend = blend;
-        gc->shader.render_op = gc->dc->render_op;
-        gc->shader.clip = 0;
+        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+        gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
+        gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
+        gc->pipe[pn].shader.cur_prog = prog;
+        gc->pipe[pn].shader.smooth = smooth;
+        gc->pipe[pn].shader.blend = blend;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = 0;
+        gc->pipe[pn].shader.cx = 0;
+        gc->pipe[pn].shader.cy = 0;
+        gc->pipe[pn].shader.cw = 0;
+        gc->pipe[pn].shader.ch = 0;
      }
-   gc->array.line = 0;
-   gc->array.use_vertex = 1;
-   gc->array.use_color = 1;
-   gc->array.use_texuv = 1;
-   gc->array.use_texuv2 = 1;
-   gc->array.use_texuv3 = 1;
-   
-   pnum = gc->array.num;
+   
+   gc->pipe[pn].region.type = RTYPE_YUV;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 1;
+   gc->pipe[pn].array.use_color = 1;
+   gc->pipe[pn].array.use_texuv = 1;
+   gc->pipe[pn].array.use_texuv2 = 1;
+   gc->pipe[pn].array.use_texuv3 = 1;
+#endif
+   
+   pipe_region_expand(gc, pn, x, y, w, h);
+   
+   pnum = gc->pipe[pn].array.num;
    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; 
    nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4;
-   gc->array.num += 6;
-   _evas_gl_common_context_array_alloc(gc);
+   gc->pipe[pn].array.num += 6;
+   array_alloc(gc, pn);
 
    tx1 = (sx) / (double)tex->pt->w;
    ty1 = (sy) / (double)tex->pt->h;
@@ -1133,44 +1714,46 @@ evas_gl_common_context_yuv_push(Evas_GL_Context *gc,
    t2x2 = ((sx + sw) / 2) / (double)tex->ptu->w;
    t2y2 = ((sy + sh) / 2) / (double)tex->ptu->h;
    
-   PUSH_VERTEX(x    , y    , 0);
-   PUSH_VERTEX(x + w, y    , 0);
-   PUSH_VERTEX(x    , y + h, 0);
+   PUSH_VERTEX(pn, x    , y    , 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
    
-   PUSH_TEXUV(tx1, ty1);
-   PUSH_TEXUV(tx2, ty1);
-   PUSH_TEXUV(tx1, ty2);
+   PUSH_TEXUV(pn, tx1, ty1);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx1, ty2);
    
-   PUSH_TEXUV2(t2x1, t2y1);
-   PUSH_TEXUV2(t2x2, t2y1);
-   PUSH_TEXUV2(t2x1, t2y2);
+   PUSH_TEXUV2(pn, t2x1, t2y1);
+   PUSH_TEXUV2(pn, t2x2, t2y1);
+   PUSH_TEXUV2(pn, t2x1, t2y2);
    
-   PUSH_TEXUV3(t2x1, t2y1);
-   PUSH_TEXUV3(t2x2, t2y1);
-   PUSH_TEXUV3(t2x1, t2y2);
+   PUSH_TEXUV3(pn, t2x1, t2y1);
+   PUSH_TEXUV3(pn, t2x2, t2y1);
+   PUSH_TEXUV3(pn, t2x1, t2y2);
    
-   PUSH_VERTEX(x + w, y    , 0);
-   PUSH_VERTEX(x + w, y + h, 0);
-   PUSH_VERTEX(x    , y + h, 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x + w, y + h, 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
    
-   PUSH_TEXUV(tx2, ty1);
-   PUSH_TEXUV(tx2, ty2);
-   PUSH_TEXUV(tx1, ty2);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx2, ty2);
+   PUSH_TEXUV(pn, tx1, ty2);
 
-   PUSH_TEXUV2(t2x2, t2y1);
-   PUSH_TEXUV2(t2x2, t2y2);
-   PUSH_TEXUV2(t2x1, t2y2);
+   PUSH_TEXUV2(pn, t2x2, t2y1);
+   PUSH_TEXUV2(pn, t2x2, t2y2);
+   PUSH_TEXUV2(pn, t2x1, t2y2);
 
-   PUSH_TEXUV3(t2x2, t2y1);
-   PUSH_TEXUV3(t2x2, t2y2);
-   PUSH_TEXUV3(t2x1, t2y2);
+   PUSH_TEXUV3(pn, t2x2, t2y1);
+   PUSH_TEXUV3(pn, t2x2, t2y2);
+   PUSH_TEXUV3(pn, t2x1, t2y2);
 
    for (i = 0; i < 6; i++)
      {
-        PUSH_COLOR(r, g, b, a);
+        PUSH_COLOR(pn, r, g, b, a);
      }
 }
 
+// FIXME: we don't handle mapped yuv!!!! :(
+// FIXME: we don't handle clipped maps right :(
 void
 evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
                                        Evas_GL_Texture *tex,
@@ -1181,11 +1764,12 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
 {
    int pnum, nv, nc, nu, nu2, nt, i;
    const int points[6] = { 0, 1, 2, 0, 2, 3 };
+   int x = 0, y = 0, w = 0, h = 0, px = 0, py = 0;
    GLfloat tx[4], ty[4];
    Eina_Bool blend = 1;
-   RGBA_Map_Point *pt;
    DATA32 cmul;
    GLuint prog = gc->shared->shader.img.prog;
+   int pn = 0;
 
    if (!tex->alpha) blend = 0;
    if (a < 255) blend = 1;
@@ -1195,16 +1779,32 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
    
    if (tex_only)
      {
-        if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
+        if (tex->pt->dyn.img)
           {
-             if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
-                 (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
-               prog = gc->shared->shader.tex_nomul.prog;
+             if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
+               {
+                  if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
+                      (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
+                     prog = gc->shared->shader.img_nomul.prog;
+                  else
+                     prog = gc->shared->shader.img.prog;
+               }
              else
-               prog = gc->shared->shader.tex.prog;
+                prog = gc->shared->shader.img.prog;
           }
         else
-          prog = gc->shared->shader.tex.prog;
+          {
+             if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
+               {
+                  if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
+                      (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
+                     prog = gc->shared->shader.tex_nomul.prog;
+                  else
+                     prog = gc->shared->shader.tex.prog;
+               }
+             else
+                prog = gc->shared->shader.tex.prog;
+          }
      }
    else
      {
@@ -1236,74 +1836,200 @@ evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
           }
      }
    
-   if ((gc->shader.cur_tex != tex->pt->texture)
-       || (gc->shader.cur_prog != prog)
-       || (gc->shader.smooth != smooth)
-       || (gc->shader.blend != blend)
-       || (gc->shader.render_op != gc->dc->render_op)
-       || (gc->shader.clip != clip)
-       || (gc->shader.cx != cx)
-       || (gc->shader.cy != cy)
-       || (gc->shader.cw != cw)
-       || (gc->shader.ch != ch)
+   /*xxx*/ shader_array_flush(gc);
+again:
+   pn = gc->state.top_pipe;
+#ifdef GLPIPES
+   if ((pn == 0) && (gc->pipe[pn].array.num == 0))
+     {
+        gc->pipe[pn].region.type = RTYPE_MAP;
+        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+        gc->pipe[pn].shader.cur_prog = prog;
+        gc->pipe[pn].shader.smooth = smooth;
+        gc->pipe[pn].shader.blend = blend;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = clip;
+        gc->pipe[pn].shader.cx = cx;
+        gc->pipe[pn].shader.cy = cy;
+        gc->pipe[pn].shader.cw = cw;
+        gc->pipe[pn].shader.ch = ch;
+        gc->pipe[pn].array.line = 0;
+        gc->pipe[pn].array.use_vertex = 1;
+        gc->pipe[pn].array.use_color = 1;
+        gc->pipe[pn].array.use_texuv = 1;
+        gc->pipe[pn].array.use_texuv2 = 0;
+        gc->pipe[pn].array.use_texuv3 = 0;
+     }
+   else
+     {
+        int found = 0;
+        
+        for (i = pn; i >= 0; i--)
+          {
+             if ((gc->pipe[i].region.type == RTYPE_MAP)
+                 && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
+                 && (gc->pipe[i].shader.cur_prog == prog)
+                 && (gc->pipe[i].shader.smooth == smooth)
+                 && (gc->pipe[i].shader.blend == blend)
+                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
+                 && (gc->pipe[i].shader.clip == clip)
+                 && (gc->pipe[i].shader.cx == cx)
+                 && (gc->pipe[i].shader.cy == cy)
+                 && (gc->pipe[i].shader.cw == cw)
+                 && (gc->pipe[i].shader.ch == ch)
+                )
+               {
+                  found = 1;
+                  pn = i;
+                  break;
+               }
+             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
+          }
+        if (!found)
+          {
+             pn = gc->state.top_pipe + 1;
+             if (pn >= gc->shared->info.pipes_max)
+               {
+                  shader_array_flush(gc);
+                  goto again;
+               }
+             gc->state.top_pipe = pn;
+             gc->pipe[pn].region.type = RTYPE_MAP;
+             gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+             gc->pipe[pn].shader.cur_prog = prog;
+             gc->pipe[pn].shader.smooth = smooth;
+             gc->pipe[pn].shader.blend = blend;
+             gc->pipe[pn].shader.render_op = gc->dc->render_op;
+             gc->pipe[pn].shader.clip = clip;
+             gc->pipe[pn].shader.cx = cx;
+             gc->pipe[pn].shader.cy = cy;
+             gc->pipe[pn].shader.cw = cw;
+             gc->pipe[pn].shader.ch = ch;
+             gc->pipe[pn].array.line = 0;
+             gc->pipe[pn].array.use_vertex = 1;
+             gc->pipe[pn].array.use_color = 1;
+             gc->pipe[pn].array.use_texuv = 1;
+             gc->pipe[pn].array.use_texuv2 = 0;
+             gc->pipe[pn].array.use_texuv3 = 0;
+         }
+     }
+   if ((tex->im) && (tex->im->native.data))
+     {
+        if (gc->pipe[pn].array.im != tex->im)
+          {
+             shader_array_flush(gc);
+             pn = gc->state.top_pipe;
+             gc->pipe[pn].array.im = tex->im;
+             goto again;
+          }
+     }
+   if (tex->pt->dyn.img)
+     {
+        if (gc->pipe[pn].array.im != tex->im)
+          {
+             shader_array_flush(gc);
+             pn = gc->state.top_pipe;
+             gc->pipe[pn].array.im = tex->im;
+             goto again;
+          }
+     }
+#else   
+   if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
+       || (gc->pipe[pn].shader.cur_prog != prog)
+       || (gc->pipe[pn].shader.smooth != smooth)
+       || (gc->pipe[pn].shader.blend != blend)
+       || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
+       || (gc->pipe[pn].shader.clip != clip)
+       || (gc->pipe[pn].shader.cx != cx)
+       || (gc->pipe[pn].shader.cy != cy)
+       || (gc->pipe[pn].shader.cw != cw)
+       || (gc->pipe[pn].shader.ch != ch)
        )
      {
         shader_array_flush(gc);
-        gc->shader.cur_tex = tex->pt->texture;
-        gc->shader.cur_prog = prog;
-        gc->shader.smooth = smooth;
-        gc->shader.blend = blend;
-        gc->shader.render_op = gc->dc->render_op;
-        gc->shader.clip = clip;
-        gc->shader.cx = cx;
-        gc->shader.cy = cy;
-        gc->shader.cw = cw;
-        gc->shader.ch = ch;
+        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+        gc->pipe[pn].shader.cur_prog = prog;
+        gc->pipe[pn].shader.smooth = smooth;
+        gc->pipe[pn].shader.blend = blend;
+        gc->pipe[pn].shader.render_op = gc->dc->render_op;
+        gc->pipe[pn].shader.clip = clip;
+        gc->pipe[pn].shader.cx = cx;
+        gc->pipe[pn].shader.cy = cy;
+        gc->pipe[pn].shader.cw = cw;
+        gc->pipe[pn].shader.ch = ch;
      }
    if ((tex->im) && (tex->im->native.data))
      {
-        if (gc->array.im != tex->im)
+        if (gc->pipe[pn].array.im != tex->im)
           {
              shader_array_flush(gc);
-             gc->array.im = tex->im;
+             gc->pipe[pn].array.im = tex->im;
+          }
+     }
+   if (tex->pt->dyn.img)
+     {
+        if (gc->pipe[pn].array.im != tex->im)
+          {
+             shader_array_flush(gc);
+             gc->pipe[pn].array.im = tex->im;
           }
      }
-   gc->array.line = 0;
-   gc->array.use_vertex = 1;
-   gc->array.use_color = 1;
-   gc->array.use_texuv = 1;
-   gc->array.use_texuv2 = 1;
-   gc->array.use_texuv3 = 0;
-   
-   pnum = gc->array.num;
-   nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
-   nt = pnum * 4;
-   gc->array.num += 6;
-   _evas_gl_common_context_array_alloc(gc);
 
+   gc->pipe[pn].region.type = RTYPE_MAP;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 1;
+   gc->pipe[pn].array.use_color = 1;
+   gc->pipe[pn].array.use_texuv = 1;
+   gc->pipe[pn].array.use_texuv2 = 0;
+   gc->pipe[pn].array.use_texuv3 = 0;
+#endif   
+   
+   x = w = (p[points[0]].x >> FP);
+   y = h = (p[points[0]].y >> FP);
    for (i = 0; i < 4; i++)
      {
         tx[i] = ((double)(tex->x) + (((double)p[i].u) / FP1)) /
           (double)tex->pt->w;
         ty[i] = ((double)(tex->y) + (((double)p[i].v) / FP1)) / 
           (double)tex->pt->h;
+        px = (p[points[i]].x >> FP);
+        if      (px < x) x = px;
+        else if (px > w) w = py;
+        py = (p[points[i]].y >> FP);
+        if      (py < y) y = py;
+        else if (py > h) h = py;
      }
+   w = w - x;
+   h = h - y;
+   
+   pipe_region_expand(gc, pn, x, y, w, h);
+   
+   pnum = gc->pipe[pn].array.num;
+   nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
+   nt = pnum * 4;
+   gc->pipe[pn].array.num += 6;
+   array_alloc(gc, pn);
+
    if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
      {
         // FIXME: handle yinvert
+        fprintf(stderr, "EVAS GL ENGINE ERROR: not handling inverted y case for map4\n");
      }
    
    cmul = ARGB_JOIN(a, r, g, b);
    for (i = 0; i < 6; i++)
      {
         DATA32 cl = MUL4_SYM(cmul, p[points[i]].col);
-        PUSH_VERTEX((p[points[i]].x >> FP), 
+        PUSH_VERTEX(pn,
+                    (p[points[i]].x >> FP), 
                     (p[points[i]].y >> FP),
                     0);
-        PUSH_TEXUV(tx[points[i]],
+        PUSH_TEXUV(pn,
+                   tx[points[i]],
                    ty[points[i]]);
         
-        PUSH_COLOR(R_VAL(&cl),
+        PUSH_COLOR(pn,
+                   R_VAL(&cl),
                    G_VAL(&cl),
                    B_VAL(&cl),
                    A_VAL(&cl));
@@ -1314,265 +2040,286 @@ void
 evas_gl_common_context_flush(Evas_GL_Context *gc)
 {
    shader_array_flush(gc);
-//   fprintf(stderr, "------------FRAME: done\n");
 }
 
 static void
 shader_array_flush(Evas_GL_Context *gc)
 {
-   if (gc->array.num <= 0) return;
-
-//   fprintf(stderr, "  flush array %i\n", gc->array.num);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "<flush err>");
-   if (gc->shader.cur_prog != gc->shader.current.cur_prog)
+   int i;
+   
+   for (i = 0; i < gc->shared->info.pipes_max; i++)
      {
-        glUseProgram(gc->shader.cur_prog);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-     }
+        if (gc->pipe[i].array.num <= 0) break;
 
-   if (gc->shader.cur_tex != gc->shader.current.cur_tex)
-     {
-#if 0
-        if (gc->shader.cur_tex)
+        gc->flushnum++;
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "<flush err>");
+        if (gc->pipe[i].shader.cur_prog != gc->state.current.cur_prog)
           {
-             glEnable(GL_TEXTURE_2D);
+             glUseProgram(gc->pipe[i].shader.cur_prog);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
-        else
+        
+        if (gc->pipe[i].shader.cur_tex != gc->state.current.cur_tex)
           {
-             glDisable(GL_TEXTURE_2D);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-          }
+#if 0
+             if (gc->pipe[i].shader.cur_tex)
+               {
+                  glEnable(GL_TEXTURE_2D);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+               }
+             else
+               {
+                  glDisable(GL_TEXTURE_2D);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+               }
 #endif
-        glActiveTexture(GL_TEXTURE0);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-     }
-   if (gc->array.im)
-     {
-        if (!gc->array.im->native.loose)
-          {
-             if (gc->array.im->native.func.bind)
-               gc->array.im->native.func.bind(gc->array.im->native.func.data, 
-                                              gc->array.im);
-          }
-     }
-   if (gc->shader.render_op != gc->shader.current.render_op)
-     {
-        switch (gc->shader.render_op)
-          {
-          case EVAS_RENDER_BLEND: /**< default op: d = d*(1-sa) + s */
-             glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             break;
-          case EVAS_RENDER_COPY: /**< d = s */
-             gc->shader.blend = 0;
-             glBlendFunc(GL_ONE, GL_ONE);
+             glActiveTexture(GL_TEXTURE0);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             break;
-             // FIXME: fix blend funcs below!
-          case EVAS_RENDER_BLEND_REL: /**< d = d*(1 - sa) + s*da */
-          case EVAS_RENDER_COPY_REL: /**< d = s*da */
-          case EVAS_RENDER_ADD: /**< d = d + s */
-          case EVAS_RENDER_ADD_REL: /**< d = d + s*da */
-          case EVAS_RENDER_SUB: /**< d = d - s */
-          case EVAS_RENDER_SUB_REL: /**< d = d - s*da */
-          case EVAS_RENDER_TINT: /**< d = d*s + d*(1 - sa) + s*(1 - da) */
-          case EVAS_RENDER_TINT_REL: /**< d = d*(1 - sa + s) */
-          case EVAS_RENDER_MASK: /**< d = d*sa */
-          case EVAS_RENDER_MUL: /**< d = d*s */
-          default:
-             glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+             glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_tex);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             break;
           }
-     }
-   if (gc->shader.blend != gc->shader.current.blend)
-     {
-        if (gc->shader.blend)
+        if (gc->pipe[i].array.im)
           {
-             glEnable(GL_BLEND);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+             if (gc->pipe[i].array.im->tex->pt->dyn.img)
+               {
+                  secsym_glEGLImageTargetTexture2DOES
+                     (GL_TEXTURE_2D, gc->pipe[i].array.im->tex->pt->dyn.img);
+               }
+             else
+#endif                
+               {
+                  if (!gc->pipe[i].array.im->native.loose)
+                    {
+                       if (gc->pipe[i].array.im->native.func.bind)
+                          gc->pipe[i].array.im->native.func.bind(gc->pipe[i].array.im->native.func.data, 
+                                                                 gc->pipe[i].array.im);
+                    }
+               }
           }
-        else
+        if (gc->pipe[i].shader.render_op != gc->state.current.render_op)
           {
-             glDisable(GL_BLEND);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+             switch (gc->pipe[i].shader.render_op)
+               {
+               case EVAS_RENDER_BLEND: /**< default op: d = d*(1-sa) + s */
+                  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  break;
+               case EVAS_RENDER_COPY: /**< d = s */
+                  gc->pipe[i].shader.blend = 0;
+                  glBlendFunc(GL_ONE, GL_ONE);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  break;
+                  // FIXME: fix blend funcs below!
+               case EVAS_RENDER_BLEND_REL: /**< d = d*(1 - sa) + s*da */
+               case EVAS_RENDER_COPY_REL: /**< d = s*da */
+               case EVAS_RENDER_ADD: /**< d = d + s */
+               case EVAS_RENDER_ADD_REL: /**< d = d + s*da */
+               case EVAS_RENDER_SUB: /**< d = d - s */
+               case EVAS_RENDER_SUB_REL: /**< d = d - s*da */
+               case EVAS_RENDER_TINT: /**< d = d*s + d*(1 - sa) + s*(1 - da) */
+               case EVAS_RENDER_TINT_REL: /**< d = d*(1 - sa + s) */
+               case EVAS_RENDER_MASK: /**< d = d*sa */
+               case EVAS_RENDER_MUL: /**< d = d*s */
+               default:
+                     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  break;
+               }
           }
-     }
-   if (gc->shader.smooth != gc->shader.current.smooth)
-     {
-        if (gc->shader.smooth)
+        if (gc->pipe[i].shader.blend != gc->state.current.blend)
           {
-#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
-             if (shared->info.anisotropic > 0.0)
+             if (gc->pipe[i].shader.blend)
                {
-                  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, shared->info.anisotropic);
+                  glEnable(GL_BLEND);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+               }
+             else
+               {
+                  glDisable(GL_BLEND);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                }
-#endif
-             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
-        else
+        if (gc->pipe[i].shader.smooth != gc->state.current.smooth)
           {
-#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
-             if (shared->info.anisotropic > 0.0)
+             if (gc->pipe[i].shader.smooth)
                {
-                  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
+#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
+                  if (shared->info.anisotropic > 0.0)
+                    {
+                       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, shared->info.anisotropic);
+                       GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                    }
+#endif
+                  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                }
+             else
+               {
+#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
+                  if (shared->info.anisotropic > 0.0)
+                    {
+                       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
+                       GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                    }
 #endif
-             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+                  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+               }
+          }
+        /* hmmm this breaks things. must find out why!   
+         if (gc->pipe[i].shader.clip != gc->state.current.clip)
+         {
+         if (gc->pipe[i].shader.clip)
+         glEnable(GL_SCISSOR_TEST);
+         else
+         {
+         glDisable(GL_SCISSOR_TEST);
+         //             glScissor(0, 0, 0, 0);
+         }
+         }
+         if (gc->pipe[i].shader.clip)
+         {
+         if ((gc->pipe[i].shader.cx != gc->state.current.cx) ||
+         (gc->pipe[i].shader.cx != gc->state.current.cx) ||
+         (gc->pipe[i].shader.cx != gc->state.current.cx) ||
+         (gc->pipe[i].shader.cx != gc->state.current.cx))
+         {
+         glScissor(gc->pipe[i].shader.cx, 
+         gc->h - gc->pipe[i].shader.cy - gc->pipe[i].shader.ch,
+         gc->pipe[i].shader.cw,
+         gc->pipe[i].shader.ch);
+         }
+         //                    gc->pipe[i].clip.x,
+         //                    gc->h - gc->pipe[i].clip.y - gc->pipe[i].clip.h,
+         //                    gc->pipe[i].clip.w,
+         //                    gc->pipe[i].clip.h);
+         * 
+         }
+         */
+        glVertexAttribPointer(SHAD_VERTEX, 3, GL_SHORT, GL_FALSE, 0, gc->pipe[i].array.vertex);
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        glVertexAttribPointer(SHAD_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, gc->pipe[i].array.color);
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        if (gc->pipe[i].array.use_texuv)
+          {
+             glEnableVertexAttribArray(SHAD_TEXUV);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+             glVertexAttribPointer(SHAD_TEXUV, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
-     }
-/* hmmm this breaks things. must find out why!   
-   if (gc->shader.clip != gc->shader.current.clip)
-     {
-        if (gc->shader.clip)
-          glEnable(GL_SCISSOR_TEST);
         else
           {
-             glDisable(GL_SCISSOR_TEST);
-//             glScissor(0, 0, 0, 0);
-          }
-     }
-   if (gc->shader.clip)
-     {
-        if ((gc->shader.cx != gc->shader.current.cx) ||
-            (gc->shader.cx != gc->shader.current.cx) ||
-            (gc->shader.cx != gc->shader.current.cx) ||
-            (gc->shader.cx != gc->shader.current.cx))
-          {
-             glScissor(gc->shader.cx, 
-                       gc->h - gc->shader.cy - gc->shader.ch,
-                       gc->shader.cw,
-                       gc->shader.ch);
+             glDisableVertexAttribArray(SHAD_TEXUV);
+             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
-//                    gc->clip.x,
-//                    gc->h - gc->clip.y - gc->clip.h,
-//                    gc->clip.w,
-//                    gc->clip.h);
         
-     }
- */
-   glVertexAttribPointer(SHAD_VERTEX, 3, GL_SHORT, GL_FALSE, 0, gc->array.vertex);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glVertexAttribPointer(SHAD_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, gc->array.color);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   if (gc->array.use_texuv)
-     {
-        glEnableVertexAttribArray(SHAD_TEXUV);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glVertexAttribPointer(SHAD_TEXUV, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-     }
-   else
-     {
-        glDisableVertexAttribArray(SHAD_TEXUV);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-     }
-
-   if (gc->array.line)
-     {
-        glDisableVertexAttribArray(SHAD_TEXUV);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glDisableVertexAttribArray(SHAD_TEXUV2); 
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glDisableVertexAttribArray(SHAD_TEXUV3);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glDrawArrays(GL_LINES, 0, gc->array.num);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-     }
-   else
-     {
-        if ((gc->array.use_texuv2) && (gc->array.use_texuv3))
+        if (gc->pipe[i].array.line)
           {
-             glEnableVertexAttribArray(SHAD_TEXUV2);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glEnableVertexAttribArray(SHAD_TEXUV3);
+             glDisableVertexAttribArray(SHAD_TEXUV);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv2);
+             glDisableVertexAttribArray(SHAD_TEXUV2); 
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glVertexAttribPointer(SHAD_TEXUV3, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv3);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glActiveTexture(GL_TEXTURE1);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glBindTexture(GL_TEXTURE_2D, gc->shader.cur_texu);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glActiveTexture(GL_TEXTURE2);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glBindTexture(GL_TEXTURE_2D, gc->shader.cur_texv);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glActiveTexture(GL_TEXTURE0);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-          }
-        else if (gc->array.use_texuv2)
-          {
-             glEnableVertexAttribArray(SHAD_TEXUV2);
+             glDisableVertexAttribArray(SHAD_TEXUV3);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv2);
+             glDrawArrays(GL_LINES, 0, gc->pipe[i].array.num);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
         else
           {
-             glDisableVertexAttribArray(SHAD_TEXUV2);
-             GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glDisableVertexAttribArray(SHAD_TEXUV3);
+             if ((gc->pipe[i].array.use_texuv2) && (gc->pipe[i].array.use_texuv3))
+               {
+                  glEnableVertexAttribArray(SHAD_TEXUV2);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glEnableVertexAttribArray(SHAD_TEXUV3);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv2);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glVertexAttribPointer(SHAD_TEXUV3, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv3);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glActiveTexture(GL_TEXTURE1);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glActiveTexture(GL_TEXTURE2);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texv);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glActiveTexture(GL_TEXTURE0);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+               }
+             else if (gc->pipe[i].array.use_texuv2)
+               {
+                  glEnableVertexAttribArray(SHAD_TEXUV2);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv2);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+               }
+             else
+               {
+                  glDisableVertexAttribArray(SHAD_TEXUV2);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glDisableVertexAttribArray(SHAD_TEXUV3);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+               }
+             
+             glDrawArrays(GL_TRIANGLES, 0, gc->pipe[i].array.num);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
-   
-        glDrawArrays(GL_TRIANGLES, 0, gc->array.num);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-     }
-   if (gc->array.im)
-     {
-        if (!gc->array.im->native.loose)
+        if (gc->pipe[i].array.im)
           {
-             if (gc->array.im->native.func.unbind)
-               gc->array.im->native.func.unbind(gc->array.im->native.func.data, 
-                                                gc->array.im);
+             if (!gc->pipe[i].array.im->native.loose)
+               {
+                  if (gc->pipe[i].array.im->native.func.unbind)
+                     gc->pipe[i].array.im->native.func.unbind(gc->pipe[i].array.im->native.func.data, 
+                                                              gc->pipe[i].array.im);
+               }
+             gc->pipe[i].array.im = NULL;
           }
-        gc->array.im = NULL;
+        
+        gc->state.current.cur_prog = gc->pipe[i].shader.cur_prog;
+        gc->state.current.cur_tex = gc->pipe[i].shader.cur_tex;
+        gc->state.current.blend = gc->pipe[i].shader.blend;
+        gc->state.current.smooth = gc->pipe[i].shader.smooth;
+        gc->state.current.render_op = gc->pipe[i].shader.render_op;
+        gc->state.current.clip = gc->pipe[i].shader.clip;
+        gc->state.current.cx = gc->pipe[i].shader.cx;
+        gc->state.current.cy = gc->pipe[i].shader.cy;
+        gc->state.current.cw = gc->pipe[i].shader.cw;
+        gc->state.current.ch = gc->pipe[i].shader.ch;
+        
+        if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex);
+        if (gc->pipe[i].array.color) free(gc->pipe[i].array.color);
+        if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv);
+        if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2);
+        if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3);
+        
+        gc->pipe[i].array.vertex = NULL;
+        gc->pipe[i].array.color = NULL;
+        gc->pipe[i].array.texuv = NULL;
+        gc->pipe[i].array.texuv2 = NULL;
+        gc->pipe[i].array.texuv3 = NULL;
+
+        gc->pipe[i].array.num = 0;
+        gc->pipe[i].array.alloc = 0;
+        
+        gc->pipe[i].region.x = 0;
+        gc->pipe[i].region.y = 0;
+        gc->pipe[i].region.w = 0;
+        gc->pipe[i].region.h = 0;
+        gc->pipe[i].region.type = 0;
      }
-
-   gc->shader.current.cur_prog = gc->shader.cur_prog;
-   gc->shader.current.cur_tex = gc->shader.cur_tex;
-   gc->shader.current.blend = gc->shader.blend;
-   gc->shader.current.smooth = gc->shader.smooth;
-   gc->shader.current.render_op = gc->shader.render_op;
-   gc->shader.current.clip = gc->shader.clip;
-   gc->shader.current.cx = gc->shader.cx;
-   gc->shader.current.cy = gc->shader.cy;
-   gc->shader.current.cw = gc->shader.cw;
-   gc->shader.current.ch = gc->shader.ch;
-   
-   if (gc->array.vertex) free(gc->array.vertex);
-   if (gc->array.color) free(gc->array.color);
-   if (gc->array.texuv) free(gc->array.texuv);
-   if (gc->array.texuv2) free(gc->array.texuv2);
-   if (gc->array.texuv3) free(gc->array.texuv3);
-   
-   gc->array.vertex = NULL;
-   gc->array.color = NULL;
-   gc->array.texuv = NULL;
-   gc->array.texuv2 = NULL;
-   gc->array.texuv3 = NULL;
-   
-   gc->array.num = 0;
-   gc->array.alloc = 0;
+    gc->state.top_pipe = 0;
 }
index 72be3ae..83c9641 100644 (file)
@@ -265,6 +265,75 @@ evas_gl_common_image_native_disable(Evas_GL_Image *im)
 }
 
 void
+evas_gl_common_image_scale_hint_set(Evas_GL_Image *im, int hint)
+{
+   im->scale_hint = hint;
+   // FIXME: take advantage of this even in gl (eg if image is
+   // 1600x1200 but we always use it at 800x600 or even less - drop
+   // the texture res down for "non dynamic" stuff to save memory)
+}
+
+void
+evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint)
+{
+   if (im->content_hint == hint) return;
+   im->content_hint = hint;
+   if (!im->gc) return;
+   if (!im->gc->shared->info.sec_image_map) return;
+   if (!im->gc->shared->info.bgra) return;
+   // does not handle yuv yet.
+   if (im->cs.space != EVAS_COLORSPACE_ARGB8888) return;
+   if (im->content_hint == EVAS_IMAGE_CONTENT_HINT_DYNAMIC)
+     {
+        if (im->cs.data)
+          {
+             if (!im->cs.no_free) free(im->cs.data);
+             im->cs.data = NULL;
+          }
+        im->cs.no_free = 0;
+        if (im->cached)
+          {
+             im->gc->shared->images = eina_list_remove(im->gc->shared->images, im);
+             im->cached = 0;
+          }
+        if (im->im)
+          {
+             evas_cache_image_drop(&im->im->cache_entry);
+             im->im = NULL;
+          }
+        if (im->tex)
+          {
+             evas_gl_common_texture_free(im->tex);
+             im->tex = NULL;
+          }
+        im->tex = evas_gl_common_texture_dynamic_new(im->gc, im);
+        im->tex_only = 1;
+     }
+   else
+     {
+        if (im->im)
+          {
+             evas_cache_image_drop(&im->im->cache_entry);
+             im->im = NULL;
+          }
+        if (im->tex)
+          {
+             evas_gl_common_texture_free(im->tex);
+             im->tex = NULL;
+          }
+        im->tex_only = 0;
+        
+        im->im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
+        im->im->cache_entry.flags.alpha = im->alpha;
+        im->cs.space = EVAS_COLORSPACE_ARGB8888;
+        evas_cache_image_colorspace(&im->im->cache_entry, im->cs.space);
+        im->im = (RGBA_Image *)evas_cache_image_size_set(&im->im->cache_entry, im->w, im->h);
+        if (!im->tex)
+           im->tex = evas_gl_common_texture_new(im->gc, im->im);
+     }
+}
+
+void
 evas_gl_common_image_free(Evas_GL_Image *im)
 {
    im->references--;
@@ -454,7 +523,9 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy
      yuv = 1;
    
    im->tex->im = im;
-   if ((!gc->dc->cutout.rects) || (gc->dc->cutout.active > 16))
+   if ((!gc->dc->cutout.rects) || 
+       ((gc->shared->info.cutout_max > 0) &&
+           (gc->dc->cutout.active > gc->shared->info.cutout_max)))
      {
         if (gc->dc->clip.use)
           {
index 49dd902..fda1400 100644 (file)
@@ -125,7 +125,7 @@ evas_gl_common_poly_draw(Evas_GL_Context *gc, Evas_GL_Polygon *poly, int dx, int
    Cutout_Rects *rects;
    Cutout_Rect  *r;
    int c, cx, cy, cw, ch, cr, cg, cb, ca, i;
-   int x, y, w, h;
+   int x = 0, y = 0, w = 0, h = 0;
 
    Eina_List *l;
    int n, k, num_active_edges, y0, y1, *sorted_index, j;
index c26ab24..92193ef 100644 (file)
@@ -10,10 +10,17 @@ static const GLenum rgb_fmt    = GL_RGBA;
 static const GLenum rgb_ifmt   = GL_RGB;
 //#endif
 #ifdef GL_BGRA
+# if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+static const GLenum bgra_fmt   = GL_BGRA;
+static const GLenum bgra_ifmt  = GL_BGRA;
+static const GLenum bgr_fmt    = GL_BGRA;
+static const GLenum bgr_ifmt   = GL_BGRA;
+# else
 static const GLenum bgra_fmt   = GL_BGRA;
 static const GLenum bgra_ifmt  = GL_RGBA;
 static const GLenum bgr_fmt    = GL_BGRA;
 static const GLenum bgr_ifmt   = GL_RGB;
+# endif
 #endif
 static const GLenum alpha_fmt  = GL_ALPHA;
 static const GLenum alpha_ifmt = GL_ALPHA;
@@ -35,8 +42,6 @@ _nearest_pow2(int num)
 static void
 _tex_adjust(Evas_GL_Context *gc, int *w, int *h)
 {
-   unsigned int n;
-   
    if (gc->shared->info.tex_npo2) return;
    /*if (gc->shared->info.tex_rect) return;*/
    *w = _nearest_pow2(*w);
@@ -116,7 +121,7 @@ _pool_tex_new(Evas_GL_Context *gc, int w, int h, int intformat, int format)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    _tex_2d(pt->intformat, w, h, pt->format, pt->dataformat);
-   glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex);
+   glBindTexture(GL_TEXTURE_2D, gc->pipe[0].shader.cur_tex);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    return pt;
 }
@@ -330,7 +335,7 @@ _pool_tex_render_new(Evas_GL_Context *gc, int w, int h, int intformat, int forma
    glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    
-   glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex);
+   glBindTexture(GL_TEXTURE_2D, gc->pipe[0].shader.cur_tex);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    return pt;
 }
@@ -384,11 +389,150 @@ _pool_tex_native_new(Evas_GL_Context *gc, int w, int h, int intformat, int forma
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    glBindTexture(im->native.target, 0);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glBindTexture(im->native.target, gc->shader.cur_tex);
+   glBindTexture(im->native.target, gc->pipe[0].shader.cur_tex);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    return pt;
 }
 
+static Evas_GL_Texture_Pool *
+_pool_tex_dynamic_new(Evas_GL_Context *gc, int w, int h, int intformat, int format)
+{
+   Evas_GL_Texture_Pool *pt = NULL;
+   
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+   int fmt; // EGL_MAP_GL_TEXTURE_RGBA_SEC or EGL_MAP_GL_TEXTURE_RGB_SEC or bust
+   int pixtype; // EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC or bust
+   int attr[] =
+     {
+        EGL_MAP_GL_TEXTURE_WIDTH_SEC, 32,
+        EGL_MAP_GL_TEXTURE_HEIGHT_SEC, 32,
+        EGL_MAP_GL_TEXTURE_FORMAT_SEC, EGL_MAP_GL_TEXTURE_RGBA_SEC,
+        EGL_MAP_GL_TEXTURE_PIXEL_TYPE_SEC, EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC,
+        EGL_NONE
+     };
+   void *egldisplay;
+   
+   pt = calloc(1, sizeof(Evas_GL_Texture_Pool));
+   if (!pt) return NULL;
+   h = _tex_round_slot(gc, h) << 4;
+   _tex_adjust(gc, &w, &h);
+   pt->gc = gc;
+   pt->w = w;
+   pt->h = h;
+   pt->intformat = intformat;
+   pt->format = format;
+   pt->dataformat = GL_UNSIGNED_BYTE;
+   pt->render = 1;
+   pt->references = 0;
+   glGenTextures(1, &(pt->texture));
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glBindTexture(GL_TEXTURE_2D, pt->texture);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
+   egldisplay = pt->gc->egldisp;
+   
+   attr[1] = pt->w;
+   attr[3] = pt->h;
+
+   // FIXME: seems a bit slower than i'd like - maybe too many flushes?
+   // FIXME: YCbCr no support as yet
+   pt->dyn.img = secsym_eglCreateImage(egldisplay,
+                                       EGL_NO_CONTEXT, 
+                                       EGL_MAP_GL_TEXTURE_2D_SEC,
+                                       0, attr);
+   if (!pt->dyn.img)
+     {
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        return pt;
+     }
+   pt->dyn.data = secsym_eglMapImageSEC(egldisplay,
+                                        pt->dyn.img);
+   if (!pt->dyn.data)
+     {
+        secsym_eglDestroyImage(egldisplay, pt->dyn.img);
+        pt->dyn.img = NULL;
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        return pt;
+     }
+   if (secsym_eglGetImageAttribSEC(egldisplay,
+                                   pt->dyn.img,
+                                   EGL_MAP_GL_TEXTURE_WIDTH_SEC,
+                                   &(pt->dyn.w)) != EGL_TRUE)
+     {
+        secsym_eglDestroyImage(egldisplay, pt->dyn.img);
+        pt->dyn.img = NULL;
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        return pt;
+     }
+   if (secsym_eglGetImageAttribSEC(egldisplay,
+                                   pt->dyn.img,
+                                   EGL_MAP_GL_TEXTURE_HEIGHT_SEC,
+                                   &(pt->dyn.h)) != EGL_TRUE)
+     {
+        secsym_eglDestroyImage(egldisplay, pt->dyn.img);
+        pt->dyn.img = NULL;
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        return pt;
+     }
+   if (secsym_eglGetImageAttribSEC(egldisplay,
+                                   pt->dyn.img,
+                                   EGL_MAP_GL_TEXTURE_STRIDE_IN_BYTES_SEC,
+                                   &(pt->dyn.stride)) != EGL_TRUE)
+     {
+        secsym_eglDestroyImage(egldisplay, pt->dyn.img);
+        pt->dyn.img = NULL;
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        return pt;
+     }
+   if (secsym_eglGetImageAttribSEC(egldisplay,
+                                   pt->dyn.img,
+                                   EGL_MAP_GL_TEXTURE_FORMAT_SEC,
+                                   &(fmt)) != EGL_TRUE)
+     {
+        secsym_eglDestroyImage(egldisplay, pt->dyn.img);
+        pt->dyn.img = NULL;
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        return pt;
+     }
+   if (fmt != EGL_MAP_GL_TEXTURE_RGBA_SEC)
+     {
+        secsym_eglDestroyImage(egldisplay, pt->dyn.img);
+        pt->dyn.img = NULL;
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        return pt;
+     }
+   if (secsym_eglGetImageAttribSEC(egldisplay,
+                                   pt->dyn.img,
+                                   EGL_MAP_GL_TEXTURE_PIXEL_TYPE_SEC,
+                                   &(pixtype)) != EGL_TRUE)
+     {
+        secsym_eglDestroyImage(egldisplay, pt->dyn.img);
+        pt->dyn.img = NULL;
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        return pt;
+     }
+   if (pixtype != EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC)
+     {
+        secsym_eglDestroyImage(egldisplay, pt->dyn.img);
+        pt->dyn.img = NULL;
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        return pt;
+     }
+   
+   glBindTexture(GL_TEXTURE_2D, gc->pipe[0].shader.cur_tex);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+#endif  
+   return pt;
+}
+
 static void
 pt_unref(Evas_GL_Texture_Pool *pt)
 {
@@ -402,6 +546,19 @@ pt_unref(Evas_GL_Texture_Pool *pt)
           pt->gc->shared->tex.atlas [pt->slot][pt->fslot] =
           eina_list_remove(pt->gc->shared->tex.atlas[pt->slot][pt->fslot], pt);
      }
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+   if (pt->dyn.img)
+     {
+        void *egldisplay = pt->gc->egldisp;
+        
+        secsym_eglDestroyImage(pt->gc->egldisp, pt->dyn.img);
+        pt->dyn.img = NULL;
+        pt->dyn.data = NULL;
+        pt->dyn.w = 0;
+        pt->dyn.h = 0;
+        pt->dyn.stride = 0;
+     }
+#endif   
    
    glDeleteTextures(1, &(pt->texture));
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
@@ -418,8 +575,6 @@ Evas_GL_Texture *
 evas_gl_common_texture_native_new(Evas_GL_Context *gc, int w, int h, int alpha, Evas_GL_Image *im)
 {
    Evas_GL_Texture *tex;
-   Eina_List *l_after = NULL;
-   int u = 0, v = 0;
 
    tex = calloc(1, sizeof(Evas_GL_Texture));
    if (!tex) return NULL;
@@ -459,8 +614,6 @@ Evas_GL_Texture *
 evas_gl_common_texture_render_new(Evas_GL_Context *gc, int w, int h, int alpha)
 {
    Evas_GL_Texture *tex;
-   Eina_List *l_after = NULL;
-   int u = 0, v = 0;
 
    tex = calloc(1, sizeof(Evas_GL_Texture));
    if (!tex) return NULL;
@@ -496,6 +649,45 @@ evas_gl_common_texture_render_new(Evas_GL_Context *gc, int w, int h, int alpha)
    return tex;
 }
 
+Evas_GL_Texture *
+evas_gl_common_texture_dynamic_new(Evas_GL_Context *gc, Evas_GL_Image *im)
+{
+   Evas_GL_Texture *tex;
+
+   tex = calloc(1, sizeof(Evas_GL_Texture));
+   if (!tex) return NULL;
+   
+   tex->gc = gc;
+   tex->references = 1;
+   tex->alpha = im->alpha;
+   tex->x = 0;
+   tex->y = 0;
+   tex->w = im->w;
+   tex->h = im->h;
+   if (tex->alpha)
+     {
+        if (gc->shared->info.bgra)
+          tex->pt = _pool_tex_dynamic_new(gc, tex->w, tex->h, bgra_ifmt, bgra_fmt);
+        else
+          tex->pt = _pool_tex_dynamic_new(gc, tex->w, tex->h, bgra_ifmt, bgra_fmt);
+     }
+   else
+     {
+        if (gc->shared->info.bgra)
+          tex->pt = _pool_tex_dynamic_new(gc, tex->w, tex->h, bgra_ifmt, bgra_fmt);
+        else
+          tex->pt = _pool_tex_dynamic_new(gc, tex->w, tex->h, bgra_ifmt, bgra_fmt);
+     }
+   if (!tex->pt)
+     {
+        memset(tex, 0x44, sizeof(Evas_GL_Texture)); // mark as freed
+        free(tex);
+        return NULL;
+     }
+   
+   return tex;
+}
+
 void
 evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
 {
@@ -574,9 +766,9 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
                1, 1,
                fmt, tex->pt->dataformat,
                im->image.data + ((im->cache_entry.h - 1) * im->cache_entry.w) + (im->cache_entry.w - 1));
-   if (tex->pt->texture != tex->gc->shader.cur_tex)
+   if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex)
      {
-        glBindTexture(GL_TEXTURE_2D, tex->gc->shader.cur_tex);
+        glBindTexture(GL_TEXTURE_2D, tex->gc->pipe[0].shader.cur_tex);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
      }
 }
@@ -653,9 +845,9 @@ evas_gl_common_texture_alpha_update(Evas_GL_Texture *tex, DATA8 *pixels,
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    _tex_sub_2d(tex->x, tex->y, w, h, tex->pt->format, tex->pt->dataformat, 
                pixels);
-   if (tex->pt->texture != tex->gc->shader.cur_tex)
+   if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex)
      {
-        glBindTexture(GL_TEXTURE_2D, tex->gc->shader.cur_tex);
+        glBindTexture(GL_TEXTURE_2D, tex->gc->pipe[0].shader.cur_tex);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
      }
 }
@@ -664,8 +856,8 @@ Evas_GL_Texture *
 evas_gl_common_texture_yuv_new(Evas_GL_Context *gc, DATA8 **rows, int w, int h)
 {
    Evas_GL_Texture *tex;
-   Eina_List *l_after = NULL;
-   int u = 0, v = 0;
+//   Eina_List *l_after = NULL;
+//   int u = 0, v = 0;
 
    tex = calloc(1, sizeof(Evas_GL_Texture));
    if (!tex) return NULL;
@@ -725,8 +917,6 @@ evas_gl_common_texture_yuv_new(Evas_GL_Context *gc, DATA8 **rows, int w, int h)
 void
 evas_gl_common_texture_yuv_update(Evas_GL_Texture *tex, DATA8 **rows, int w, int h)
 {
-   int y;
-
    if (!tex->pt) return;
    // FIXME: works on lowest size 4 pixel high buffers. must also be multiple of 2
 #ifdef GL_UNPACK_ROW_LENGTH
@@ -748,6 +938,8 @@ evas_gl_common_texture_yuv_update(Evas_GL_Texture *tex, DATA8 **rows, int w, int
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    _tex_sub_2d(0, 0, w / 2, h / 2, tex->ptv->format, tex->ptv->dataformat, rows[h + (h / 2)]);
 #else
+   int y;
+
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    glBindTexture(GL_TEXTURE_2D, tex->pt->texture);
@@ -780,9 +972,9 @@ evas_gl_common_texture_yuv_update(Evas_GL_Texture *tex, DATA8 **rows, int w, int
           _tex_sub_2d(0, y, w / 2, 1, tex->ptv->format, tex->ptv->dataformat, rows[h + (h / 2) + y]);
      }
 #endif   
-   if (tex->pt->texture != tex->gc->shader.cur_tex)
+   if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex)
      {
-        glBindTexture(GL_TEXTURE_2D, tex->gc->shader.cur_tex);
+        glBindTexture(GL_TEXTURE_2D, tex->gc->pipe[0].shader.cur_tex);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
      }
 }
index 938429a..2042b4a 100644 (file)
@@ -20,7 +20,8 @@ GL_GLEW_LIBADD = @evas_engine_gl_glew_libs@ $(top_builddir)/src/modules/engines/
 
 pkgdir = $(libdir)/evas/modules/engines/gl_glew/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_GL_Glew.h
+includes_HEADERS = Evas_Engine_GL_Glew.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_GL_GLEW
 
index 37b0f43..8d21d4d 100644 (file)
@@ -1,3 +1,4 @@
+#include "evas_common.h" /* Also includes international specific stuff */
 #include "evas_engine.h"
 
 int _evas_engine_GL_glew_log_dom = -1;
@@ -65,7 +66,6 @@ eng_setup(Evas *e, void *in)
        evas_common_convert_init();
        evas_common_scale_init();
        evas_common_rectangle_init();
-       evas_common_gradient_init();
        evas_common_polygon_init();
        evas_common_line_init();
        evas_common_font_init();
@@ -335,244 +335,6 @@ eng_polygon_draw(void *data, void *context, void *surface, void *polygon, int x,
 //--//   evas_gl_common_poly_draw(re->window->gl_context, polygon, x, y);
 }
 
-static void
-eng_gradient2_color_np_stop_insert(void *data __UNUSED__, void *gradient __UNUSED__, int r __UNUSED__, int g __UNUSED__, int b __UNUSED__, int a __UNUSED__, float pos __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_clear(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_fill_transform_set(void *data __UNUSED__, void *gradient __UNUSED__, void *transform __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_fill_spread_set
-(void *data __UNUSED__, void *gradient __UNUSED__, int spread __UNUSED__)
-{
-}
-
-static void *
-eng_gradient2_linear_new(void *data __UNUSED__)
-{
-   return NULL;
-}
-
-static void
-eng_gradient2_linear_free(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_fill_set(void *data __UNUSED__, void *linear_gradient __UNUSED__, int x0 __UNUSED__, int y0 __UNUSED__, int x1 __UNUSED__, int y1 __UNUSED__)
-{
-}
-
-static int
-eng_gradient2_linear_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static int
-eng_gradient2_linear_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static void
-eng_gradient2_linear_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_render_post(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-}
-
-static void *
-eng_gradient2_radial_new(void *data __UNUSED__)
-{
-   return NULL;
-}
-
-static void
-eng_gradient2_radial_free(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_fill_set(void *data __UNUSED__, void *radial_gradient __UNUSED__, float cx __UNUSED__, float cy __UNUSED__, float rx __UNUSED__, float ry __UNUSED__)
-{
-}
-
-static int
-eng_gradient2_radial_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static int
-eng_gradient2_radial_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static void
-eng_gradient2_radial_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_render_post(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-}
-
-static void *
-eng_gradient_new(void *data __UNUSED__)
-{
-//--//      return evas_gl_common_gradient_new();
-   return NULL;
-}
-
-static void
-eng_gradient_color_stop_add(void *data __UNUSED__, void *gradient, int r, int g, int b, int a, int delta)
-{
-//--//      evas_gl_common_gradient_color_stop_add(gradient, r, g, b, a, delta);
-}
-
-static void
-eng_gradient_alpha_stop_add(void *data __UNUSED__, void *gradient, int a, int delta)
-{
-//--//      evas_gl_common_gradient_alpha_stop_add(gradient, a, delta);
-}
-
-static void
-eng_gradient_clear(void *data __UNUSED__, void *gradient)
-{
-//--//      evas_gl_common_gradient_clear(gradient);
-}
-
-static void
-eng_gradient_color_data_set(void *data __UNUSED__, void *gradient, void *map, int len, int has_alpha)
-{
-//--//      evas_gl_common_gradient_color_data_set(gradient, map, len, has_alpha);
-}
-
-static void
-eng_gradient_alpha_data_set(void *data __UNUSED__, void *gradient, void *alpha_map, int len)
-{
-//--//      evas_gl_common_gradient_alpha_data_set(gradient, alpha_map, len);
-}
-
-static void
-eng_gradient_free(void *data __UNUSED__, void *gradient)
-{
-//--//      evas_gl_common_gradient_free(gradient);
-}
-
-static void
-eng_gradient_fill_set(void *data __UNUSED__, void *gradient, int x, int y, int w, int h)
-{
-//--//      evas_gl_common_gradient_fill_set(gradient, x, y, w, h);
-}
-
-static void
-eng_gradient_fill_angle_set(void *data __UNUSED__, void *gradient, double angle)
-{
-//--//      evas_gl_common_gradient_fill_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_fill_spread_set(void *data __UNUSED__, void *gradient, int spread)
-{
-//--//      evas_gl_common_gradient_fill_spread_set(gradient, spread);
-}
-
-static void
-eng_gradient_angle_set(void *data __UNUSED__, void *gradient, double angle)
-{
-//--//      evas_gl_common_gradient_map_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_offset_set(void *data __UNUSED__, void *gradient, float offset)
-{
-//--//      evas_gl_common_gradient_map_offset_set(gradient, offset);
-}
-
-static void
-eng_gradient_direction_set(void *data __UNUSED__, void *gradient, int direction)
-{
-//--//      evas_gl_common_gradient_map_direction_set(gradient, direction);
-}
-
-static void
-eng_gradient_type_set(void *data __UNUSED__, void *gradient, char *name, char *params)
-{
-//--//      evas_gl_common_gradient_type_set(gradient, name, params);
-}
-
-static int
-eng_gradient_is_opaque(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->window->gl_context->dc = context;
-//--//      return evas_gl_common_gradient_is_opaque(re->window->gl_context, gradient, x, y, w, h);
-   return 0;
-}
-
-static int
-eng_gradient_is_visible(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->window->gl_context->dc = context;
-//--//      return evas_gl_common_gradient_is_visible(re->window->gl_context, gradient, x, y, w, h);
-   return 0;
-}
-
-static void
-eng_gradient_render_pre(void *data, void *context, void *gradient)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->window->gl_context->dc = context;
-//--//      evas_gl_common_gradient_render_pre(re->window->gl_context, gradient);
-}
-
-static void
-eng_gradient_render_post(void *data __UNUSED__, void *gradient)
-{
-//--//      evas_gl_common_gradient_render_post(gradient);
-}
-
-static void
-eng_gradient_draw(void *data, void *context, void *surface __UNUSED__, void *gradient, int x, int y, int w, int h)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   eng_window_use(re->window);
-   re->window->gl_context->dc = context;
-//--//      evas_gl_common_gradient_draw(re->window->gl_context, gradient, x, y, w, h);
-}
-
 static int
 eng_image_alpha_get(void *data, void *image)
 {
@@ -986,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 char *text)
+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)
 {
    Render_Engine *re;
 
@@ -1006,7 +768,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
                                              evas_gl_font_texture_new,
                                              evas_gl_font_texture_free,
                                              evas_gl_font_texture_draw);
-       evas_common_font_draw(im, context, font, x, y, text);
+       evas_common_font_draw(im, context, font, x, y, text, intl_props);
        evas_common_draw_context_font_ext_set(context,
                                              NULL,
                                              NULL,
@@ -1061,47 +823,6 @@ module_open(Evas_Module *em)
    ORD(polygon_points_clear);
    ORD(polygon_draw);
 
-   ORD(gradient2_color_np_stop_insert);
-   ORD(gradient2_clear);
-   ORD(gradient2_fill_transform_set);
-   ORD(gradient2_fill_spread_set);
-   ORD(gradient2_linear_new);
-   ORD(gradient2_linear_free);
-   ORD(gradient2_linear_fill_set);
-   ORD(gradient2_linear_is_opaque);
-   ORD(gradient2_linear_is_visible);
-   ORD(gradient2_linear_render_pre);
-   ORD(gradient2_linear_render_post);
-   ORD(gradient2_linear_draw);
-   ORD(gradient2_radial_new);
-   ORD(gradient2_radial_free);
-   ORD(gradient2_radial_fill_set);
-   ORD(gradient2_radial_is_opaque);
-   ORD(gradient2_radial_is_visible);
-   ORD(gradient2_radial_render_pre);
-   ORD(gradient2_radial_render_post);
-   ORD(gradient2_radial_draw);
-
-   ORD(gradient_new);
-   ORD(gradient_free);
-   ORD(gradient_color_stop_add);
-   ORD(gradient_alpha_stop_add);
-   ORD(gradient_color_data_set);
-   ORD(gradient_alpha_data_set);
-   ORD(gradient_clear);
-   ORD(gradient_fill_set);
-   ORD(gradient_fill_angle_set);
-   ORD(gradient_fill_spread_set);
-   ORD(gradient_angle_set);
-   ORD(gradient_offset_set);
-   ORD(gradient_direction_set);
-   ORD(gradient_type_set);
-   ORD(gradient_is_opaque);
-   ORD(gradient_is_visible);
-   ORD(gradient_render_pre);
-   ORD(gradient_render_post);
-   ORD(gradient_draw);
-
    ORD(image_load);
    ORD(image_new_from_data);
    ORD(image_new_from_copied_data);
index b275538..4af0ed5 100644 (file)
@@ -19,7 +19,8 @@ GL_SDL_LIBADD = @evas_engine_gl_sdl_libs@ $(top_builddir)/src/modules/engines/gl
 
 pkgdir = $(libdir)/evas/modules/engines/gl_sdl/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_GL_SDL.h
+includes_HEADERS = Evas_Engine_GL_SDL.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_GL_SDL
 
index bfbb120..6942e89 100644 (file)
@@ -1,4 +1,4 @@
-#include "evas_common.h"
+#include "evas_common.h" /* Also includes international specific stuff */
 #include "evas_engine.h"
 
 #include <dlfcn.h>      /* dlopen,dlclose,etc */
@@ -341,363 +341,6 @@ eng_polygon_draw(void *data, void *context, void *surface, void *polygon, int x,
    evas_gl_common_poly_draw(re->gl_context, polygon, x, y);
 }
 
-static void
-eng_gradient2_color_np_stop_insert(void *data __UNUSED__, void *gradient __UNUSED__, int r __UNUSED__, int g __UNUSED__, int b __UNUSED__, int a __UNUSED__, float pos __UNUSED__)
-{
-   evas_common_gradient2_color_np_stop_insert(gradient, r, g, b, a, pos);
-}
-
-static void
-eng_gradient2_clear(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-   evas_common_gradient2_clear(gradient);
-}
-
-static void
-eng_gradient2_fill_transform_set(void *data __UNUSED__, void *gradient __UNUSED__, void *transform __UNUSED__)
-{
-   evas_common_gradient2_fill_transform_set(gradient, transform);
-}
-
-static void
-eng_gradient2_fill_spread_set(void *data __UNUSED__, void *gradient __UNUSED__, int spread __UNUSED__)
-{
-   evas_common_gradient2_fill_spread_set(gradient, spread);
-}
-
-static void *
-eng_gradient2_linear_new(void *data __UNUSED__)
-{
-   return evas_common_gradient2_linear_new();
-}
-
-static void
-eng_gradient2_linear_free(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-   evas_common_gradient2_free(linear_gradient);
-}
-
-static void
-eng_gradient2_linear_fill_set(void *data __UNUSED__, void *linear_gradient __UNUSED__, float x0 __UNUSED__, float y0 __UNUSED__, float x1 __UNUSED__, float y1 __UNUSED__)
-{
-   evas_common_gradient2_linear_fill_set(linear_gradient, x0, y0, x1, y1);
-}
-
-static int
-eng_gradient2_linear_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)linear_gradient;
-
-   if (!dc || !gr || !gr->type.geometer)  return 0;
-   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-            gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient2_linear_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-
-   if (!dc || !linear_gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient2_linear_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)linear_gradient;
-   int  len;
-   
-   if (!dc || !gr || !gr->type.geometer)  return;
-   gr->type.geometer->geom_update(gr);
-   len = gr->type.geometer->get_map_len(gr);
-   evas_common_gradient2_map(dc, gr, len);
-}
-
-static void
-eng_gradient2_linear_render_post(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   re->gl_context->dc = context;
-     {
-        Evas_GL_Image *gim;
-        RGBA_Image *im;
-        RGBA_Draw_Context *dc = context;
-        int op = dc->render_op, cuse = dc->clip.use;
-        
-        im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
-        im = (RGBA_Image *)evas_cache_image_size_set(&im->cache_entry, w, h);
-        
-        dc->render_op = _EVAS_RENDER_FILL;
-        dc->clip.use = 0;
-        
-        // draw to buf, copy to tex, draw tex
-        evas_common_gradient2_draw(im, dc, 0, 0, w, h, linear_gradient);
-
-        gim = evas_gl_common_image_new_from_data(re->gl_context, w, h,
-                                                 im->image.data, 1,
-                                                 EVAS_COLORSPACE_ARGB8888);
-        dc->render_op = op;
-        dc->clip.use = cuse;
-        evas_gl_common_image_draw(re->gl_context, gim, 0, 0, w, h, x, y, w, h, 0);
-        evas_cache_image_drop(&im->cache_entry);
-        evas_gl_common_image_free(gim);
-     }
-}
-
-static void *
-eng_gradient2_radial_new(void *data __UNUSED__)
-{
-   return evas_common_gradient2_radial_new();
-}
-
-static void
-eng_gradient2_radial_free(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-   evas_common_gradient2_free(radial_gradient);
-}
-
-static void
-eng_gradient2_radial_fill_set(void *data __UNUSED__, void *radial_gradient __UNUSED__, float cx __UNUSED__, float cy __UNUSED__, float rx __UNUSED__, float ry __UNUSED__)
-{
-   evas_common_gradient2_radial_fill_set(radial_gradient, cx, cy, rx, ry);
-}
-
-static int
-eng_gradient2_radial_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)radial_gradient;
-   
-   if (!dc || !gr || !gr->type.geometer)  return 0;
-   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-            gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient2_radial_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   
-   if (!dc || !radial_gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient2_radial_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)radial_gradient;
-   int  len;
-   
-   if (!dc || !gr || !gr->type.geometer)  return;
-   gr->type.geometer->geom_update(gr);
-   len = gr->type.geometer->get_map_len(gr);
-   evas_common_gradient2_map(dc, gr, len);
-}
-
-static void
-eng_gradient2_radial_render_post(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   re->gl_context->dc = context;
-     {
-        Evas_GL_Image *gim;
-        RGBA_Image *im;
-        RGBA_Draw_Context *dc = context;
-        int op = dc->render_op, cuse = dc->clip.use;
-        
-        im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
-        im = (RGBA_Image *)evas_cache_image_size_set(&im->cache_entry, w, h);
-        
-        dc->render_op = _EVAS_RENDER_FILL;
-        dc->clip.use = 0;
-        
-        // draw to buf, copy to tex, draw tex
-        evas_common_gradient2_draw(im, dc, 0, 0, w, h, radial_gradient);
-
-        gim = evas_gl_common_image_new_from_data(re->gl_context, w, h,
-                                                 im->image.data, 1,
-                                                 EVAS_COLORSPACE_ARGB8888);
-        dc->render_op = op;
-        dc->clip.use = cuse;
-        evas_gl_common_image_draw(re->gl_context, gim, 0, 0, w, h, x, y, w, h, 0);
-        evas_cache_image_drop(&im->cache_entry);
-        evas_gl_common_image_free(gim);
-     }
-}
-
-static void *
-eng_gradient_new(void *data __UNUSED__)
-{
-   return evas_common_gradient_new();
-}
-
-static void
-eng_gradient_free(void *data __UNUSED__, void *gradient)
-{
-   evas_common_gradient_free(gradient);
-}
-
-static void
-eng_gradient_color_stop_add(void *data __UNUSED__, void *gradient, int r, int g, int b, int a, int delta)
-{
-   evas_common_gradient_color_stop_add(gradient, r, g, b, a, delta);
-}
-
-static void
-eng_gradient_alpha_stop_add(void *data __UNUSED__, void *gradient, int a, int delta)
-{
-   evas_common_gradient_alpha_stop_add(gradient, a, delta);
-}
-
-static void
-eng_gradient_color_data_set(void *data __UNUSED__, void *gradient, void *map, int len, int has_alpha)
-{
-   evas_common_gradient_color_data_set(gradient, map, len, has_alpha);
-}
-
-static void
-eng_gradient_alpha_data_set(void *data __UNUSED__, void *gradient, void *alpha_map, int len)
-{
-   evas_common_gradient_alpha_data_set(gradient, alpha_map, len);
-}
-
-static void
-eng_gradient_clear(void *data __UNUSED__, void *gradient)
-{
-   evas_common_gradient_clear(gradient);
-}
-
-static void
-eng_gradient_fill_set(void *data __UNUSED__, void *gradient, int x, int y, int w, int h)
-{
-   evas_common_gradient_fill_set(gradient, x, y, w, h);
-}
-
-static void
-eng_gradient_fill_angle_set(void *data __UNUSED__, void *gradient, double angle)
-{
-   evas_common_gradient_fill_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_fill_spread_set(void *data __UNUSED__, void *gradient, int spread)
-{
-   evas_common_gradient_fill_spread_set(gradient, spread);
-}
-
-static void
-eng_gradient_angle_set(void *data __UNUSED__, void *gradient, double angle)
-{
-   evas_common_gradient_map_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_offset_set(void *data __UNUSED__, void *gradient, float offset)
-{
-   evas_common_gradient_map_offset_set(gradient, offset);
-}
-
-static void
-eng_gradient_direction_set(void *data __UNUSED__, void *gradient, int direction)
-{
-   evas_common_gradient_map_direction_set(gradient, direction);
-}
-
-static void
-eng_gradient_type_set(void *data __UNUSED__, void *gradient, char *name, char *params)
-{
-   evas_common_gradient_type_set(gradient, name, params);
-}
-
-static int
-eng_gradient_is_opaque(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient *gr = (RGBA_Gradient *)gradient;
-   
-   if (!dc || !gr || !gr->type.geometer)  return 0;
-   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-            gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient_is_visible(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   
-   if (!dc || !gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient_render_pre(void *data, void *context, void *gradient)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient *gr = (RGBA_Gradient *)gradient;
-   int  len;
-   
-   if (!dc || !gr || !gr->type.geometer)  return;
-   gr->type.geometer->geom_set(gr);
-   len = gr->type.geometer->get_map_len(gr);
-   evas_common_gradient_map(dc, gr, len);
-}
-
-static void
-eng_gradient_render_post(void *data __UNUSED__, void *gradient)
-{
-}
-
-static void
-eng_gradient_draw(void *data, void *context, void *surface __UNUSED__, void *gradient, int x, int y, int w, int h)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   re->gl_context->dc = context;
-     {
-        Evas_GL_Image *gim;
-        RGBA_Image *im;
-        RGBA_Draw_Context *dc = context;
-        int op = dc->render_op, cuse = dc->clip.use;
-        
-        im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
-        im = (RGBA_Image *)evas_cache_image_size_set(&im->cache_entry, w, h);
-        
-        dc->render_op = _EVAS_RENDER_FILL;
-        dc->clip.use = 0;
-        
-        // draw to buf, copy to tex, draw tex
-        evas_common_gradient_draw(im, dc, 0, 0, w, h, gradient);
-
-        gim = evas_gl_common_image_new_from_data(re->gl_context, w, h,
-                                                 im->image.data, 1,
-                                                 EVAS_COLORSPACE_ARGB8888);
-        dc->render_op = op;
-        dc->clip.use = cuse;
-        evas_gl_common_image_draw(re->gl_context, gim, 0, 0, w, h, x, y, w, h, 0);
-        evas_cache_image_drop(&im->cache_entry);
-        evas_gl_common_image_free(gim);
-     }
-}
-
 static int
 eng_image_alpha_get(void *data, void *image)
 {
@@ -1172,7 +815,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 char *text)
+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)
 {
    Render_Engine *re;
 
@@ -1192,7 +835,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
                                              evas_gl_font_texture_new,
                                              evas_gl_font_texture_free,
                                              evas_gl_font_texture_draw);
-       evas_common_font_draw(im, context, font, x, y, text);
+       evas_common_font_draw(im, context, font, x, y, text, intl_props);
        evas_common_draw_context_font_ext_set(context,
                                              NULL,
                                              NULL,
@@ -1248,46 +891,6 @@ module_open(Evas_Module *em)
    ORD(polygon_points_clear);
    ORD(polygon_draw);
 
-   ORD(gradient2_color_np_stop_insert);
-   ORD(gradient2_clear);
-   ORD(gradient2_fill_transform_set);
-   ORD(gradient2_fill_spread_set);
-   ORD(gradient2_linear_new);
-   ORD(gradient2_linear_free);
-   ORD(gradient2_linear_fill_set);
-   ORD(gradient2_linear_is_opaque);
-   ORD(gradient2_linear_is_visible);
-   ORD(gradient2_linear_render_pre);
-   ORD(gradient2_linear_render_post);
-   ORD(gradient2_linear_draw);
-   ORD(gradient2_radial_new);
-   ORD(gradient2_radial_free);
-   ORD(gradient2_radial_fill_set);
-   ORD(gradient2_radial_is_opaque);
-   ORD(gradient2_radial_is_visible);
-   ORD(gradient2_radial_render_pre);
-   ORD(gradient2_radial_render_post);
-   ORD(gradient2_radial_draw);
-
-   ORD(gradient_new);
-   ORD(gradient_free);
-   ORD(gradient_color_stop_add);
-   ORD(gradient_alpha_stop_add);
-   ORD(gradient_color_data_set);
-   ORD(gradient_alpha_data_set);
-   ORD(gradient_clear);
-   ORD(gradient_fill_set);
-   ORD(gradient_fill_angle_set);
-   ORD(gradient_fill_spread_set);
-   ORD(gradient_angle_set);
-   ORD(gradient_offset_set);
-   ORD(gradient_direction_set);
-   ORD(gradient_type_set);
-   ORD(gradient_is_opaque);
-   ORD(gradient_is_visible);
-   ORD(gradient_render_pre);
-   ORD(gradient_render_post);
-   ORD(gradient_draw);
    ORD(image_load);
    ORD(image_new_from_data);
    ORD(image_new_from_copied_data);
@@ -1364,7 +967,6 @@ _sdl_output_setup          (int w, int h, int fullscreen, int noframe)
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
index 7421af2..de391da 100644 (file)
@@ -20,7 +20,8 @@ GL_X11_LIBADD = @evas_engine_gl_x11_libs@ $(top_builddir)/src/modules/engines/gl
 
 pkgdir = $(libdir)/evas/modules/engines/gl_x11/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_GL_X11.h
+includes_HEADERS = Evas_Engine_GL_X11.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_GL_X11
 
index e9d2484..4fffd30 100644 (file)
@@ -1,3 +1,4 @@
+#include "evas_common.h" /* Also includes international specific stuff */
 #include "evas_engine.h"
 
 #include <dlfcn.h>      /* dlopen,dlclose,etc */
 // GLX
 #endif
 
+typedef struct _Render_Engine Render_Engine;
+
+struct _Render_Engine
+{
+   Evas_GL_X11_Window      *win;
+   Evas_Engine_Info_GL_X11 *info;
+   Evas                    *evas;
+   int                      end;
+   
+   XrmDatabase   xrdb; // xres - dpi
+   struct { // xres - dpi
+      int        dpi; // xres - dpi
+   } xr; // xres - dpi
+};
+
+static int initted = 0;
+static int gl_wins = 0;
+
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
 
 #ifndef EGL_NATIVE_PIXMAP_KHR
@@ -159,21 +178,6 @@ xrdb_user_query(const char *name, const char *cls, char **type, XrmValue *val)
    return EINA_FALSE;
 }
 
-typedef struct _Render_Engine Render_Engine;
-
-struct _Render_Engine
-{
-   Evas_GL_X11_Window      *win;
-   Evas_Engine_Info_GL_X11 *info;
-   Evas                    *evas;
-   int                      end;
-   
-   XrmDatabase   xrdb; // xres - dpi
-   struct { // xres - dpi
-      int        dpi; // xres - dpi
-   } xr; // xres - dpi
-};
-
 static void *
 eng_info(Evas *e)
 {
@@ -199,9 +203,6 @@ eng_info_free(Evas *e __UNUSED__, void *info)
    free(in);
 }
 
-static int initted = 0;
-static int gl_wins = 0;
-
 static int
 eng_setup(Evas *e, void *in)
 {
@@ -304,7 +305,6 @@ eng_setup(Evas *e, void *in)
              evas_common_convert_init();
              evas_common_scale_init();
              evas_common_rectangle_init();
-             evas_common_gradient_init();
              evas_common_polygon_init();
              evas_common_line_init();
              evas_common_font_init();
@@ -325,9 +325,13 @@ eng_setup(Evas *e, void *in)
             (info->info.destination_alpha != re->win->alpha) ||
             (info->info.rotation != re->win->rot))
           {
+             int inc = 0;
+             
              if (re->win)
                {
+                  re->win->gl_context->references++;
                   eng_window_free(re->win);
+                  inc = 1;
                   gl_wins--;
                }
              re->win = eng_window_new(info->info.display,
@@ -342,6 +346,8 @@ eng_setup(Evas *e, void *in)
                                       info->info.destination_alpha,
                                       info->info.rotation);
              if (re->win) gl_wins++;
+             if ((re->win) && (inc))
+                re->win->gl_context->references--;
           }
         else if ((re->win->w != e->output.w) ||
                  (re->win->h != e->output.h))
@@ -574,7 +580,11 @@ eng_output_flush(void *data)
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
 #ifdef FRAMECOUNT
    double t0 = get_time();
-#endif   
+#endif
+   if (re->info->vsync)
+      eglSwapInterval(re->win->egl_disp, 1);
+   else
+      eglSwapInterval(re->win->egl_disp, 0);
    eglSwapBuffers(re->win->egl_disp, re->win->egl_surface[0]);
 #ifdef FRAMECOUNT
    double t1 = get_time();
@@ -740,366 +750,6 @@ eng_polygon_draw(void *data, void *context, void *surface __UNUSED__, void *poly
    evas_gl_common_poly_draw(re->win->gl_context, polygon, x, y);
 }
 
-static void
-eng_gradient2_color_np_stop_insert(void *data __UNUSED__, void *gradient __UNUSED__, int r __UNUSED__, int g __UNUSED__, int b __UNUSED__, int a __UNUSED__, float pos __UNUSED__)
-{
-   evas_common_gradient2_color_np_stop_insert(gradient, r, g, b, a, pos);
-}
-
-static void
-eng_gradient2_clear(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-   evas_common_gradient2_clear(gradient);
-}
-
-static void
-eng_gradient2_fill_transform_set(void *data __UNUSED__, void *gradient __UNUSED__, void *transform __UNUSED__)
-{
-   evas_common_gradient2_fill_transform_set(gradient, transform);
-}
-
-static void
-eng_gradient2_fill_spread_set(void *data __UNUSED__, void *gradient __UNUSED__, int spread __UNUSED__)
-{
-   evas_common_gradient2_fill_spread_set(gradient, spread);
-}
-
-static void *
-eng_gradient2_linear_new(void *data __UNUSED__)
-{
-   return evas_common_gradient2_linear_new();
-}
-
-static void
-eng_gradient2_linear_free(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-   evas_common_gradient2_free(linear_gradient);
-}
-
-static void
-eng_gradient2_linear_fill_set(void *data __UNUSED__, void *linear_gradient __UNUSED__, float x0 __UNUSED__, float y0 __UNUSED__, float x1 __UNUSED__, float y1 __UNUSED__)
-{
-   evas_common_gradient2_linear_fill_set(linear_gradient, x0, y0, x1, y1);
-}
-
-static int
-eng_gradient2_linear_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)linear_gradient;
-
-   if (!dc || !gr || !gr->type.geometer)  return 0;
-   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-            gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient2_linear_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-
-   if (!dc || !linear_gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient2_linear_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)linear_gradient;
-   int  len;
-   
-   if (!dc || !gr || !gr->type.geometer)  return;
-   gr->type.geometer->geom_update(gr);
-   len = gr->type.geometer->get_map_len(gr);
-   evas_common_gradient2_map(dc, gr, len);
-}
-
-static void
-eng_gradient2_linear_render_post(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   re->win->gl_context->dc = context;
-     {
-        Evas_GL_Image *gim;
-        RGBA_Image *im;
-        RGBA_Draw_Context *dc = context;
-        int op = dc->render_op, cuse = dc->clip.use;
-        
-        im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
-        im = (RGBA_Image *)evas_cache_image_size_set(&im->cache_entry, w, h);
-        
-        dc->render_op = _EVAS_RENDER_FILL;
-        dc->clip.use = 0;
-        
-        // draw to buf, copy to tex, draw tex
-        evas_common_gradient2_draw(im, dc, 0, 0, w, h, linear_gradient);
-
-        gim = evas_gl_common_image_new_from_data(re->win->gl_context, w, h,
-                                                 im->image.data, 1,
-                                                 EVAS_COLORSPACE_ARGB8888);
-        dc->render_op = op;
-        dc->clip.use = cuse;
-        evas_gl_common_image_draw(re->win->gl_context, gim, 0, 0, w, h, x, y, w, h, 0);
-        evas_cache_image_drop(&im->cache_entry);
-        evas_gl_common_image_free(gim);
-     }
-}
-
-static void *
-eng_gradient2_radial_new(void *data __UNUSED__)
-{
-   return evas_common_gradient2_radial_new();
-}
-
-static void
-eng_gradient2_radial_free(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-   evas_common_gradient2_free(radial_gradient);
-}
-
-static void
-eng_gradient2_radial_fill_set(void *data __UNUSED__, void *radial_gradient __UNUSED__, float cx __UNUSED__, float cy __UNUSED__, float rx __UNUSED__, float ry __UNUSED__)
-{
-   evas_common_gradient2_radial_fill_set(radial_gradient, cx, cy, rx, ry);
-}
-
-static int
-eng_gradient2_radial_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)radial_gradient;
-   
-   if (!dc || !gr || !gr->type.geometer)  return 0;
-   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-            gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient2_radial_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   
-   if (!dc || !radial_gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient2_radial_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)radial_gradient;
-   int  len;
-   
-   if (!dc || !gr || !gr->type.geometer)  return;
-   gr->type.geometer->geom_update(gr);
-   len = gr->type.geometer->get_map_len(gr);
-   evas_common_gradient2_map(dc, gr, len);
-}
-
-static void
-eng_gradient2_radial_render_post(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   re->win->gl_context->dc = context;
-     {
-        Evas_GL_Image *gim;
-        RGBA_Image *im;
-        RGBA_Draw_Context *dc = context;
-        int op = dc->render_op, cuse = dc->clip.use;
-        
-        im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
-        im = (RGBA_Image *)evas_cache_image_size_set(&im->cache_entry, w, h);
-        
-        dc->render_op = _EVAS_RENDER_FILL;
-        dc->clip.use = 0;
-        
-        // draw to buf, copy to tex, draw tex
-        evas_common_gradient2_draw(im, dc, 0, 0, w, h, radial_gradient);
-
-        gim = evas_gl_common_image_new_from_data(re->win->gl_context, w, h,
-                                                 im->image.data, 1,
-                                                 EVAS_COLORSPACE_ARGB8888);
-        dc->render_op = op;
-        dc->clip.use = cuse;
-        evas_gl_common_image_draw(re->win->gl_context, gim, 0, 0, w, h, x, y, w, h, 0);
-        evas_cache_image_drop(&im->cache_entry);
-        evas_gl_common_image_free(gim);
-     }
-}
-
-static void *
-eng_gradient_new(void *data __UNUSED__)
-{
-   return evas_common_gradient_new();
-}
-
-static void
-eng_gradient_free(void *data __UNUSED__, void *gradient)
-{
-   evas_common_gradient_free(gradient);
-}
-
-static void
-eng_gradient_color_stop_add(void *data __UNUSED__, void *gradient, int r, int g, int b, int a, int delta)
-{
-   evas_common_gradient_color_stop_add(gradient, r, g, b, a, delta);
-}
-
-static void
-eng_gradient_alpha_stop_add(void *data __UNUSED__, void *gradient, int a, int delta)
-{
-   evas_common_gradient_alpha_stop_add(gradient, a, delta);
-}
-
-static void
-eng_gradient_color_data_set(void *data __UNUSED__, void *gradient, void *map, int len, int has_alpha)
-{
-   evas_common_gradient_color_data_set(gradient, map, len, has_alpha);
-}
-
-static void
-eng_gradient_alpha_data_set(void *data __UNUSED__, void *gradient, void *alpha_map, int len)
-{
-   evas_common_gradient_alpha_data_set(gradient, alpha_map, len);
-}
-
-static void
-eng_gradient_clear(void *data __UNUSED__, void *gradient)
-{
-   evas_common_gradient_clear(gradient);
-}
-
-static void
-eng_gradient_fill_set(void *data __UNUSED__, void *gradient, int x, int y, int w, int h)
-{
-   evas_common_gradient_fill_set(gradient, x, y, w, h);
-}
-
-static void
-eng_gradient_fill_angle_set(void *data __UNUSED__, void *gradient, double angle)
-{
-   evas_common_gradient_fill_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_fill_spread_set(void *data __UNUSED__, void *gradient, int spread)
-{
-   evas_common_gradient_fill_spread_set(gradient, spread);
-}
-
-static void
-eng_gradient_angle_set(void *data __UNUSED__, void *gradient, double angle)
-{
-   evas_common_gradient_map_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_offset_set(void *data __UNUSED__, void *gradient, float offset)
-{
-   evas_common_gradient_map_offset_set(gradient, offset);
-}
-
-static void
-eng_gradient_direction_set(void *data __UNUSED__, void *gradient, int direction)
-{
-   evas_common_gradient_map_direction_set(gradient, direction);
-}
-
-static void
-eng_gradient_type_set(void *data __UNUSED__, void *gradient, char *name, char *params)
-{
-   evas_common_gradient_type_set(gradient, name, params);
-}
-
-static int
-eng_gradient_is_opaque(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient *gr = (RGBA_Gradient *)gradient;
-   
-   if (!dc || !gr || !gr->type.geometer)  return 0;
-   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-            gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient_is_visible(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   
-   if (!dc || !gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient_render_pre(void *data, void *context, void *gradient)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient *gr = (RGBA_Gradient *)gradient;
-   int  len;
-   
-   if (!dc || !gr || !gr->type.geometer)  return;
-   gr->type.geometer->geom_set(gr);
-   len = gr->type.geometer->get_map_len(gr);
-   evas_common_gradient_map(dc, gr, len);
-}
-
-static void
-eng_gradient_render_post(void *data __UNUSED__, void *gradient)
-{
-}
-
-static void
-eng_gradient_draw(void *data, void *context, void *surface __UNUSED__, void *gradient, int x, int y, int w, int h)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   re->win->gl_context->dc = context;
-     {
-        Evas_GL_Image *gim;
-        RGBA_Image *im;
-        RGBA_Draw_Context *dc = context;
-        int op = dc->render_op, cuse = dc->clip.use;
-        
-        im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
-        im = (RGBA_Image *)evas_cache_image_size_set(&im->cache_entry, w, h);
-        
-        dc->render_op = _EVAS_RENDER_FILL;
-        dc->clip.use = 0;
-        
-        // draw to buf, copy to tex, draw tex
-        evas_common_gradient_draw(im, dc, 0, 0, w, h, gradient);
-
-        gim = evas_gl_common_image_new_from_data(re->win->gl_context, w, h,
-                                                 im->image.data, 1,
-                                                 EVAS_COLORSPACE_ARGB8888);
-        dc->render_op = op;
-        dc->clip.use = cuse;
-        evas_gl_common_image_draw(re->win->gl_context, gim, 0, 0, w, h, x, y, w, h, 0);
-        evas_cache_image_drop(&im->cache_entry);
-        evas_gl_common_image_free(gim);
-     }
-}
-
 static int
 eng_image_alpha_get(void *data, void *image)
 {
@@ -1133,12 +783,19 @@ eng_image_alpha_set(void *data, void *image, int has_alpha)
    re = (Render_Engine *)data;
    if (!image) return NULL;
    im = image;
+   if (im->alpha == has_alpha) return image;
    if (im->native.data)
      {
         im->alpha = has_alpha;
         return image;
      }
    eng_window_use(re->win);
+   if ((im->tex) && (im->tex->pt->dyn.img))
+     {
+        im->alpha = has_alpha;
+        im->tex->alpha = im->alpha;
+        return image;
+     }
    /* FIXME: can move to gl_common */
    if (im->cs.space != EVAS_COLORSPACE_ARGB8888) return im;
    if ((has_alpha) && (im->im->cache_entry.flags.alpha)) return image;
@@ -1279,7 +936,6 @@ struct _Native
 static void
 _native_bind_cb(void *data, void *image)
 {
-   Render_Engine *re = data;
    Evas_GL_Image *im = image;
    Native *n = im->native.data;
    
@@ -1290,17 +946,15 @@ _native_bind_cb(void *data, void *image)
           {
              glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, n->egl_surface);
              if (eglGetError() != EGL_SUCCESS)
-               {
-                  printf("Error:  glEGLImageTargetTexture2DOES() fail.\n");
-               }
+                printf("Error:  glEGLImageTargetTexture2DOES() fail.\n");
           }
         else
-          {
-             printf("Try glEGLImageTargetTexture2DOES on EGL with no support\n");
-          }
+           printf("Try glEGLImageTargetTexture2DOES on EGL with no support\n");
      }
 #else
 # ifdef GLX_BIND_TO_TEXTURE_TARGETS_EXT
+   Render_Engine *re = data;
+   
    if (glsym_glXBindTexImage)
      {
         glsym_glXBindTexImage(re->win->disp, n->glx_pixmap, 
@@ -1308,9 +962,7 @@ _native_bind_cb(void *data, void *image)
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
      }
    else
-     {
-        printf("Try glXBindTexImage on GLX with no support\n");
-     }
+      printf("Try glXBindTexImage on GLX with no support\n");
 # endif
 #endif
 }
@@ -1318,14 +970,15 @@ _native_bind_cb(void *data, void *image)
 static void
 _native_unbind_cb(void *data, void *image)
 {
-   Render_Engine *re = data;
    Evas_GL_Image *im = image;
-   Native *n = im->native.data;
 
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
    // nothing
 #else
 # ifdef GLX_BIND_TO_TEXTURE_TARGETS_EXT
+   Render_Engine *re = data;
+   Native *n = im->native.data;
+   
    if (glsym_glXReleaseTexImage)
      {
         glsym_glXReleaseTexImage(re->win->disp, n->glx_pixmap, 
@@ -1333,9 +986,7 @@ _native_unbind_cb(void *data, void *image)
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
      }
    else
-     {
-        printf("Try glXReleaseTexImage on GLX with no support\n");
-     }
+      printf("Try glXReleaseTexImage on GLX with no support\n");
 # endif
 #endif
 }
@@ -1346,7 +997,10 @@ _native_free_cb(void *data, void *image)
    Render_Engine *re = data;
    Evas_GL_Image *im = image;
    Native *n = im->native.data;
+   uint32_t pmid;
 
+   pmid = n->pixmap;
+   eina_hash_del(re->win->gl_context->shared->native_hash, &pmid, im);
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
    if (n->egl_surface)
      {
@@ -1355,14 +1009,10 @@ _native_free_cb(void *data, void *image)
              glsym_eglDestroyImage(re->win->egl_disp,
                                    n->egl_surface);
              if (eglGetError() != EGL_SUCCESS)
-               {
-                  printf("Error:  eglDestroyImage() fail.\n");
-               }
+                printf("Error:  eglDestroyImage() fail.\n");
           }
         else
-          {
-             printf("Try eglDestroyImage on EGL with no support\n");
-          }
+           printf("Try eglDestroyImage on EGL with no support\n");
      }
 #else
 # ifdef GLX_BIND_TO_TEXTURE_TARGETS_EXT
@@ -1377,9 +1027,7 @@ _native_free_cb(void *data, void *image)
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                }
              else
-               {
-                  printf("Try glXReleaseTexImage on GLX with no support\n");
-               }
+                printf("Try glXReleaseTexImage on GLX with no support\n");
           }
         if (glsym_glXDestroyPixmap)
           {
@@ -1387,9 +1035,7 @@ _native_free_cb(void *data, void *image)
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
         else
-          {
-             printf("Try glXDestroyPixmap on GLX with no support\n");
-          }
+           printf("Try glXDestroyPixmap on GLX with no support\n");
         n->glx_pixmap = 0;
      }
 # endif
@@ -1402,16 +1048,18 @@ _native_free_cb(void *data, void *image)
    free(n);
 }
 
-static void
+static void *
 eng_image_native_set(void *data, void *image, void *native)
 {
    Render_Engine *re = (Render_Engine *)data;
    Evas_Native_Surface *ns = native;
-   Evas_GL_Image *im = image;
+   Evas_GL_Image *im = image, *im2 = NULL;
    Visual *vis = NULL;
    Pixmap pm = 0;
-
-   if (!im) return;
+   Native *n = NULL;
+   uint32_t pmid;
+   
+   if (!im) return NULL;
    if (ns)
      {
         vis = ns->data.x11.visual;
@@ -1420,32 +1068,50 @@ eng_image_native_set(void *data, void *image, void *native)
           {
              Evas_Native_Surface *n = im->native.data;
              if ((n->data.x11.visual == vis) && (n->data.x11.pixmap == pm))
-               {
-                  return;
-               }
+                return im;
           }
      }
-   if ((!ns) && (!im->native.data)) return;
-#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+   if ((!ns) && (!im->native.data)) return im;
+   
+   eng_window_use(re->win);
+   
    if (im->native.data)
      {
         if (im->native.func.free)
-          im->native.func.free(im->native.func.data, im);
+           im->native.func.free(im->native.func.data, im);
         evas_gl_common_image_native_disable(im);
-        im->native.data = NULL;
      }
-   if (native)
+   
+   pmid = pm;
+   im2 = eina_hash_find(re->win->gl_context->shared->native_hash, &pmid);
+   if (im2 == im) return im;
+   if (im2)
+     {
+        n = im2->native.data;
+        if (n)
+          {
+             im2->references++;
+             evas_gl_common_image_free(im);
+             return im2;
+          }
+     }
+   im2 = evas_gl_common_image_new_from_data(re->win->gl_context, 
+                                            im->w, im->h, NULL, im->alpha,
+                                            EVAS_COLORSPACE_ARGB8888);
+   evas_gl_common_image_free(im);
+   im = im2;
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+   if (native) 
      {
-        Native *n;
-        
         n = calloc(1, sizeof(Native));
         if (n)
           {
              EGLConfig egl_config;
              int config_attrs[20];
-             int num_config, i;
+             int num_config, i = 0;
              
-             i = 0;
+             eina_hash_add(re->win->gl_context->shared->native_hash, &pmid, im);
+                  
              config_attrs[i++] = EGL_RED_SIZE;
              config_attrs[i++] = 8;
              config_attrs[i++] = EGL_GREEN_SIZE;
@@ -1466,11 +1132,19 @@ eng_image_native_set(void *data, void *image, void *native)
              
              if (!eglChooseConfig(re->win->egl_disp, config_attrs, 
                                   &egl_config, 1, &num_config))
-               {
-                  printf("ERROR: eglChooseConfig() failed for pixmap 0x%x, num_config = %i\n", (unsigned int)pm, num_config);
-               }
+                printf("ERROR: eglChooseConfig() failed for pixmap 0x%x, num_config = %i\n", (unsigned int)pm, num_config);
              n->pixmap = pm;
              n->visual = vis;
+             if (glsym_eglCreateImage)
+                n->egl_surface = glsym_eglCreateImage(re->win->egl_disp,
+                                                      EGL_NO_CONTEXT,
+                                                      EGL_NATIVE_PIXMAP_KHR,
+                                                      (void *)pm,
+                                                      NULL);
+             else
+                printf("Try eglCreateImage on EGL with no support\n");
+             if (!n->egl_surface)
+                printf("ERROR: eglCreatePixmapSurface() for 0x%x failed\n", (unsigned int)pm);
              im->native.yinvert     = 1;
              im->native.loose       = 0;
              im->native.data        = n;
@@ -1480,39 +1154,16 @@ eng_image_native_set(void *data, void *image, void *native)
              im->native.func.free   = _native_free_cb;
              im->native.target      = GL_TEXTURE_2D;
              im->native.mipmap      = 0;
-             if (glsym_eglCreateImage)
-               {
-                  n->egl_surface = glsym_eglCreateImage(re->win->egl_disp,
-                                                        EGL_NO_CONTEXT,
-                                                        EGL_NATIVE_PIXMAP_KHR,
-                                                        (void *)pm,
-                                                        NULL);
-               }
-             else
-               {
-                  printf("Try eglCreateImage on EGL with no support\n");
-               }
-             if (!n->egl_surface)
-               {
-                  printf("ERROR: eglCreatePixmapSurface() for 0x%x failed\n", (unsigned int)pm);
-               }
              evas_gl_common_image_native_enable(im);
           }
      }
 #else
 # ifdef GLX_BIND_TO_TEXTURE_TARGETS_EXT
-   if (im->native.data)
-     {
-        if (im->native.func.free)
-          im->native.func.free(im->native.func.data, im);
-        evas_gl_common_image_native_disable(im);
-     }
    if (native)
      {
         int dummy;
         unsigned int w, h, depth = 32, border;
         Window wdummy;
-        Native *n;
 
         // fixme: round trip :(
         XGetGeometry(re->win->disp, pm, &wdummy, &dummy, &dummy, 
@@ -1524,16 +1175,15 @@ eng_image_native_set(void *data, void *image, void *native)
              int target = 0;
              int i = 0;
 
+             eina_hash_add(re->win->gl_context->shared->native_hash, &pmid, im);
              if ((re->win->depth_cfg[depth].tex_target &
                   GLX_TEXTURE_2D_BIT_EXT) 
 //                 && (1) // we assume npo2 for now
                  // size is pow2 || mnpo2 supported
-                 )
-               {
-                  target = GLX_TEXTURE_2D_EXT;
-               }
+                )
+                target = GLX_TEXTURE_2D_EXT;
              else if ((re->win->depth_cfg[depth].tex_target &
-                      GLX_TEXTURE_RECTANGLE_BIT_EXT))
+                       GLX_TEXTURE_RECTANGLE_BIT_EXT))
                {
                   printf("rect!!! (not handled)\n");
                   target = GLX_TEXTURE_RECTANGLE_EXT;
@@ -1543,14 +1193,10 @@ eng_image_native_set(void *data, void *image, void *native)
                   printf("broken text-from-pixmap\n");
                   if (!(re->win->depth_cfg[depth].tex_target &
                         GLX_TEXTURE_2D_BIT_EXT))
-                    {
-                       target = GLX_TEXTURE_RECTANGLE_EXT;
-                    }
+                     target = GLX_TEXTURE_RECTANGLE_EXT;
                   else if (!(re->win->depth_cfg[depth].tex_target &
                              GLX_TEXTURE_RECTANGLE_BIT_EXT))
-                    {
-                       target = GLX_TEXTURE_2D_EXT;
-                    }
+                     target = GLX_TEXTURE_2D_EXT;
                }
              
              
@@ -1566,49 +1212,43 @@ eng_image_native_set(void *data, void *image, void *native)
                }
              
              pixmap_att[i++] = 0;
-
+             
              memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
              n->pixmap = pm;
              n->visual = vis;
              n->fbc = re->win->depth_cfg[depth].fbc;
-             im->native.yinvert     = re->win->depth_cfg[depth].yinvert;
-             im->native.loose       = re->win->detected.loose_binding;
-             im->native.data        = n;
-             im->native.func.data   = re;
-             im->native.func.bind   = _native_bind_cb;
-             im->native.func.unbind = _native_unbind_cb;
-             im->native.func.free   = _native_free_cb;
              if (glsym_glXCreatePixmap)
-               {
-                  n->glx_pixmap = glsym_glXCreatePixmap(re->win->disp, n->fbc, 
-                                                        n->pixmap, pixmap_att);
-               }
+                n->glx_pixmap = glsym_glXCreatePixmap(re->win->disp, 
+                                                      n->fbc, 
+                                                      n->pixmap, 
+                                                      pixmap_att);
              else
-               {
-                  printf("Try glXCreatePixmap on GLX with no support\n");
-               }
+                printf("Try glXCreatePixmap on GLX with no support\n");
              if (n->glx_pixmap)
                {
-//             printf("new native texture for %x | %4i x %4i @ %2i = %p\n",
-//                    pm, w, h, depth, n->glx_pixmap);
+//                  printf("%p: new native texture for %x | %4i x %4i @ %2i = %p\n",
+//                         n, pm, w, h, depth, n->glx_pixmap);
                   if (!target)
                     {
                        printf("no target :(\n");
                        if (glsym_glXQueryDrawable)
-                         glsym_glXQueryDrawable(re->win->disp, n->pixmap, GLX_TEXTURE_TARGET_EXT, &target);
+                          glsym_glXQueryDrawable(re->win->disp,
+                                                 n->pixmap, 
+                                                 GLX_TEXTURE_TARGET_EXT, 
+                                                 &target);
                     }
                   if (target == GLX_TEXTURE_2D_EXT)
                     {
                        im->native.target = GL_TEXTURE_2D;
                        im->native.mipmap = re->win->depth_cfg[depth].mipmap;
                     }
-#ifdef GL_TEXTURE_RECTANGLE_ARB             
+#  ifdef GL_TEXTURE_RECTANGLE_ARB             
                   else if (target == GLX_TEXTURE_RECTANGLE_EXT)
                     {
                        im->native.target = GL_TEXTURE_RECTANGLE_ARB;
                        im->native.mipmap = 0;
                     }
-#endif             
+#  endif             
                   else
                     {
                        im->native.target = GL_TEXTURE_2D;
@@ -1617,15 +1257,21 @@ eng_image_native_set(void *data, void *image, void *native)
                     }
                }
              else
-               {
-                  printf("ERROR: GLX Pixmap create fail\n");
-               }
+                printf("ERROR: GLX Pixmap create fail\n");
+             im->native.yinvert     = re->win->depth_cfg[depth].yinvert;
+             im->native.loose       = re->win->detected.loose_binding;
+             im->native.data        = n;
+             im->native.func.data   = re;
+             im->native.func.bind   = _native_bind_cb;
+             im->native.func.unbind = _native_unbind_cb;
+             im->native.func.free   = _native_free_cb;
 
              evas_gl_common_image_native_enable(im);
           }
      }
 # endif   
 #endif
+   return im;
 }
 
 static void *
@@ -1718,6 +1364,13 @@ eng_image_size_set(void *data, void *image, int w, int h)
         return image;
      }
    eng_window_use(re->win);
+   if ((im->tex) && (im->tex->pt->dyn.img))
+     {
+        evas_gl_common_texture_free(im->tex);
+        im->tex = NULL;
+        im->tex = evas_gl_common_texture_dynamic_new(im->gc, im);
+        return image;
+     }
    im_old = image;
    if ((eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P601_PL) ||
        (eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P709_PL))
@@ -1776,6 +1429,11 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data)
         *image_data = NULL;
         return im;
      }
+   if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.data))
+     {
+        *image_data = im->tex->pt->dyn.data;
+        return im;
+     }
    eng_window_use(re->win);
    evas_cache_image_load_data(&im->im->cache_entry);
    switch (im->cs.space)
@@ -1825,6 +1483,28 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data)
    im = image;
    if (im->native.data) return image;
    eng_window_use(re->win);
+   if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.data))
+     {
+        if (im->tex->pt->dyn.data == image_data)
+          {
+             return image;
+          }
+        else
+          {
+            int w, h;
+
+            w = im->im->cache_entry.w;
+            h = im->im->cache_entry.h;
+            im2 = eng_image_new_from_data(data, w, h, image_data,
+                                          eng_image_alpha_get(data, image),
+                                          eng_image_colorspace_get(data, image));
+            if (!im2) return im;
+            evas_gl_common_image_free(im);
+            im = im2;
+             evas_gl_common_image_dirty(im, 0, 0, 0, 0);
+             return im;
+          }
+     }
    switch (im->cs.space)
      {
       case EVAS_COLORSPACE_ARGB8888:
@@ -1907,6 +1587,15 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
 static void
 eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
 {
+   if (image) evas_gl_common_image_scale_hint_set(image, hint);
+}
+
+static int
+eng_image_scale_hint_get(void *data __UNUSED__, void *image)
+{
+   Evas_GL_Image *gim = image;
+   if (!gim) return EVAS_IMAGE_SCALE_HINT_NONE;
+   return gim->scale_hint;
 }
 
 static void
@@ -1936,14 +1625,31 @@ eng_image_map_surface_free(void *data __UNUSED__, void *surface)
    evas_gl_common_image_free(surface);
 }
 
+static void
+eng_image_content_hint_set(void *data __UNUSED__, void *image, int hint)
+{
+   if (image) evas_gl_common_image_content_hint_set(image, hint);
+}
+
 static int
-eng_image_scale_hint_get(void *data __UNUSED__, void *image)
+eng_image_content_hint_get(void *data __UNUSED__, void *image)
 {
-   return EVAS_IMAGE_SCALE_HINT_NONE;
+   Evas_GL_Image *gim = image;
+   if (!gim) return EVAS_IMAGE_CONTENT_HINT_NONE;
+   return gim->content_hint;
 }
 
 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 char *text)
+eng_image_stride_get(void *data, void *image, int *stride)
+{
+   Render_Engine *re = (Render_Engine *)data;
+   Evas_GL_Image *im = image;
+   *stride = im->w;
+   if ((im->tex) && (im->tex->pt->dyn.img)) *stride = im->tex->pt->dyn.w;
+}
+
+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)
 {
    Render_Engine *re;
 
@@ -1964,7 +1670,7 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
                                              evas_gl_font_texture_new,
                                              evas_gl_font_texture_free,
                                              evas_gl_font_texture_draw);
-       evas_common_font_draw(im, context, font, x, y, text);
+       evas_common_font_draw(im, context, font, x, y, text, intl_props);
        evas_common_draw_context_font_ext_set(context,
                                              NULL,
                                              NULL,
@@ -2027,46 +1733,6 @@ module_open(Evas_Module *em)
    ORD(polygon_points_clear);
    ORD(polygon_draw);
 
-   ORD(gradient2_color_np_stop_insert);
-   ORD(gradient2_clear);
-   ORD(gradient2_fill_transform_set);
-   ORD(gradient2_fill_spread_set);
-   ORD(gradient2_linear_new);
-   ORD(gradient2_linear_free);
-   ORD(gradient2_linear_fill_set);
-   ORD(gradient2_linear_is_opaque);
-   ORD(gradient2_linear_is_visible);
-   ORD(gradient2_linear_render_pre);
-   ORD(gradient2_linear_render_post);
-   ORD(gradient2_linear_draw);
-   ORD(gradient2_radial_new);
-   ORD(gradient2_radial_free);
-   ORD(gradient2_radial_fill_set);
-   ORD(gradient2_radial_is_opaque);
-   ORD(gradient2_radial_is_visible);
-   ORD(gradient2_radial_render_pre);
-   ORD(gradient2_radial_render_post);
-   ORD(gradient2_radial_draw);
-
-   ORD(gradient_new);
-   ORD(gradient_free);
-   ORD(gradient_color_stop_add);
-   ORD(gradient_alpha_stop_add);
-   ORD(gradient_color_data_set);
-   ORD(gradient_alpha_data_set);
-   ORD(gradient_clear);
-   ORD(gradient_fill_set);
-   ORD(gradient_fill_angle_set);
-   ORD(gradient_fill_spread_set);
-   ORD(gradient_angle_set);
-   ORD(gradient_offset_set);
-   ORD(gradient_direction_set);
-   ORD(gradient_type_set);
-   ORD(gradient_is_opaque);
-   ORD(gradient_is_visible);
-   ORD(gradient_render_pre);
-   ORD(gradient_render_post);
-   ORD(gradient_draw);
    ORD(image_load);
    ORD(image_new_from_data);
    ORD(image_new_from_copied_data);
@@ -2089,15 +1755,20 @@ module_open(Evas_Module *em)
    ORD(image_colorspace_get);
    ORD(image_native_set);
    ORD(image_native_get);
+   
    ORD(font_draw);
    
    ORD(image_scale_hint_set);
    ORD(image_scale_hint_get);
+   ORD(image_stride_get);
    
    ORD(image_map4_draw);
    ORD(image_map_surface_new);
    ORD(image_map_surface_free);
    
+   ORD(image_content_hint_set);
+   ORD(image_content_hint_get);
+   
    /* now advertise out own api */
    em->functions = (void *)(&func);
    return 1;
index 83595a1..bab9d65 100644 (file)
@@ -202,6 +202,7 @@ eng_window_new(Display *disp,
         printf("Error: eglMakeCurrent() fail.\n");
         printf("Error: error # was: 0x%x\n", eglGetError());
      }
+    _evas_gl_x11_window = gw;
 
    vendor = glGetString(GL_VENDOR);
    renderer = glGetString(GL_RENDERER);
@@ -288,6 +289,17 @@ eng_window_new(Display *disp,
         fprintf(stderr, "version: %s\n", version);
         
         if (strstr(vendor, "NVIDIA"))
+           // FIXME: also same as tegra2 - maybe check renderer too
+           // 
+           // vendor: NVIDIA Corporation
+           // renderer: NVIDIA Tegra
+           // version: OpenGL ES 2.0
+           // 
+           // vs (for example)
+           // 
+           // vendor: NVIDIA Corporation
+           // renderer: GeForce GT 220/PCI/SSE2
+           // version: 3.2.0 NVIDIA 195.36.24
           {
              gw->detected.loose_binding = 1;
           }
@@ -385,6 +397,9 @@ eng_window_new(Display *disp,
        eng_window_free(gw);
        return NULL;
      }
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+   gw->gl_context->egldisp = gw->egl_disp;
+#endif   
    evas_gl_common_context_use(gw->gl_context);
    evas_gl_common_context_resize(gw->gl_context, w, h, rot);
    win_count++;
@@ -394,22 +409,28 @@ eng_window_new(Display *disp,
 void
 eng_window_free(Evas_GL_X11_Window *gw)
 {
+   int ref = 0;
    win_count--;
+   eng_window_use(gw);
    if (gw == _evas_gl_x11_window) _evas_gl_x11_window = NULL;
-   if (gw->gl_context) evas_gl_common_context_free(gw->gl_context);
+   if (gw->gl_context)
+      {
+         ref = gw->gl_context->references - 1;
+         evas_gl_common_context_free(gw->gl_context);
+      }
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
    if (gw->egl_surface[0] != EGL_NO_SURFACE)
      eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
-   if (win_count == 0)
+   if (ref == 0)
      {
         if (context) eglDestroyContext(gw->egl_disp, context);
-        eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
         eglTerminate(gw->egl_disp);
         context = EGL_NO_CONTEXT;
      }
+   eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 #else
    if (gw->glxwin) glXDestroyWindow(gw->disp, gw->glxwin);
-   if (win_count == 0)
+   if (ref == 0)
      {
         if (context) glXDestroyContext(gw->disp, context);
         if (rgba_context) glXDestroyContext(gw->disp, rgba_context);
index 597e454..df92e17 100644 (file)
@@ -16,7 +16,8 @@ QUARTZ_LIBADD = @evas_engine_quartz_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/quartz/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Quartz.h
+includes_HEADERS = Evas_Engine_Quartz.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_QUARTZ
 
index 160f043..4c96754 100644 (file)
@@ -1,6 +1,3 @@
-/*
- * vim:ts=3:sw=3:sts=3:expandtab
- */
 #include <ApplicationServices/ApplicationServices.h>
 
 #include "evas_common.h"
@@ -92,7 +89,6 @@ eng_output_setup(CGContextRef context, int w, int h)
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
@@ -497,231 +493,6 @@ eng_polygon_draw(void *data, void *context, void *surface, void *polygon)
    CGContextFillPath(re->ctx);
 }
 
-#pragma mark Gradient Manipulation & Drawing
-
-static void *
-eng_gradient_new(void *data)
-{
-   Evas_Quartz_Gradient *gradient = calloc(1, sizeof(Evas_Quartz_Gradient));
-   if (!gradient) return NULL;
-
-   gradient->grad = evas_common_gradient_new();
-   if (!(gradient->grad))
-   {
-      free(gradient);
-      return NULL;
-   }
-
-   gradient->changed = 1;
-   gradient->buf = NULL;
-
-   return gradient;
-}
-
-static void
-eng_gradient_free(void *data, void *gradient)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   if (gr->grad) evas_common_gradient_free(gr->grad);
-   if (gr->im) eng_image_free(data, gr->im);
-   if (gr->buf) free(gr->buf);
-   free(gr);
-}
-
-static void
-eng_gradient_color_stop_add(void *data, void *gradient, int r, int g, int b, int a, int delta)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_color_stop_add(gr->grad, r, g, b, a, delta);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_alpha_stop_add(void *data, void *gradient, int a, int delta)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_alpha_stop_add(gr->grad, a, delta);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_color_data_set(void *data, void *gradient, void *map, int len, int has_alpha)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_color_data_set(gr->grad, map, len, has_alpha);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_alpha_data_set(void *data, void *gradient, void *alpha_map, int len)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_alpha_data_set(gr->grad, alpha_map, len);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_clear(void *data, void *gradient)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_clear(gr->grad);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_fill_set(void *data, void *gradient, int x, int y, int w, int h)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_fill_set(gr->grad, x, y, w, h);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_fill_angle_set(void *data, void *gradient, double angle)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_fill_angle_set(gr->grad, angle);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_fill_spread_set(void *data, void *gradient, int spread)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_fill_spread_set(gr->grad, spread);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_angle_set(void *data, void *gradient, double angle)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_map_angle_set(gr->grad, angle);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_offset_set(void *data, void *gradient, float offset)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_map_offset_set(gr->grad, offset);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_direction_set(void *data, void *gradient, int direction)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_map_direction_set(gr->grad, direction);
-   gr->changed = 1;
-}
-
-static void
-eng_gradient_type_set(void *data, void *gradient, char *name, char *params)
-{
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-   if (!gr) return;
-   evas_common_gradient_type_set(gr->grad, name, params);
-   gr->changed = 1;
-}
-
-static int
-eng_gradient_is_opaque(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient *grad;
-   if (!gradient) return 0;
-
-   grad = ((Evas_Quartz_Gradient *)gradient)->grad;
-
-   if (!grad || !grad->type.geometer) return 0;
-
-   return !(grad->type.geometer->has_alpha(grad, dc->render_op) |
-              grad->type.geometer->has_mask(grad, dc->render_op));
-}
-
-static int
-eng_gradient_is_visible(void *data, void *context, void *gradient, int x, int y, int w, int h)
-{
-   if (!gradient) return 0;
-   return 1;
-}
-
-static void
-eng_gradient_render_pre(void *data, void *context, void *gradient)
-{
-   int  len;
-   RGBA_Gradient *grad;
-
-   if (!context || !gradient) return;
-   grad = ((Evas_Quartz_Gradient *)gradient)->grad;
-   if (!grad || !grad->type.geometer) return;
-   grad->type.geometer->geom_set(grad);
-   len = grad->type.geometer->get_map_len(grad);
-   evas_common_gradient_map(context, grad, len);
-   ((Evas_Quartz_Gradient *)gradient)->changed = 1;
-}
-
-static void
-eng_gradient_render_post(void *data, void *gradient)
-{
-}
-
-static void
-eng_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   Evas_Quartz_Gradient *gr = (Evas_Quartz_Gradient *)gradient;
-
-   INF("#Gradient#");
-   INF("Fill: %i %i %i %i", gr->grad->fill.x, gr->grad->fill.y, gr->grad->fill.w, gr->grad->fill.h);
-   INF("Type: %s %s", gr->grad->type.name, gr->grad->type.params);
-   INF("XYWH: %i %i %i %i", x, y, w, h);
-   INF("Geom: %p %p", gr->grad->type.geometer, gr->grad->type.geometer->get_fill_func);
-   INF("Map: len: %d angle: %f direction: %d offset: %f", gr->grad->map.len, gr->grad->map.angle, gr->grad->map.direction, gr->grad->map.offset);
-   INF("Color: nstops: %d len: %d", gr->grad->color.nstops, gr->grad->color.len);
-   INF("Alpha: nstops: %d len: %d", gr->grad->alpha.nstops, gr->grad->alpha.len);
-   INF("");
-
-   if ((gr->sw != w) || (gr->sh != h))
-      gr->changed = 1;
-
-   if ((gr->changed) || (!gr->im))
-   {
-      if (gr->buf && ((gr->sw != w) || (gr->sh != h)))
-      {
-         free(gr->buf);
-         gr->buf = NULL;
-      }
-
-      if (!gr->buf)
-         gr->buf = calloc(w * h, 4);
-
-      eng_image_free(data, gr->im);
-      gr->im = eng_image_new_from_data(data, w, h, gr->buf, 1, EVAS_COLORSPACE_ARGB8888);
-      dc->render_op = _EVAS_RENDER_FILL;
-      evas_common_gradient_draw((RGBA_Image *) &gr->im->im->cache_entry, dc, 0, 0, w, h, gr->grad);
-      evas_common_cpu_end_opt();
-      gr->sw = w;
-      gr->sh = h;
-      gr->changed = 0;
-   }
-
-   eng_image_draw(data, context, NULL, gr->im, 0, 0, 0, 0, x, y, w, h, 0);
-}
-
 #pragma mark Image Manipulation & Drawing
 
 static void *
@@ -807,7 +578,7 @@ eng_image_data_preload_request(void *data __UNUSED__, void *image, const void *t
 {
    Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
 
-   if (!im && !im->im) return ;
+   if (!im || !im->im) return ;
    evas_cache_image_preload_data(&im->im->cache_entry, target);
 }
 
@@ -816,7 +587,7 @@ eng_image_data_preload_cancel(void *data __UNUSED__, void *image, const void *ta
 {
    Evas_Quartz_Image *im = (Evas_Quartz_Image *)image;
 
-   if (!im && !im->im) return ;
+   if (!im || !im->im) return ;
    evas_cache_image_preload_cancel(&im->im->cache_entry, target);
 }
 
@@ -1249,7 +1020,7 @@ eng_font_max_descent_get(void *data, void *font)
 }
 
 static void
-eng_font_string_size_get(void *data, void *font, const char *text, int *w, int *h)
+eng_font_string_size_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props, int *w, int *h)
 {
    Render_Engine *re = (Render_Engine *)data;
    Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
@@ -1279,28 +1050,28 @@ 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)
+eng_font_h_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props)
 {
    int w;
 
-   eng_font_string_size_get(data, font, text, &w, NULL);
+   eng_font_string_size_get(data, font, text, intl_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)
+eng_font_v_advance_get(void *data, void *font, const char *text, const Evas_BiDi_Props *intl_props)
 {
    int h;
 
-   eng_font_string_size_get(data, font, text, NULL, &h);
+   eng_font_string_size_get(data, font, text, intl_props, NULL, &h);
 
    return h;
 }
 
 static int
-eng_font_char_coords_get(void *data, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch)
+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)
 {
    Evas_Quartz_Font *loaded_font = (Evas_Quartz_Font *)font;
 
@@ -1320,7 +1091,7 @@ eng_font_char_coords_get(void *data, void *font, const char *text, int pos, int
 }
 
 static int
-eng_font_char_at_coords_get(void *data, void *font, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch)
+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)
 {
    // 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;
@@ -1332,8 +1103,8 @@ eng_font_char_at_coords_get(void *data, void *font, const char *text, int x, int
    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, stringIndex, cx, cy, NULL, NULL);
-   eng_font_char_coords_get(data, font, text, stringIndex + 1, cw, NULL, NULL, NULL);
+   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);
 
    if (cw && cx) *cw -= *cx;
    if (ch) *ch = loaded_font->size;
@@ -1359,7 +1130,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)
+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)
 {
    Render_Engine *re = (Render_Engine *)data;
    Evas_Quartz_Context *ctxt = (Evas_Quartz_Context *)context;
@@ -1479,25 +1250,6 @@ module_open(Evas_Module *em)
    ORD(font_memory_load);
    ORD(font_string_size_get);
    ORD(font_v_advance_get);
-   ORD(gradient_new);
-   ORD(gradient_free);
-   ORD(gradient_color_stop_add);
-   ORD(gradient_alpha_stop_add);
-   ORD(gradient_color_data_set);
-   ORD(gradient_alpha_data_set);
-   ORD(gradient_clear);
-   ORD(gradient_fill_set);
-   ORD(gradient_fill_angle_set);
-   ORD(gradient_fill_spread_set);
-   ORD(gradient_angle_set);
-   ORD(gradient_offset_set);
-   ORD(gradient_direction_set);
-   ORD(gradient_type_set);
-   ORD(gradient_is_opaque);
-   ORD(gradient_is_visible);
-   ORD(gradient_render_pre);
-   ORD(gradient_render_post);
-   ORD(gradient_draw);
    ORD(image_alpha_get);
    ORD(image_alpha_set);
    ORD(image_colorspace_get);
index a32e232..c259c07 100644 (file)
@@ -84,15 +84,4 @@ struct _Evas_Quartz_Font
    int               size;
 };
 
-typedef struct _Evas_Quartz_Gradient Evas_Quartz_Gradient;
-
-struct _Evas_Quartz_Gradient
-{
-   DATA32            *buf;
-   RGBA_Gradient     *grad;
-   Evas_Quartz_Image *im;
-   unsigned char     changed : 1;
-   int               sw, sh;
-};
-
 #endif
index 67e26fc..852e869 100644 (file)
@@ -1,9 +1,10 @@
 #ifndef _EVAS_QUARTZ_PRIVATE_H_
 #define _EVAS_QUARTZ_PRIVATE_H_
 
+#include "evas_common.h"/* Also includes international specific stuff */
 #include "evas_engine.h"
 
-CG_EXTERN void CGContextResetClip (CGContextRef); // undocumented CoreGraphics function to clear clip rect/*
+CG_EXTERN void CGContextResetClip (CGContextRef); // undocumented CoreGraphics function to clear clip rect
 
 static inline void flip_pixels(int *y, int *h, void *re);
 
@@ -45,25 +46,6 @@ static void *eng_polygon_point_add(void *data, void *context, void *polygon, int
 static void *eng_polygon_points_clear(void *data, void *context, void *polygon);
 static void eng_polygon_draw(void *data, void *context, void *surface, void *polygon);
 
-static void *eng_gradient_new(void *data);
-static void eng_gradient_free(void *data, void *gradient);
-static void eng_gradient_color_stop_add(void *data, void *gradient, int r, int g, int b, int a, int delta);
-static void eng_gradient_alpha_stop_add(void *data, void *gradient, int a, int delta);
-static void eng_gradient_color_data_set(void *data, void *gradient, void *map, int len, int has_alpha);
-static void eng_gradient_alpha_data_set(void *data, void *gradient, void *alpha_map, int len);
-static void eng_gradient_clear(void *data, void *gradient);
-static void eng_gradient_fill_set(void *data, void *gradient, int x, int y, int w, int h);
-static void eng_gradient_fill_angle_set(void *data, void *gradient, double angle);
-static void eng_gradient_fill_spread_set(void *data, void *gradient, int spread);
-static void eng_gradient_angle_set(void *data, void *gradient, double angle);
-static void eng_gradient_offset_set(void *data, void *gradient, float offset);
-static void eng_gradient_direction_set(void *data, void *gradient, int direction);
-static void eng_gradient_type_set(void *data, void *gradient, char *name, char *params);
-static int eng_gradient_is_opaque(void *data, void *context, void *gradient, int x, int y, int w, int h);
-static int eng_gradient_is_visible(void *data, void *context, void *gradient, int x, int y, int w, int h);
-static void eng_gradient_render_pre(void *data, void *context, void *gradient);
-static void eng_gradient_render_post(void *data, void *gradient);
-static void eng_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h);
 static void *eng_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo);
 
 static void *eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
@@ -93,7 +75,7 @@ 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, int *w, int *h);
+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);
 static int eng_font_v_advance_get(void *data, void *font, const char *text);
index 64c354a..fa40b7f 100644 (file)
@@ -1,4 +1,4 @@
-#include "evas_common.h"
+#include "evas_common.h"/* Also includes international specific stuff */
 #include "evas_common_soft16.h"
 
 /*
@@ -203,264 +203,6 @@ eng_polygon_draw(void *data __UNUSED__, void *context, void *surface, void *poly
    soft16_polygon_draw(surface, context, polygon, x, y);
 }
 
-
-static void
-eng_gradient2_color_np_stop_insert(void *data __UNUSED__, void *gradient __UNUSED__, int r __UNUSED__, int g __UNUSED__, int b __UNUSED__, int a __UNUSED__, float pos __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_clear(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_fill_transform_set(void *data __UNUSED__, void *gradient __UNUSED__, void *transform __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_fill_spread_set(void *data __UNUSED__, void *gradient __UNUSED__, int spread __UNUSED__)
-{
-}
-
-static void *
-eng_gradient2_linear_new(void *data __UNUSED__)
-{
-   return NULL;
-}
-
-static void
-eng_gradient2_linear_free(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_fill_set(void *data __UNUSED__, void *linear_gradient __UNUSED__, float x0 __UNUSED__, float y0 __UNUSED__, float x1 __UNUSED__, float y1 __UNUSED__)
-{
-}
-
-static int
-eng_gradient2_linear_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static int
-eng_gradient2_linear_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static void
-eng_gradient2_linear_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_render_post(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-}
-
-static void *
-eng_gradient2_radial_new(void *data __UNUSED__)
-{
-   return NULL;
-}
-
-static void
-eng_gradient2_radial_free(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_fill_set(void *data __UNUSED__, void *radial_gradient __UNUSED__, float cx __UNUSED__, float cy __UNUSED__, float rx __UNUSED__, float ry __UNUSED__)
-{
-}
-
-static int
-eng_gradient2_radial_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static int
-eng_gradient2_radial_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static void
-eng_gradient2_radial_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_render_post(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-}
-
-static void *
-eng_gradient_new(void *data __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-   return NULL;
-//   return evas_common_gradient_new();
-}
-
-static void
-eng_gradient_free(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_free(gradient);
-}
-
-static void
-eng_gradient_color_stop_add(void *data __UNUSED__, void *gradient __UNUSED__, int r __UNUSED__, int g __UNUSED__, int b __UNUSED__, int a __UNUSED__, int delta __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_color_stop_add(gradient, r, g, b, a, delta);
-}
-
-static void
-eng_gradient_alpha_stop_add(void *data __UNUSED__, void *gradient __UNUSED__, int a __UNUSED__, int delta __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_alpha_stop_add(gradient, a, delta);
-}
-
-static void
-eng_gradient_color_data_set(void *data __UNUSED__, void *gradient __UNUSED__, void *map __UNUSED__, int len __UNUSED__, int has_alpha __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_color_data_set(gradient, map, len, has_alpha);
-}
-
-static void
-eng_gradient_alpha_data_set(void *data __UNUSED__, void *gradient __UNUSED__, void *alpha_map __UNUSED__, int len __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_alpha_data_set(gradient, alpha_map, len);
-}
-
-static void
-eng_gradient_clear(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_clear(gradient);
-}
-
-static void
-eng_gradient_fill_set(void *data __UNUSED__, void *gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_fill_set(gradient, x, y, w, h);
-}
-
-static void
-eng_gradient_fill_angle_set(void *data __UNUSED__, void *gradient __UNUSED__, double angle __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_fill_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_fill_spread_set(void *data __UNUSED__, void *gradient __UNUSED__, int spread __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_fill_spread_set(gradient, spread);
-}
-
-static void
-eng_gradient_angle_set(void *data __UNUSED__, void *gradient __UNUSED__, double angle __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_map_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_offset_set(void *data __UNUSED__, void *gradient __UNUSED__, float offset __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_map_offset_set(gradient, offset);
-}
-
-static void
-eng_gradient_direction_set(void *data __UNUSED__, void *gradient __UNUSED__, int direction __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_map_direction_set(gradient, direction);
-}
-
-static void
-eng_gradient_type_set(void *data __UNUSED__, void *gradient __UNUSED__, char *name __UNUSED__, char *params __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-//   evas_common_gradient_type_set(gradient, name, params);
-}
-
-static int
-eng_gradient_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-   return 0;
-//   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-//   RGBA_Gradient *gr = (RGBA_Gradient *)gradient;
-//
-//   if (!dc || !gr || !gr->type.geometer)  return 0;
-//   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-//              gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-   return 0;
-//   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-//
-//   if (!dc || !gradient)  return 0;
-//   return 1;
-}
-
-static void
-eng_gradient_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *gradient __UNUSED__)
-{
-//   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-//   RGBA_Gradient *gr = (RGBA_Gradient *)gradient;
-//   int  len;
-//
-//   if (!dc || !gr || !gr->type.geometer)  return;
-//   gr->type.geometer->geom_set(gr);
-//   len = gr->type.geometer->get_map_len(gr);
-//   evas_common_gradient_map(dc, gr, len);
-   NOT_IMPLEMENTED();
-}
-
-static void
-eng_gradient_render_post(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-   NOT_IMPLEMENTED();
-}
-
-static void
-eng_gradient_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-//   evas_common_gradient_draw(surface, context, x, y, w, h, gradient);
-//   evas_common_cpu_end_opt();
-   NOT_IMPLEMENTED();
-}
-
 static int
 eng_image_alpha_get(void *data __UNUSED__, void *image)
 {
@@ -516,10 +258,11 @@ eng_image_colorspace_set(void *data __UNUSED__, void *image __UNUSED__, int cspa
    NOT_IMPLEMENTED();
 }
 
-static void
+static void *
 eng_image_native_set(void *data __UNUSED__, void *image __UNUSED__, void *native __UNUSED__)
 {
    NOT_IMPLEMENTED();
+   return NULL;
 }
 
 static void *
@@ -762,55 +505,55 @@ eng_font_max_descent_get(void *data __UNUSED__, void *font)
 }
 
 static void
-eng_font_string_size_get(void *data __UNUSED__, void *font, const char *text, int *w, int *h)
+eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h)
 {
-   evas_common_font_query_size(font, text, w, h);
+   evas_common_font_query_size(font, text, intl_props, w, h);
 }
 
 static int
-eng_font_inset_get(void *data __UNUSED__, void *font, const char *text)
+eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text)
 {
    return evas_common_font_query_inset(font, text);
 }
 
 static int
-eng_font_h_advance_get(void *data __UNUSED__, void *font, const char *text)
+eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
 {
    int h, v;
 
-   evas_common_font_query_advance(font, text, &h, &v);
+   evas_common_font_query_advance(font, text, intl_props, &h, &v);
    return h;
 }
 
 static int
-eng_font_v_advance_get(void *data __UNUSED__, void *font, const char *text)
+eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
 {
    int h, v;
 
-   evas_common_font_query_advance(font, text, &h, &v);
+   evas_common_font_query_advance(font, text, intl_props, &h, &v);
    return v;
 }
 
 static int
-eng_font_char_coords_get(void *data __UNUSED__, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch)
+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)
 {
-   return evas_common_font_query_char_coords(font, text, pos, cx, cy, cw, ch);
+   return evas_common_font_query_char_coords(font, text, intl_props, pos, cx, cy, cw, ch);
 }
 
 static int
-eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const char *text, 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_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
 {
-   return evas_common_font_query_text_at_pos(font, text, x, y, cx, cy, cw, ch);
+   return evas_common_font_query_char_at_coords(font, text, intl_props, x, y, cx, cy, cw, ch);
 }
 
 static int
-eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const char *text, int x, int y)
+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)
 {
-   return evas_common_font_query_last_up_to_pos(font, text, x, y);
+   return evas_common_font_query_last_up_to_pos(font, text, intl_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 char *text)
+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)
 {
    static RGBA_Image    *im = NULL;
    Soft16_Image         *dst = surface;
@@ -823,7 +566,7 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, i
                                         soft16_font_glyph_new,
                                         soft16_font_glyph_free,
                                         soft16_font_glyph_draw);
-   evas_common_font_draw(im, context, font, x, y, text);
+   evas_common_font_draw(im, context, font, x, y, text, intl_props);
    evas_common_draw_context_font_ext_set(context,
                                         NULL,
                                         NULL,
@@ -920,49 +663,6 @@ static Evas_Func func =
      eng_polygon_point_add,
      eng_polygon_points_clear,
      eng_polygon_draw,
-     /* gradient draw funcs */
-     eng_gradient2_color_np_stop_insert,
-     eng_gradient2_clear,
-     eng_gradient2_fill_transform_set,
-     eng_gradient2_fill_spread_set,
-     
-     eng_gradient2_linear_new,
-     eng_gradient2_linear_free,
-     eng_gradient2_linear_fill_set,
-     eng_gradient2_linear_is_opaque,
-     eng_gradient2_linear_is_visible,
-     eng_gradient2_linear_render_pre,
-     eng_gradient2_linear_render_post,
-     eng_gradient2_linear_draw,
-     
-     eng_gradient2_radial_new,
-     eng_gradient2_radial_free,
-     eng_gradient2_radial_fill_set,
-     eng_gradient2_radial_is_opaque,
-     eng_gradient2_radial_is_visible,
-     eng_gradient2_radial_render_pre,
-     eng_gradient2_radial_render_post,
-     eng_gradient2_radial_draw,
-     
-     eng_gradient_new,
-     eng_gradient_free,
-     eng_gradient_color_stop_add,
-     eng_gradient_alpha_stop_add,
-     eng_gradient_color_data_set,
-     eng_gradient_alpha_data_set,
-     eng_gradient_clear,
-     eng_gradient_fill_set,
-     eng_gradient_fill_angle_set,
-     eng_gradient_fill_spread_set,
-     eng_gradient_angle_set,
-     eng_gradient_offset_set,
-     eng_gradient_direction_set,
-     eng_gradient_type_set,
-     eng_gradient_is_opaque,
-     eng_gradient_is_visible,
-     eng_gradient_render_pre,
-     eng_gradient_render_post,
-     eng_gradient_draw,
      /* image draw funcs */
      eng_image_load,
      eng_image_new_from_data,
index 321227c..c075691 100644 (file)
@@ -22,7 +22,8 @@ SOFTWARE_16_DDRAW_LIBADD = @evas_engine_software_16_ddraw_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/software_16_ddraw/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Software_16_DDraw.h
+includes_HEADERS = Evas_Engine_Software_16_DDraw.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_SOFTWARE_16_DDRAW
 
index 90f1162..247b5f4 100644 (file)
@@ -126,7 +126,6 @@ eng_setup(Evas *e, void *in)
        evas_common_convert_init();
        evas_common_scale_init();
        evas_common_rectangle_init();
-       evas_common_gradient_init();
        evas_common_polygon_init();
        evas_common_line_init();
        evas_common_font_init();
index 75ee709..bcaa15b 100644 (file)
@@ -12,7 +12,8 @@ evas_engine.h
 
 pkgdir = $(libdir)/evas/modules/engines/software_16_sdl/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_SDL_16.h
+includes_HEADERS = Evas_Engine_SDL_16.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_SOFTWARE_SDL
 
index 049da61..f9bf9fe 100644 (file)
@@ -5,7 +5,7 @@
 #include <time.h>
 #include <SDL/SDL.h>
 
-#include "evas_common.h"
+#include "evas_common.h"/* Also includes international specific stuff */
 #include "evas_engine.h"
 int _evas_engine_soft16_sdl_log_dom = -1;
 
@@ -129,7 +129,6 @@ _sdl16_output_setup(int w, int h, int rotation, int fullscreen, int noframe, int
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
@@ -877,7 +876,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 char *text)
+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)
 {
    static RGBA_Image            *im = NULL;
    SDL_Engine_Image_Entry       *eim = surface;
@@ -899,7 +898,7 @@ evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface,
                                          soft16_font_glyph_new,
                                          soft16_font_glyph_free,
                                          soft16_font_glyph_draw);
-   evas_common_font_draw(im, context, font, x, y, text);
+   evas_common_font_draw(im, context, font, x, y, text, intl_props);
    evas_common_draw_context_font_ext_set(context,
                                          NULL,
                                          NULL,
index 8c7d780..984b418 100644 (file)
@@ -24,7 +24,8 @@ SOFTWARE_16_WINCE_LIBADD = @evas_engine_software_16_wince_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/software_16_wince/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Software_16_WinCE.h
+includes_HEADERS = Evas_Engine_Software_16_WinCE.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_SOFTWARE_16_WINCE
 
index b994a9a..4a29ff2 100644 (file)
@@ -160,7 +160,6 @@ eng_setup(Evas *e, void *in)
        evas_common_convert_init();
        evas_common_scale_init();
        evas_common_rectangle_init();
-       evas_common_gradient_init();
        evas_common_polygon_init();
        evas_common_line_init();
        evas_common_font_init();
index 45106ed..979f315 100644 (file)
@@ -21,7 +21,8 @@ SOFTWARE_16_X11_LIBADD = @evas_engine_software_16_x11_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/software_16_x11/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Software_16_X11.h
+includes_HEADERS = Evas_Engine_Software_16_X11.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_SOFTWARE_16_X11
 
index 7f753fc..425323a 100644 (file)
@@ -178,7 +178,6 @@ eng_setup(Evas *e, void *in)
        evas_common_convert_init();
        evas_common_scale_init();
        evas_common_rectangle_init();
-       evas_common_gradient_init();
        evas_common_polygon_init();
        evas_common_line_init();
        evas_common_font_init();
diff --git a/src/modules/engines/software_8/Makefile.am b/src/modules/engines/software_8/Makefile.am
new file mode 100644 (file)
index 0000000..9f100f6
--- /dev/null
@@ -0,0 +1,38 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/src/lib \
+-I$(top_srcdir)/src/lib/include \
+-I$(top_srcdir)/src/modules/engines \
+@FREETYPE_CFLAGS@ \
+@EINA_CFLAGS@
+
+AM_CFLAGS = @WIN32_CFLAGS@
+
+if BUILD_ENGINE_SOFTWARE_8
+
+SOFTWARE_8_SOURCES = evas_engine.c
+
+pkgdir = $(libdir)/evas/modules/engines/software_8/$(MODULE_ARCH)
+
+if !EVAS_STATIC_BUILD_SOFTWARE_8_X11
+
+pkg_LTLIBRARIES = module.la
+module_la_SOURCES = $(SOFTWARE_8_SOURCES)
+module_la_LIBADD = @EINA_LIBS@ $(top_builddir)/src/lib/libevas.la
+module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
+module_la_LIBTOOLFLAGS = --tag=disable-static
+
+else
+
+noinst_LTLIBRARIES = libevas_engine_software_8.la
+
+libevas_engine_software_8_la_SOURCES = $(SOFTWARE_8_SOURCES)
+
+endif
+endif
+
+EXTRA_DIST = \
+evas_engine.c
diff --git a/src/modules/engines/software_8/evas_engine.c b/src/modules/engines/software_8/evas_engine.c
new file mode 100644 (file)
index 0000000..5efab4e
--- /dev/null
@@ -0,0 +1,818 @@
+#include "evas_common.h"
+#include "evas_common_soft8.h"
+
+/*
+ *****
+ **
+ ** ENGINE ROUTINES
+ **
+ *****
+ */
+int _evas_soft8_log_dom = -1;
+#ifdef ERR
+#undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR( _evas_soft8_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_evas_soft8_log_dom, __VA_ARGS__)
+
+#ifdef INF
+#undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_evas_soft8_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+#undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_evas_soft8_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+#undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_evas_soft8_log_dom, __VA_ARGS__)
+
+#define NOT_IMPLEMENTED()                                               \
+  WRN("NOT_IMPLEMENTED: %s() at %s:%d",                                \
+           __FUNCTION__, __FILE__, __LINE__)
+
+static void
+eng_output_dump(void *data __UNUSED__)
+{
+   evas_common_image_image_all_unload();
+   evas_common_font_font_all_unload();
+}
+
+static void *
+eng_context_new(void *data __UNUSED__)
+{
+   return evas_common_draw_context_new();
+}
+
+static void
+eng_context_free(void *data __UNUSED__, void *context)
+{
+   evas_common_draw_context_free(context);
+}
+
+static void
+eng_context_clip_set(void *data __UNUSED__, void *context, int x, int y, int w,
+                     int h)
+{
+   evas_common_draw_context_set_clip(context, x, y, w, h);
+}
+
+static void
+eng_context_clip_clip(void *data __UNUSED__, void *context, int x, int y, int w,
+                      int h)
+{
+   evas_common_draw_context_clip_clip(context, x, y, w, h);
+}
+
+static void
+eng_context_clip_unset(void *data __UNUSED__, void *context)
+{
+   evas_common_draw_context_unset_clip(context);
+}
+
+static int
+eng_context_clip_get(void *data __UNUSED__, void *context, int *x, int *y,
+                     int *w, int *h)
+{
+   *x = ((RGBA_Draw_Context *) context)->clip.x;
+   *y = ((RGBA_Draw_Context *) context)->clip.y;
+   *w = ((RGBA_Draw_Context *) context)->clip.w;
+   *h = ((RGBA_Draw_Context *) context)->clip.h;
+   return ((RGBA_Draw_Context *) context)->clip.use;
+}
+
+static void
+eng_context_color_set(void *data __UNUSED__, void *context, int r, int g, int b,
+                      int a)
+{
+   evas_common_draw_context_set_color(context, r, g, b, a);
+}
+
+static int
+eng_context_color_get(void *data __UNUSED__, void *context, int *r, int *g,
+                      int *b, int *a)
+{
+   *r = (int)(R_VAL(&((RGBA_Draw_Context *) context)->col.col));
+   *g = (int)(G_VAL(&((RGBA_Draw_Context *) context)->col.col));
+   *b = (int)(B_VAL(&((RGBA_Draw_Context *) context)->col.col));
+   *a = (int)(A_VAL(&((RGBA_Draw_Context *) context)->col.col));
+   return 1;
+}
+
+static void
+eng_context_multiplier_set(void *data __UNUSED__, void *context, int r, int g,
+                           int b, int a)
+{
+   evas_common_draw_context_set_multiplier(context, r, g, b, a);
+}
+
+static void
+eng_context_multiplier_unset(void *data __UNUSED__, void *context)
+{
+   evas_common_draw_context_unset_multiplier(context);
+}
+
+static int
+eng_context_multiplier_get(void *data __UNUSED__, void *context, int *r, int *g,
+                           int *b, int *a)
+{
+   *r = (int)(R_VAL(&((RGBA_Draw_Context *) context)->mul.col));
+   *g = (int)(G_VAL(&((RGBA_Draw_Context *) context)->mul.col));
+   *b = (int)(B_VAL(&((RGBA_Draw_Context *) context)->mul.col));
+   *a = (int)(A_VAL(&((RGBA_Draw_Context *) context)->mul.col));
+   return ((RGBA_Draw_Context *) context)->mul.use;
+}
+
+static void
+eng_context_cutout_add(void *data __UNUSED__, void *context, int x, int y,
+                       int w, int h)
+{
+   evas_common_draw_context_add_cutout(context, x, y, w, h);
+}
+
+static void
+eng_context_cutout_clear(void *data __UNUSED__, void *context)
+{
+   evas_common_draw_context_clear_cutouts(context);
+}
+
+static void
+eng_context_anti_alias_set(void *data __UNUSED__, void *context,
+                           unsigned char aa)
+{
+   evas_common_draw_context_set_anti_alias(context, aa);
+}
+
+static unsigned char
+eng_context_anti_alias_get(void *data __UNUSED__, void *context)
+{
+   return ((RGBA_Draw_Context *) context)->anti_alias;
+}
+
+static void
+eng_context_color_interpolation_set(void *data __UNUSED__, void *context,
+                                    int color_space)
+{
+   evas_common_draw_context_set_color_interpolation(context, color_space);
+}
+
+static int
+eng_context_color_interpolation_get(void *data __UNUSED__, void *context)
+{
+   return ((RGBA_Draw_Context *) context)->interpolation.color_space;
+}
+
+static void
+eng_context_render_op_set(void *data __UNUSED__, void *context, int op)
+{
+   evas_common_draw_context_set_render_op(context, op);
+}
+
+static int
+eng_context_render_op_get(void *data __UNUSED__, void *context)
+{
+   return ((RGBA_Draw_Context *) context)->render_op;
+}
+
+static void
+eng_rectangle_draw(void *data __UNUSED__, void *context, void *surface, int x,
+                   int y, int w, int h)
+{
+   soft8_rectangle_draw(surface, context, x, y, w, h);
+}
+
+static void
+eng_line_draw(void *data __UNUSED__, void *context, void *surface, int x1,
+              int y1, int x2, int y2)
+{
+   soft8_line_draw(surface, context, x1, y1, x2, y2);
+}
+
+static void *
+eng_polygon_point_add(void *data __UNUSED__, void *context __UNUSED__,
+                      void *polygon, int x, int y)
+{
+   return evas_common_polygon_point_add(polygon, x, y);
+}
+
+static void *
+eng_polygon_points_clear(void *data __UNUSED__, void *context __UNUSED__,
+                         void *polygon)
+{
+   return evas_common_polygon_points_clear(polygon);
+}
+
+static void
+eng_polygon_draw(void *data __UNUSED__, void *context, void *surface,
+                 void *polygon, int x, int y)
+{
+   soft8_polygon_draw(surface, context, polygon, x, y);
+}
+
+static int
+eng_image_alpha_get(void *data __UNUSED__, void *image)
+{
+   Soft8_Image *im;
+
+   if (!image)
+      return 0;
+   im = image;
+   return im->cache_entry.flags.alpha;
+}
+
+static int
+eng_image_colorspace_get(void *data __UNUSED__, void *image __UNUSED__)
+{
+   return EVAS_COLORSPACE_GRY8;
+}
+
+static void *
+eng_image_alpha_set(void *data __UNUSED__, void *image, int have_alpha)
+{
+   if (!image)
+      return NULL;
+   have_alpha = !!have_alpha;
+   image = soft8_image_alpha_set(image, have_alpha);
+   return image;
+}
+
+static void *
+eng_image_border_set(void *data __UNUSED__, void *image, int l __UNUSED__,
+                     int r __UNUSED__, int t __UNUSED__, int b __UNUSED__)
+{
+   return image;
+}
+
+static void
+eng_image_border_get(void *data __UNUSED__, void *image __UNUSED__,
+                     int *l __UNUSED__, int *r __UNUSED__, int *t __UNUSED__,
+                     int *b __UNUSED__)
+{
+}
+
+static char *
+eng_image_comment_get(void *data __UNUSED__, void *image __UNUSED__,
+                      char *key __UNUSED__)
+{
+   return NULL;
+}
+
+static char *
+eng_image_format_get(void *data __UNUSED__, void *image __UNUSED__)
+{
+   NOT_IMPLEMENTED();
+   return NULL;
+}
+
+static void
+eng_image_colorspace_set(void *data __UNUSED__, void *image __UNUSED__,
+                         int cspace __UNUSED__)
+{
+   NOT_IMPLEMENTED();
+}
+
+static void
+eng_image_native_set(void *data __UNUSED__, void *image __UNUSED__,
+                     void *native __UNUSED__)
+{
+   NOT_IMPLEMENTED();
+}
+
+static void *
+eng_image_native_get(void *data __UNUSED__, void *image __UNUSED__)
+{
+   NOT_IMPLEMENTED();
+   return NULL;
+}
+
+static void *
+eng_image_load(void *data __UNUSED__, const char *file, const char *key,
+               int *error, Evas_Image_Load_Opts * lo)
+{
+   return evas_cache_image_request(evas_common_soft8_image_cache_get(), file,
+                                   key, lo, error);
+}
+
+static void *
+eng_image_new_from_data(void *data __UNUSED__, int w, int h,
+                        DATA32 * image_data, int alpha, int cspace)
+{
+   if ((image_data) && (cspace != EVAS_COLORSPACE_GRY8))
+     {
+        WRN("Unsupported colorspace %d in %s() (%s:%d)",
+            cspace, __FUNCTION__, __FILE__, __LINE__);
+        return NULL;
+     }
+   return evas_cache_image_data(evas_common_soft8_image_cache_get(), w, h,
+                                image_data, alpha, EVAS_COLORSPACE_GRY8);
+}
+
+static void *
+eng_image_new_from_copied_data(void *data __UNUSED__, int w, int h,
+                               DATA32 * image_data, int alpha, int cspace)
+{
+   if ((image_data) && (cspace != EVAS_COLORSPACE_GRY8))
+     {
+        WRN("Unsupported colorspace %d in %s() (%s:%d)",
+            cspace, __FUNCTION__, __FILE__, __LINE__);
+        return NULL;
+     }
+   return evas_cache_image_copied_data(evas_common_soft8_image_cache_get(), w,
+                                       h, image_data, alpha,
+                                       EVAS_COLORSPACE_GRY8);
+}
+
+static void
+eng_image_free(void *data __UNUSED__, void *image)
+{
+   evas_cache_image_drop((Image_Entry *) image);
+}
+
+static void
+eng_image_size_get(void *data __UNUSED__, void *image, int *w, int *h)
+{
+   Soft8_Image *im;
+
+   if (w)
+      *w = 0;
+   if (h)
+      *h = 0;
+   if (!image)
+      return;
+   im = image;
+   if (w)
+      *w = im->cache_entry.w;
+   if (h)
+      *h = im->cache_entry.h;
+}
+
+static void *
+eng_image_size_set(void *data __UNUSED__, void *image, int w, int h)
+{
+   if (!image)
+      return NULL;
+   if ((w <= 0) || (h <= 0))
+     {
+        evas_cache_image_drop((Image_Entry *) image);
+        return NULL;
+     }
+   return evas_cache_image_size_set((Image_Entry *) image, w, h);
+}
+
+static void
+eng_image_stride_get(void *data __UNUSED__, void *image, int *stride)
+{
+   Soft8_Image *im;
+
+   if (stride)
+      *stride = 0;
+   if (!image)
+      return;
+   im = image;
+   if (stride)
+      *stride = im->stride;
+}
+
+static void *
+eng_image_dirty_region(void *data __UNUSED__, void *image __UNUSED__,
+                       int x __UNUSED__, int y __UNUSED__, int w __UNUSED__,
+                       int h __UNUSED__)
+{
+   /* FIXME: is this required? */
+   //NOT_IMPLEMENTED();
+   return image;
+}
+
+static void *
+eng_image_data_get(void *data __UNUSED__, void *image, int to_write,
+                   DATA32 ** image_data)
+{
+   Soft8_Image *im;
+
+   if (!image)
+     {
+        *image_data = NULL;
+        return NULL;
+     }
+
+   im = image;
+   evas_cache_image_load_data(&im->cache_entry);
+
+   if (to_write)
+      im = (Soft8_Image *) evas_cache_image_alone(&im->cache_entry);
+
+   if (image_data)
+      *image_data = (DATA32 *) im->pixels;
+
+   return im;
+}
+
+static void *
+eng_image_data_put(void *data __UNUSED__, void *image, DATA32 * image_data)
+{
+   Soft8_Image *old_im, *new_im;
+
+   if (!image)
+      return NULL;
+
+   old_im = image;
+   if ((DATA8 *) image_data == old_im->pixels)
+      return old_im;
+
+   new_im =
+       (Soft8_Image *)
+       evas_cache_image_data(evas_common_soft8_image_cache_get(),
+                             old_im->cache_entry.w, old_im->cache_entry.h,
+                             image_data, old_im->cache_entry.flags.alpha,
+                             EVAS_COLORSPACE_GRY8);
+   evas_cache_image_drop(&old_im->cache_entry);
+   return new_im;
+}
+
+static void
+eng_image_data_preload_request(void *data __UNUSED__, void *image,
+                               const void *target)
+{
+   Soft8_Image *im = image;
+
+   if (!im)
+      return;
+   evas_cache_image_preload_data(&im->cache_entry, target);
+}
+
+static void
+eng_image_data_preload_cancel(void *data __UNUSED__, void *image,
+                              const void *target)
+{
+   Soft8_Image *im = image;
+
+   if (!im)
+      return;
+   evas_cache_image_preload_cancel(&im->cache_entry, target);
+}
+
+static void
+eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image,
+               int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y,
+               int dst_w, int dst_h, int smooth)
+{
+   Soft8_Image *im;
+
+   im = (Soft8_Image *) image;
+
+   evas_cache_image_load_data(&im->cache_entry);
+   soft8_image_draw(im, surface, context,
+                    src_x, src_y, src_w, src_h,
+                    dst_x, dst_y, dst_w, dst_h, smooth);
+}
+
+static void
+eng_image_scale_hint_set(void *data __UNUSED__, void *image __UNUSED__,
+                         int hint __UNUSED__)
+{
+}
+
+static int
+eng_image_scale_hint_get(void *data __UNUSED__, void *image __UNUSED__)
+{
+   return EVAS_IMAGE_SCALE_HINT_NONE;
+}
+
+static void
+eng_image_cache_flush(void *data __UNUSED__)
+{
+   evas_cache_image_flush(evas_common_soft8_image_cache_get());
+}
+
+static void
+eng_image_cache_set(void *data __UNUSED__, int bytes)
+{
+   evas_cache_image_set(evas_common_soft8_image_cache_get(), bytes);
+}
+
+static int
+eng_image_cache_get(void *data __UNUSED__)
+{
+   return evas_cache_image_get(evas_common_soft8_image_cache_get());
+}
+
+static void *
+eng_font_load(void *data __UNUSED__, const char *name, int size)
+{
+   return evas_common_font_load(name, size);
+}
+
+static void *
+eng_font_memory_load(void *data __UNUSED__, char *name, int size,
+                     const void *fdata, int fdata_size)
+{
+   return evas_common_font_memory_load(name, size, fdata, fdata_size);
+}
+
+static void *
+eng_font_add(void *data __UNUSED__, void *font, const char *name, int size)
+{
+   return evas_common_font_add(font, name, size);
+}
+
+static void *
+eng_font_memory_add(void *data __UNUSED__, void *font, char *name, int size,
+                    const void *fdata, int fdata_size)
+{
+   return evas_common_font_memory_add(font, name, size, fdata, fdata_size);
+}
+
+static void
+eng_font_free(void *data __UNUSED__, void *font)
+{
+   evas_common_font_free(font);
+}
+
+static int
+eng_font_ascent_get(void *data __UNUSED__, void *font)
+{
+   return evas_common_font_ascent_get(font);
+}
+
+static int
+eng_font_descent_get(void *data __UNUSED__, void *font)
+{
+   return evas_common_font_descent_get(font);
+}
+
+static int
+eng_font_max_ascent_get(void *data __UNUSED__, void *font)
+{
+   return evas_common_font_max_ascent_get(font);
+}
+
+static int
+eng_font_max_descent_get(void *data __UNUSED__, void *font)
+{
+   return evas_common_font_max_descent_get(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)
+{
+   evas_common_font_query_size(font, text, intl_props, w, h);
+}
+
+static int
+eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text)
+{
+   return evas_common_font_query_inset(font, text);
+}
+
+static int
+eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
+{
+   int h, v;
+
+   evas_common_font_query_advance(font, text, intl_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)
+{
+   int h, v;
+
+   evas_common_font_query_advance(font, text, intl_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)
+{
+   return evas_common_font_query_char_coords(font, text, intl_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)
+{
+   return evas_common_font_query_char_at_coords(font, text, intl_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)
+{
+   return evas_common_font_query_last_up_to_pos(font, text, intl_props, x, y);
+}
+
+static void
+eng_font_draw(void *data __UNUSED__, 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)
+{
+   evas_common_font_draw(surface, context, font, x, y, text, intl_props);
+   evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL);
+}
+
+static void
+eng_font_cache_flush(void *data __UNUSED__)
+{
+   evas_common_font_flush();
+}
+
+static void
+eng_font_cache_set(void *data __UNUSED__, int bytes)
+{
+   evas_common_font_cache_set(bytes);
+}
+
+static int
+eng_font_cache_get(void *data __UNUSED__)
+{
+   return evas_common_font_cache_get();
+}
+
+static void
+eng_font_hinting_set(void *data __UNUSED__, void *font, int hinting)
+{
+   evas_common_font_hinting_set(font, hinting);
+}
+
+static int
+eng_font_hinting_can_hint(void *data __UNUSED__, int hinting)
+{
+   return evas_common_hinting_available(hinting);
+}
+
+static Eina_Bool
+eng_canvas_alpha_get(void *data __UNUSED__, void *context __UNUSED__)
+{
+   return EINA_TRUE;
+}
+
+/*
+ *****
+ **
+ ** ENGINE API
+ **
+ *****
+ */
+
+static Evas_Func func = {
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   eng_output_dump,
+   /* draw context virtual methods */
+   eng_context_new,
+   eng_canvas_alpha_get,
+   eng_context_free,
+   eng_context_clip_set,
+   eng_context_clip_clip,
+   eng_context_clip_unset,
+   eng_context_clip_get,
+   eng_context_color_set,
+   eng_context_color_get,
+   eng_context_multiplier_set,
+   eng_context_multiplier_unset,
+   eng_context_multiplier_get,
+   eng_context_cutout_add,
+   eng_context_cutout_clear,
+   eng_context_anti_alias_set,
+   eng_context_anti_alias_get,
+   eng_context_color_interpolation_set,
+   eng_context_color_interpolation_get,
+   eng_context_render_op_set,
+   eng_context_render_op_get,
+   /* rect draw funcs */
+   eng_rectangle_draw,
+   /* line draw funcs */
+   eng_line_draw,
+   /* polygon draw funcs */
+   eng_polygon_point_add,
+   eng_polygon_points_clear,
+   eng_polygon_draw,
+   /* image draw funcs */
+   eng_image_load,
+   eng_image_new_from_data,
+   eng_image_new_from_copied_data,
+   eng_image_free,
+   eng_image_size_get,
+   eng_image_size_set,
+   eng_image_stride_get,
+   eng_image_dirty_region,
+   eng_image_data_get,
+   eng_image_data_put,
+   eng_image_data_preload_request,
+   eng_image_data_preload_cancel,
+   eng_image_alpha_set,
+   eng_image_alpha_get,
+   eng_image_border_set,
+   eng_image_border_get,
+   eng_image_draw,
+   eng_image_comment_get,
+   eng_image_format_get,
+   eng_image_colorspace_set,
+   eng_image_colorspace_get,
+   eng_image_native_set,
+   eng_image_native_get,
+   /* image cache funcs */
+   eng_image_cache_flush,
+   eng_image_cache_set,
+   eng_image_cache_get,
+   /* font draw functions */
+   eng_font_load,
+   eng_font_memory_load,
+   eng_font_add,
+   eng_font_memory_add,
+   eng_font_free,
+   eng_font_ascent_get,
+   eng_font_descent_get,
+   eng_font_max_ascent_get,
+   eng_font_max_descent_get,
+   eng_font_string_size_get,
+   eng_font_inset_get,
+   eng_font_h_advance_get,
+   eng_font_v_advance_get,
+   eng_font_char_coords_get,
+   eng_font_char_at_coords_get,
+   eng_font_draw,
+   /* font cache functions */
+   eng_font_cache_flush,
+   eng_font_cache_set,
+   eng_font_cache_get,
+   /* font hinting functions */
+   eng_font_hinting_set,
+   eng_font_hinting_can_hint,
+   eng_image_scale_hint_set,
+   eng_image_scale_hint_get,
+   /* more font draw functions */
+   eng_font_last_up_to_pos
+       /* FUTURE software generic calls go here */
+//   ORD(image_map4_draw);
+//   ORD(image_map_surface_new);
+//   ORD(image_map_surface_free);
+       /* FUTURE software generic calls go here */
+};
+
+/*
+ *****
+ **
+ ** MODULE ACCESSIBLE API API
+ **
+ *****
+ */
+
+static int
+module_open(Evas_Module * em)
+{
+   if (!em)
+      return 0;
+   _evas_soft8_log_dom =
+       eina_log_domain_register("Soft8Engine", EVAS_DEFAULT_LOG_COLOR);
+   if (_evas_soft8_log_dom < 0)
+     {
+        EINA_LOG_ERR
+            ("Impossible to create a log domain for the soft8 Engine.\n");
+        return 0;
+     }
+   em->functions = (void *)(&func);
+
+   return 1;
+}
+
+static void
+module_close(Evas_Module * em)
+{
+   eina_log_domain_unregister(_evas_soft8_log_dom);
+}
+
+static Evas_Module_Api evas_modapi = {
+   EVAS_MODULE_API_VERSION,
+   "software_8",
+   "none",
+   {
+    module_open,
+    module_close}
+};
+
+EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, software_8);
+
+#ifndef EVAS_STATIC_BUILD_SOFTWARE_8
+EVAS_EINA_MODULE_DEFINE(engine, software_8);
+#endif
diff --git a/src/modules/engines/software_8_x11/Evas_Engine_Software_8_X11.h b/src/modules/engines/software_8_x11/Evas_Engine_Software_8_X11.h
new file mode 100644 (file)
index 0000000..fac3d8e
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _EVAS_ENGINE_SOFTWARE_8_X11_H
+#define _EVAS_ENGINE_SOFTWARE_8_X11_H
+
+#include <xcb/xcb.h>
+
+typedef struct _Evas_Engine_Info_Software_8_X11              Evas_Engine_Info_Software_8_X11;
+
+struct _Evas_Engine_Info_Software_8_X11
+{
+   /* PRIVATE - don't mess with this baby or evas will poke its tongue out */
+   /* at you and make nasty noises */
+   Evas_Engine_Info magic;
+
+   /* engine specific data & parameters it needs to set up */
+   struct {
+      xcb_connection_t *connection;
+      xcb_drawable_t drawable;
+      xcb_gcontext_t gc;
+      xcb_screen_t *screen;
+
+      unsigned int mask;
+      void        *visual;
+      unsigned int colormap;
+      int          depth;
+      int          rotation;
+
+      int          alloc_grayscale    : 1;
+      int          debug              : 1;
+      int          shape_dither       : 1;
+      int          destination_alpha  : 1;
+      int          track_mask_changes : 1;
+   } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
+};
+
+#endif
diff --git a/src/modules/engines/software_8_x11/Makefile.am b/src/modules/engines/software_8_x11/Makefile.am
new file mode 100644 (file)
index 0000000..b4e6b8a
--- /dev/null
@@ -0,0 +1,47 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/src/lib \
+-I$(top_srcdir)/src/lib/include \
+-I$(top_srcdir)/src/modules/engines \
+-I$(top_srcdir)/src/modules/engines/software_8 \
+@FREETYPE_CFLAGS@ \
+@EINA_CFLAGS@ \
+@evas_engine_software_8_x11_cflags@ \
+-I/usr/include/pixman-1
+
+if BUILD_ENGINE_SOFTWARE_8_X11
+
+SOFTWARE_8_X11_SOURCES =  \
+evas_engine.c \
+evas_x_buffer.c
+
+SOFTWARE_8_X11_LIBADD = @evas_engine_software_8_x11_libs@
+
+pkgdir = $(libdir)/evas/modules/engines/software_8_x11/$(MODULE_ARCH)
+
+include_HEADERS = Evas_Engine_Software_8_X11.h
+
+if !EVAS_STATIC_BUILD_SOFTWARE_8_X11
+
+pkg_LTLIBRARIES        = module.la
+
+module_la_SOURCES = $(SOFTWARE_8_X11_SOURCES)
+module_la_LIBADD = @EINA_LIBS@ $(SOFTWARE_8_X11_LIBADD) $(top_builddir)/src/lib/libevas.la
+#-lxcb-image -lxcb-shm -lxcb -lpixman-1
+module_la_LDFLAGS = -no-undefined -module -avoid-version
+module_la_LIBTOOLFLAGS = --tag=disable-static
+
+else
+
+noinst_LTLIBRARIES = libevas_engine_software_8_x11.la
+
+libevas_engine_software_8_x11_la_SOURCES = $(SOFTWARE_8_X11_SOURCES)
+libevas_engine_software_8_x11_la_LIBADD = $(SOFTWARE_8_X11_LIBADD)
+
+endif
+endif
+
+EXTRA_DIST = evas_engine.h
diff --git a/src/modules/engines/software_8_x11/evas_engine.c b/src/modules/engines/software_8_x11/evas_engine.c
new file mode 100644 (file)
index 0000000..661db18
--- /dev/null
@@ -0,0 +1,699 @@
+#include "evas_common.h"
+#include "evas_private.h"
+#include "evas_engine.h"
+#include "Evas_Engine_Software_8_X11.h"
+#include "evas_common_soft8.h"
+#include <pixman.h>
+
+int _evas_engine_soft8_x11_log_dom = -1;
+/* function tables - filled in later (func and parent func) */
+static Evas_Func func, pfunc;
+
+/* engine struct data */
+typedef struct _Render_Engine Render_Engine;
+
+struct _Render_Engine {
+   xcb_connection_t *connection;
+   xcb_drawable_t drawable;
+   xcb_screen_t *screen;
+   unsigned char pal[256];
+   int depth;
+
+   int w, h, rot;
+   Tilebuf *tb;
+   Tilebuf_Rect *rects;
+   Tilebuf_Rect *cur_rect;
+
+   X_Output_Buffer *shbuf;
+   Soft8_Image *tmp_out;        /* used by indirect render, like rotation */
+
+   pixman_region16_t *clip_rects;
+   unsigned char end:1;
+   unsigned char shm:1;
+};
+
+/* prototypes we will use here */
+
+static void *eng_info(Evas * e);
+static void eng_info_free(Evas * e, void *info);
+static int eng_setup(Evas * e, void *info);
+static void eng_output_free(void *data);
+static void eng_output_resize(void *data, int w, int h);
+static void eng_output_tile_size_set(void *data, int w, int h);
+static void eng_output_redraws_rect_add(void *data, int x, int y, int w, int h);
+static void eng_output_redraws_rect_del(void *data, int x, int y, int w, int h);
+static void eng_output_redraws_clear(void *data);
+static void *eng_output_redraws_next_update_get(void *data, int *x, int *y,
+                                                int *w, int *h, int *cx,
+                                                int *cy, int *cw, int *ch);
+static void eng_output_redraws_next_update_push(void *data, void *surface,
+                                                int x, int y, int w, int h);
+static void eng_output_flush(void *data);
+static void eng_output_idle_flush(void *data);
+
+/* engine api this module provides */
+static void *
+eng_info(Evas * e)
+{
+   Evas_Engine_Info_Software_8_X11 *info;
+
+   info = calloc(1, sizeof(Evas_Engine_Info_Software_8_X11));
+   if (!info)
+      return NULL;
+   info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
+   return info;
+   e = NULL;
+}
+
+static void
+eng_info_free(Evas * e __UNUSED__, void *info)
+{
+   Evas_Engine_Info_Software_8_X11 *in;
+   in = (Evas_Engine_Info_Software_8_X11 *) info;
+   free(in);
+}
+
+static void
+_tmp_out_alloc(Render_Engine * re)
+{
+   Tilebuf_Rect *r;
+   int w = 0, h = 0;
+
+   EINA_INLIST_FOREACH(re->rects, r)
+   {
+      if (r->w > w)
+         w = r->w;
+      if (r->h > h)
+         h = r->h;
+   }
+
+   if (re->tmp_out)
+     {
+        if ((re->tmp_out->cache_entry.w < w)
+            || (re->tmp_out->cache_entry.h < h))
+          {
+             evas_cache_image_drop(&re->tmp_out->cache_entry);
+             re->tmp_out = NULL;
+          }
+     }
+
+   if (!re->tmp_out)
+     {
+        Soft8_Image *im;
+
+        im = (Soft8_Image *)
+            evas_cache_image_empty(evas_common_soft8_image_cache_get());
+        im->cache_entry.flags.alpha = 0;
+        evas_cache_image_surface_alloc(&im->cache_entry, w, h);
+
+        re->tmp_out = im;
+     }
+}
+
+static void
+alloc_colors(Render_Engine * re)
+{
+   xcb_alloc_color_cookie_t color_rq[256];
+   xcb_alloc_color_reply_t *rep;
+   xcb_colormap_t colormap = re->screen->default_colormap;
+
+   int i;
+   for (i = 0; i < 256; i++)
+      color_rq[i] =
+          xcb_alloc_color(re->connection, colormap, i << 8, i << 8, i << 8);
+
+   for (i = 0; i < 256; i++)
+     {
+        rep = xcb_alloc_color_reply(re->connection, color_rq[i], NULL);
+        re->pal[i] = rep->pixel;
+        free(rep);
+     }
+}
+
+static int
+eng_setup(Evas * e, void *in)
+{
+   Render_Engine *re;
+   Evas_Engine_Info_Software_8_X11 *info;
+/*    X_Output_Buffer *xob; */
+
+   info = (Evas_Engine_Info_Software_8_X11 *) in;
+   if (!e->engine.data.output)
+     {
+        /* the only check - simplistic, i know, but enough for this
+         * "special purpose" engine. Remember it is meant to be used
+         * for limited power devices that have a 8bit display mode
+         * and no real other acceleration, and high resolution so we
+         * can pre-dither into 8bpp. */
+//      if (DefaultDepth(info->info.display,
+//                       DefaultScreen(info->info.display)) != 8)
+//        return;
+        /* do common routine init - we wil at least use it for core
+         * image loading and font loading/glyph rendering & placement */
+        evas_common_cpu_init();
+
+        evas_common_blend_init();
+        evas_common_image_init();
+        evas_common_convert_init();
+        evas_common_scale_init();
+        evas_common_rectangle_init();
+        evas_common_polygon_init();
+        evas_common_line_init();
+        evas_common_font_init();
+        evas_common_draw_init();
+        evas_common_tilebuf_init();
+        evas_common_soft8_image_init();
+
+        /* render engine specific data */
+        re = calloc(1, sizeof(Render_Engine));
+        if (!re)
+           return 0;
+        e->engine.data.output = re;
+        re->connection = info->info.connection;
+        re->screen = info->info.screen;
+        re->drawable = info->info.drawable;
+        re->depth = info->info.depth;
+        re->w = e->output.w;
+        re->h = e->output.h;
+        re->rot = info->info.rotation;
+        re->tb = evas_common_tilebuf_new(e->output.w, e->output.h);
+        if (re->tb)
+           evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
+        alloc_colors(re);
+     }
+   else
+     {
+        /* we changed the info after first init - do a re-eval where
+         * appropriate */
+        re = e->engine.data.output;
+        if (re->tb)
+           evas_common_tilebuf_free(re->tb);
+        re->connection = info->info.connection;
+        re->screen = info->info.screen;
+        re->drawable = info->info.drawable;
+        re->w = e->output.w;
+        re->h = e->output.h;
+        re->rot = info->info.rotation;
+        re->tb = evas_common_tilebuf_new(e->output.w, e->output.h);
+        if (re->tb)
+           evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
+        if (re->tmp_out)
+          {
+             evas_cache_image_drop(&re->tmp_out->cache_entry);
+             re->tmp_out = NULL;
+          }
+        alloc_colors(re);
+     }
+   if (!e->engine.data.output)
+      return 0;
+
+   /* add a draw context if we dont have one */
+   if (!e->engine.data.context)
+      e->engine.data.context =
+          e->engine.func->context_new(e->engine.data.output);
+   /* check if the display can do shm */
+   re->shm = evas_software_x11_x_can_do_shm(re->connection, re->screen);
+
+   return 1;
+}
+
+static void
+eng_output_free(void *data)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *) data;
+   if (re->shbuf)
+      evas_software_x11_x_output_buffer_free(re->shbuf, 0);
+   if (re->clip_rects)
+     {
+        pixman_region_fini(re->clip_rects);
+        free(re->clip_rects);
+        re->clip_rects = NULL;
+     }
+   if (re->tb)
+      evas_common_tilebuf_free(re->tb);
+   if (re->rects)
+      evas_common_tilebuf_free_render_rects(re->rects);
+   if (re->tmp_out)
+      evas_cache_image_drop(&re->tmp_out->cache_entry);
+   free(re);
+
+   evas_common_font_shutdown();
+   evas_common_image_shutdown();
+   evas_common_soft8_image_shutdown();
+}
+
+static void
+eng_output_resize(void *data, int w, int h)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *) data;
+
+   if ((re->w == w) && (re->h == h))
+      return;
+
+   evas_common_tilebuf_free(re->tb);
+   re->w = w;
+   re->h = h;
+   re->tb = evas_common_tilebuf_new(w, h);
+   if (re->tb)
+      evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
+   if (re->shbuf)
+     {
+        evas_software_x11_x_output_buffer_free(re->shbuf, 0);
+        re->shbuf = NULL;
+     }
+   if (re->clip_rects)
+     {
+        pixman_region_fini(re->clip_rects);
+        free(re->clip_rects);
+        re->clip_rects = NULL;
+     }
+
+   if (re->tmp_out)
+     {
+        evas_cache_image_drop(&re->tmp_out->cache_entry);
+        re->tmp_out = NULL;
+     }
+}
+
+static void
+eng_output_tile_size_set(void *data, int w, int h)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *) data;
+   evas_common_tilebuf_set_tile_size(re->tb, w, h);
+}
+
+static void
+eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *) data;
+   evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
+}
+
+static void
+eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *) data;
+   evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
+}
+
+static void
+eng_output_redraws_clear(void *data)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *) data;
+   evas_common_tilebuf_clear(re->tb);
+}
+
+static inline void
+_output_buffer_alloc(Render_Engine * re)
+{
+   int w, h;
+   if (re->shbuf)
+      return;
+
+   if ((re->rot == 0) || (re->rot == 180))
+     {
+        w = re->w;
+        h = re->h;
+     }
+   else
+     {
+        w = re->h;
+        h = re->w;
+     }
+
+   re->shbuf = evas_software_x11_x_output_buffer_new
+       (re->connection, re->screen, re->depth, re->pal, w, h, 1, NULL);
+
+   re->shbuf->drawable = re->drawable;
+   re->shbuf->screen = re->screen;
+   if (re->shbuf->gc)
+     {
+        xcb_free_gc(re->shbuf->connection, re->shbuf->gc);
+        re->shbuf->gc = 0;
+     }
+
+   re->shbuf->gc = xcb_generate_id(re->shbuf->connection);
+   xcb_create_gc(re->shbuf->connection, re->shbuf->gc, re->shbuf->drawable, 0,
+                 NULL);
+}
+
+static void *
+eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h,
+                                   int *cx, int *cy, int *cw, int *ch)
+{
+   Render_Engine *re;
+   Tilebuf_Rect *rect;
+   int ux, uy, uw, uh;
+
+   re = (Render_Engine *) data;
+   if (re->end)
+     {
+        re->end = 0;
+        return NULL;
+     }
+   if (!re->rects)
+     {
+        re->rects = evas_common_tilebuf_get_render_rects(re->tb);
+        if (!re->rects)
+           return NULL;
+
+        re->cur_rect = re->rects;
+        _output_buffer_alloc(re);
+        if (re->rot != 0)
+           _tmp_out_alloc(re);  /* grows if required */
+     }
+   if (!re->cur_rect)
+     {
+        if (re->rects)
+           evas_common_tilebuf_free_render_rects(re->rects);
+        re->rects = NULL;
+        return NULL;
+     }
+   rect = re->cur_rect;
+   ux = rect->x;
+   uy = rect->y;
+   uw = rect->w;
+   uh = rect->h;
+   re->cur_rect = (Tilebuf_Rect *) ((EINA_INLIST_GET(re->cur_rect))->next);
+   if (!re->cur_rect)
+     {
+        evas_common_tilebuf_free_render_rects(re->rects);
+        re->rects = NULL;
+        re->end = 1;
+     }
+
+   *x = ux;
+   *y = uy;
+   *w = uw;
+   *h = uh;
+   if (re->rot == 0)
+     {
+        *cx = ux;
+        *cy = uy;
+        *cw = uw;
+        *ch = uh;
+        return re->shbuf->im;
+     }
+   else
+     {
+        *cx = 0;
+        *cy = 0;
+        *cw = uw;
+        *ch = uh;
+        return re->tmp_out;
+     }
+}
+
+static void
+_blit_rot_90(Soft8_Image * dst, const Soft8_Image * src,
+             int out_x, int out_y, int w, int h)
+{
+   DATA8 *dp, *sp;
+   int x, y;
+
+   sp = src->pixels;
+   dp = dst->pixels + (out_x + (w + out_y - 1) * dst->stride);
+
+   for (y = 0; y < h; y++)
+     {
+        DATA8 *dp_itr, *sp_itr;
+
+        sp_itr = sp;
+        dp_itr = dp;
+
+        for (x = 0; x < w; x++)
+          {
+             *dp_itr = *sp_itr;
+
+             sp_itr++;
+             dp_itr -= dst->stride;
+          }
+        sp += src->stride;
+        dp++;
+     }
+}
+
+static void
+_blit_rot_180(Soft8_Image * dst, const Soft8_Image * src,
+              int out_x, int out_y, int w, int h)
+{
+   DATA8 *dp, *sp;
+   int x, y;
+
+   sp = src->pixels;
+   dp = dst->pixels + ((w + out_x - 1) + (h + out_y - 1) * dst->stride);
+
+   for (y = 0; y < h; y++)
+     {
+        DATA8 *dp_itr, *sp_itr;
+
+        sp_itr = sp;
+        dp_itr = dp;
+
+        for (x = 0; x < w; x++)
+          {
+             *dp_itr = *sp_itr;
+
+             sp_itr++;
+             dp_itr--;
+          }
+        sp += src->stride;
+        dp -= dst->stride;
+     }
+}
+
+static void
+_blit_rot_270(Soft8_Image * dst, const Soft8_Image * src,
+              int out_x, int out_y, int w, int h)
+{
+   DATA8 *dp, *sp;
+   int x, y;
+
+   sp = src->pixels;
+   dp = dst->pixels + ((h + out_x - 1) + out_y * dst->stride);
+
+   for (y = 0; y < h; y++)
+     {
+        DATA8 *dp_itr, *sp_itr;
+
+        sp_itr = sp;
+        dp_itr = dp;
+
+        for (x = 0; x < w; x++)
+          {
+             *dp_itr = *sp_itr;
+
+             sp_itr++;
+             dp_itr += dst->stride;
+          }
+        sp += src->stride;
+        dp--;
+     }
+}
+
+static void
+_tmp_out_process(Render_Engine * re, int out_x, int out_y, int w, int h)
+{
+   Soft8_Image *d, *s;
+
+   d = re->shbuf->im;
+   s = re->tmp_out;
+
+   if ((w < 1) || (h < 1) || (out_x >= d->cache_entry.w)
+       || (out_y >= d->cache_entry.h))
+      return;
+
+   if (re->rot == 90)
+      _blit_rot_90(d, s, out_x, out_y, w, h);
+   else if (re->rot == 180)
+      _blit_rot_180(d, s, out_x, out_y, w, h);
+   else if (re->rot == 270)
+      _blit_rot_270(d, s, out_x, out_y, w, h);
+}
+
+static void
+eng_output_redraws_next_update_push(void *data, void *surface __UNUSED__, int x,
+                                    int y, int w, int h)
+{
+   Render_Engine *re;
+   struct {
+      int x, y, width, height;
+   } r =
+   {
+   0, 0, 0, 0};
+
+   re = (Render_Engine *) data;
+
+   if (!re->clip_rects)
+     {
+        re->clip_rects =
+            (pixman_region16_t *) malloc(sizeof(pixman_region16_t));
+        pixman_region_init(re->clip_rects);
+     }
+
+   if (re->rot == 0)
+     {
+        r.x = x;
+        r.y = y;
+        r.width = w;
+        r.height = h;
+     }
+   else if (re->rot == 90)
+     {
+        r.x = y;
+        r.y = re->w - w - x;
+        r.width = h;
+        r.height = w;
+     }
+   else if (re->rot == 180)
+     {
+        r.x = re->w - w - x;
+        r.y = re->h - h - y;
+        r.width = w;
+        r.height = h;
+     }
+   else if (re->rot == 270)
+     {
+        r.x = re->h - h - y;
+        r.y = x;
+        r.width = h;
+        r.height = w;
+     }
+
+   if (re->rot != 0)
+      _tmp_out_process(re, r.x, r.y, w, h);
+
+   pixman_region_union_rect(re->clip_rects, re->clip_rects,
+                            r.x, r.y, r.width, r.height);
+}
+
+static void
+eng_output_flush(void *data)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *) data;
+
+   if (re->clip_rects)
+     {
+        re->shbuf->drawable = re->drawable;
+        {
+           int i;
+           pixman_box16_t *rects =
+               pixman_region_rectangles(re->clip_rects, NULL);
+           for (i = 0; i < pixman_region_n_rects(re->clip_rects); i++, rects++)
+              evas_software_x11_x_output_buffer_paste
+                  (re->shbuf, re->drawable, re->shbuf->gc, rects->x1, rects->y1,
+                   rects->x2 - rects->x1, rects->y2 - rects->y1, 1);
+        }
+
+        pixman_region_fini(re->clip_rects);
+        free(re->clip_rects);
+        re->clip_rects = NULL;
+     }
+}
+
+static void
+eng_output_idle_flush(void *data)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *) data;
+   if (re->shbuf)
+     {
+        evas_software_x11_x_output_buffer_free(re->shbuf, 0);
+        re->shbuf = NULL;
+     }
+   if (re->clip_rects)
+     {
+        pixman_region_fini(re->clip_rects);
+        free(re->clip_rects);
+        re->clip_rects = NULL;
+     }
+   if (re->tmp_out)
+     {
+        evas_cache_image_drop(&re->tmp_out->cache_entry);
+        re->tmp_out = NULL;
+     }
+}
+
+static Eina_Bool
+eng_canvas_alpha_get(void *data __UNUSED__, void *context __UNUSED__)
+{
+   return EINA_FALSE;
+}
+
+/* module advertising code */
+static int
+module_open(Evas_Module * em)
+{
+   if (!em)
+      return 0;
+   /* get whatever engine module we inherit from */
+   if (!_evas_module_engine_inherit(&pfunc, "software_8"))
+      return 0;
+   _evas_engine_soft8_x11_log_dom =
+       eina_log_domain_register("EvasSoft8X11", EVAS_DEFAULT_LOG_COLOR);
+   if (_evas_engine_soft8_x11_log_dom < 0)
+     {
+        EINA_LOG_ERR
+            ("Impossible to create a log domain for the Soft8_X11 engine.\n");
+        return 0;
+     }
+
+   /* store it for later use */
+   func = pfunc;
+   /* now to override methods */
+#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
+   ORD(info);
+   ORD(info_free);
+   ORD(setup);
+   ORD(canvas_alpha_get);
+   ORD(output_free);
+   ORD(output_resize);
+   ORD(output_tile_size_set);
+   ORD(output_redraws_rect_add);
+   ORD(output_redraws_rect_del);
+   ORD(output_redraws_clear);
+   ORD(output_redraws_next_update_get);
+   ORD(output_redraws_next_update_push);
+   ORD(output_flush);
+   ORD(output_idle_flush);
+   /* now advertise out own api */
+   em->functions = (void *)(&func);
+   return 1;
+}
+
+static void
+module_close(Evas_Module * em)
+{
+   eina_log_domain_unregister(_evas_engine_soft8_x11_log_dom);
+}
+
+static Evas_Module_Api evas_modapi = {
+   EVAS_MODULE_API_VERSION,
+   "software_8_x11",
+   "none",
+   {
+    module_open,
+    module_close}
+};
+
+EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, software_8_x11);
+
+#ifndef EVAS_STATIC_BUILD_SOFTWARE_8_X11
+EVAS_EINA_MODULE_DEFINE(engine, software_8_x11);
+#endif
diff --git a/src/modules/engines/software_8_x11/evas_engine.h b/src/modules/engines/software_8_x11/evas_engine.h
new file mode 100644 (file)
index 0000000..1408271
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef EVAS_ENGINE_H
+#define EVAS_ENGINE_H
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include <xcb/xcb.h>
+#include <xcb/shm.h>
+#include <xcb/xcb_image.h>
+
+#include "evas_common.h"
+#include "evas_common_soft8.h"
+
+extern int _evas_engine_soft8_x11_log_dom;
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_evas_engine_soft8_x11_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+# undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_evas_engine_soft8_x11_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_evas_engine_soft8_x11_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_evas_engine_soft8_x11_log_dom, __VA_ARGS__)
+
+#ifdef CRIT
+# undef CRIT
+#endif
+#define CRIT(...) EINA_LOG_DOM_CRIT(_evas_engine_soft8_x11_log_dom, __VA_ARGS__)
+
+typedef struct _X_Output_Buffer       X_Output_Buffer;
+
+struct _X_Output_Buffer
+{
+   Soft8_Image                 *im;
+   xcb_connection_t            *connection;
+   xcb_screen_t                        *screen;
+   xcb_image_t                 *xim;
+   xcb_drawable_t              drawable;
+   xcb_gcontext_t              gc;
+   xcb_shm_segment_info_t      *shm_info;
+   unsigned char               *pal;
+   void                                *data;
+};
+
+/****/
+void             evas_software_x11_x_init                        (void);
+
+int              evas_software_x11_x_can_do_shm                  (xcb_connection_t *c, xcb_screen_t *screen);
+X_Output_Buffer *evas_software_x11_x_output_buffer_new           (xcb_connection_t *, xcb_screen_t *screen, int depth, unsigned char *pal, int w, int h, int try_shm, void *data);
+void             evas_software_x11_x_output_buffer_free          (X_Output_Buffer *xob, int sync);
+void             evas_software_x11_x_output_buffer_paste         (X_Output_Buffer *xob, xcb_drawable_t d, xcb_gcontext_t gc, int x, int y, int w, int h, int sync);
+DATA8           *evas_software_x11_x_output_buffer_data          (X_Output_Buffer *xob, int *bytes_per_line_ret);
+int              evas_software_x11_x_output_buffer_depth         (X_Output_Buffer *xob);
+int              evas_software_x11_x_output_buffer_byte_order    (X_Output_Buffer *xob);
+int              evas_software_x11_x_output_buffer_bit_order     (X_Output_Buffer *xob);
+
+#endif
diff --git a/src/modules/engines/software_8_x11/evas_x_buffer.c b/src/modules/engines/software_8_x11/evas_x_buffer.c
new file mode 100644 (file)
index 0000000..6c6b667
--- /dev/null
@@ -0,0 +1,245 @@
+#include "evas_common.h"
+#include "evas_engine.h"
+
+static int _xcb_err = 0;
+
+int
+evas_software_x11_x_can_do_shm(xcb_connection_t * c, xcb_screen_t * screen)
+{
+   static xcb_connection_t *cached_c = NULL;
+   static int cached_result = 0;
+
+   if (c == cached_c)
+      return cached_result;
+   cached_c = c;
+
+   if (xcb_get_extension_data(c, &xcb_shm_id))
+     {
+        X_Output_Buffer *xob;
+
+        xob = evas_software_x11_x_output_buffer_new(c,
+                                                    screen,
+                                                    screen->root_depth,
+                                                    (unsigned char *)NULL,
+                                                    16, 16, 2, NULL);
+        if (!xob)
+          {
+             cached_result = 0;
+             return 0;
+          }
+        evas_software_x11_x_output_buffer_free(xob, 1);
+        cached_result = 1;
+        return 1;
+     }
+   cached_result = 0;
+   return 0;
+}
+
+X_Output_Buffer *
+evas_software_x11_x_output_buffer_new(xcb_connection_t * c,
+                                      xcb_screen_t * s,
+                                      int depth,
+                                      unsigned char *pal,
+                                      int w, int h, int try_shm, void *data)
+{
+   X_Output_Buffer *xob;
+
+   xob = calloc(1, sizeof(X_Output_Buffer));
+   if (!xob)
+      return NULL;
+
+   xob->connection = c;
+   xob->screen = s;
+   xob->xim = NULL;
+   xob->shm_info = NULL;
+   xob->pal = pal;
+
+   if (try_shm > 0)
+     {
+        xob->shm_info = malloc(sizeof(xcb_shm_segment_info_t));
+        if (xob->shm_info)
+          {
+             xob->shm_info->shmseg = xcb_generate_id(c);
+             xob->xim = xcb_image_create_native(c, w, h,
+                                                XCB_IMAGE_FORMAT_Z_PIXMAP,
+                                                depth, NULL, ~0, NULL);
+             if (xob->xim)
+               {
+                  xob->shm_info->shmid = shmget(IPC_PRIVATE,
+                                                xob->xim->size,
+                                                IPC_CREAT | 0777);
+
+                  if (xob->shm_info->shmid >= 0)
+                    {
+                       xob->shm_info->shmaddr = xob->xim->data =
+                           shmat(xob->shm_info->shmid, 0, 0);
+
+                       if (xob->shm_info->shmaddr != NULL)
+                         {
+                            /*
+                             * FIXME: no error mechanism
+                             */
+
+                            /* XErrorHandler ph; */
+                            /* EventHandlers eh; */
+
+                            free(xcb_get_input_focus_reply
+                                 (c, xcb_get_input_focus_unchecked(c), NULL));
+                            _xcb_err = 0;
+                            /* ph = XSetErrorHandler((XErrorHandler) */
+                            /* x_output_tmp_x_err); */
+                            xcb_shm_attach(c,
+                                           xob->shm_info->shmseg,
+                                           xob->shm_info->shmid, 0);
+                            free(xcb_get_input_focus_reply
+                                 (c, xcb_get_input_focus_unchecked(c), NULL));
+                            /* XSetErrorHandler((XErrorHandler)ph); */
+                            if (!_xcb_err)
+                              {
+                                 xob->im =
+                                     (Soft8_Image *)
+                                     evas_cache_image_data
+                                     (evas_common_soft8_image_cache_get(), w, h,
+                                      (DATA32 *) xob->xim->data, 0,
+                                      EVAS_COLORSPACE_GRY8);
+
+                                 if (xob->im)
+                                    xob->im->stride =
+                                        xob->xim->stride / sizeof(DATA8);
+                                 return xob;
+                              }
+                         }
+                       shmdt(xob->shm_info->shmaddr);
+                       shmctl(xob->shm_info->shmid, IPC_RMID, 0);
+                    }
+                  if (xob->xim)
+                     xcb_image_destroy(xob->xim);
+                  xob->xim = NULL;
+               }
+             if (xob->shm_info)
+                free(xob->shm_info);
+             xob->shm_info = NULL;
+          }
+     }
+
+   if (try_shm > 1)
+      return NULL;
+
+   xob->xim = xcb_image_create_native(c, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
+                                      depth, NULL, ~0, NULL);
+   if (!xob->xim)
+     {
+        free(xob);
+        return NULL;
+     }
+
+   xob->data = data;
+
+   if (!xob->xim->data)
+     {
+        xob->xim->data = malloc(xob->xim->stride * xob->xim->height);
+        if (!xob->xim->data)
+          {
+             xcb_image_destroy(xob->xim);
+             free(xob);
+             return NULL;
+          }
+     }
+   if (xob->im)
+      evas_cache_image_drop(&xob->im->cache_entry);
+
+   xob->im =
+       (Soft8_Image *)
+       evas_cache_image_data(evas_common_soft8_image_cache_get(), w, h,
+                             (DATA32 *) xob->xim->data, 0,
+                             EVAS_COLORSPACE_GRY8);
+   if (xob->im)
+      xob->im->stride = xob->xim->stride / sizeof(DATA8);
+   return xob;
+}
+
+void
+evas_software_x11_x_output_buffer_free(X_Output_Buffer * xob, int sync)
+{
+   if (xob->shm_info)
+     {
+        if (sync)
+           free(xcb_get_input_focus_reply(xob->connection,
+                                          xcb_get_input_focus_unchecked(xob->
+                                                                        connection),
+                                          NULL));
+        xcb_shm_detach(xob->connection, xob->shm_info->shmseg);
+        xcb_image_destroy(xob->xim);
+        shmdt(xob->shm_info->shmaddr);
+        shmctl(xob->shm_info->shmid, IPC_RMID, 0);
+        free(xob->shm_info);
+     }
+   else
+     {
+        if (xob->data)
+           xob->xim->data = NULL;
+        free(xob->xim->data);
+        xcb_image_destroy(xob->xim);
+     }
+   free(xob);
+}
+
+void
+evas_software_x11_x_output_buffer_paste(X_Output_Buffer * xob,
+                                        xcb_drawable_t d,
+                                        xcb_gcontext_t gc,
+                                        int x, int y, int w, int h, int sync)
+{
+   unsigned char *data;
+   int i, j;
+
+   if (xob->shm_info)
+     {
+        for (i = y; i < y + h; i++)
+          {
+             data = xob->xim->data + i * xob->xim->width + x;
+             for (j = x; j < x + w; j++, data++)
+                *data = xob->pal[*data];
+          }
+
+        xcb_image_shm_put(xob->connection, d, gc,
+                          xob->xim, *xob->shm_info, x, y, x, y, w, h, 0);
+
+        if (sync)
+           free(xcb_get_input_focus_reply(xob->connection,
+                                          xcb_get_input_focus_unchecked(xob->
+                                                                        connection),
+                                          NULL));
+     }
+   else
+     {
+        xcb_image_put(xob->connection, d, gc, xob->xim, x, y, 0);
+     }
+}
+
+DATA8 *
+evas_software_x11_x_output_buffer_data(X_Output_Buffer * xob,
+                                       int *bytes_per_line_ret)
+{
+   if (bytes_per_line_ret)
+      *bytes_per_line_ret = xob->xim->stride;
+   return (DATA8 *) xob->xim->data;
+}
+
+int
+evas_software_x11_x_output_buffer_depth(X_Output_Buffer * xob)
+{
+   return xob->xim->bpp;
+}
+
+int
+evas_software_x11_x_output_buffer_byte_order(X_Output_Buffer * xob)
+{
+   return xob->xim->byte_order;
+}
+
+int
+evas_software_x11_x_output_buffer_bit_order(X_Output_Buffer * xob)
+{
+   return xob->xim->bit_order;
+}
index 5a3a266..440e291 100644 (file)
@@ -22,7 +22,8 @@ SOFTWARE_DDRAW_LIBADD = @evas_engine_software_ddraw_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/software_ddraw/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Software_DDraw.h
+includes_HEADERS = Evas_Engine_Software_DDraw.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_SOFTWARE_DDRAW
 
index 114f586..8f77a35 100644 (file)
@@ -46,7 +46,6 @@ _output_setup(int  width,
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
index 35c4bc8..dfebabe 100644 (file)
@@ -22,7 +22,8 @@ SOFTWARE_GDI_LIBADD = @evas_engine_software_gdi_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/software_gdi/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Software_Gdi.h
+includes_HEADERS = Evas_Engine_Software_Gdi.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_SOFTWARE_GDI
 
index d635147..b30c0ed 100644 (file)
@@ -44,7 +44,6 @@ _output_setup(int          width,
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
index a28185e..d9db3a0 100644 (file)
@@ -1,4 +1,4 @@
-#include "evas_common.h"
+#include "evas_common.h" /* Also includes international specific stuff */
 #include "evas_private.h"
 
 /*
@@ -212,312 +212,6 @@ eng_polygon_draw(void *data __UNUSED__, void *context, void *surface, void *poly
      }
 }
 
-static void
-eng_gradient2_color_np_stop_insert(void *data __UNUSED__, void *gradient, int r, int g, int b, int a, float pos)
-{
-   evas_common_gradient2_color_np_stop_insert(gradient, r, g, b, a, pos);
-}
-
-static void
-eng_gradient2_clear(void *data __UNUSED__, void *gradient)
-{
-   evas_common_gradient2_clear(gradient);
-}
-
-static void
-eng_gradient2_fill_transform_set(void *data __UNUSED__, void *gradient, void *transform)
-{
-   evas_common_gradient2_fill_transform_set(gradient, transform);
-}
-
-static void
-eng_gradient2_fill_spread_set(void *data __UNUSED__, void *gradient, int spread)
-{
-   evas_common_gradient2_fill_spread_set(gradient, spread);
-}
-
-static void *
-eng_gradient2_linear_new(void *data __UNUSED__)
-{
-   return evas_common_gradient2_linear_new();
-}
-
-static void
-eng_gradient2_linear_free(void *data __UNUSED__, void *linear_gradient)
-{
-   evas_common_gradient2_free(linear_gradient);
-}
-
-static void
-eng_gradient2_linear_fill_set(void *data __UNUSED__, void *linear_gradient, float x0, float y0, float x1, float y1)
-{
-   evas_common_gradient2_linear_fill_set(linear_gradient, x0, y0, x1, y1);
-}
-
-static int
-eng_gradient2_linear_is_opaque(void *data __UNUSED__, void *context, void *linear_gradient, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)linear_gradient;
-
-   if (!dc || !gr || !gr->type.geometer)  return 0;
-   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-              gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient2_linear_is_visible(void *data __UNUSED__, void *context, void *linear_gradient, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-
-   if (!dc || !linear_gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient2_linear_render_pre(void *data __UNUSED__, void *context, void *linear_gradient)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)linear_gradient;
-   int  len;
-
-   if (!dc || !gr || !gr->type.geometer)  return;
-   gr->type.geometer->geom_update(gr);
-   len = gr->type.geometer->get_map_len(gr);
-   evas_common_gradient2_map(dc, gr, len);
-}
-
-static void
-eng_gradient2_linear_render_post(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_draw(void *data __UNUSED__, void *context, void *surface, void *linear_gradient, int x, int y, int w, int h)
-{
-#ifdef BUILD_PIPE_RENDER
-   if ((cpunum > 1)
-#ifdef EVAS_FRAME_QUEUING
-        && evas_common_frameq_enabled()
-#endif
-        )
-     evas_common_pipe_grad2_draw(surface, context, x, y, w, h, linear_gradient);
-   else
-#endif
-     evas_common_gradient2_draw(surface, context, x, y, w, h, linear_gradient);
-}
-
-static void *
-eng_gradient2_radial_new(void *data __UNUSED__)
-{
-   return evas_common_gradient2_radial_new();
-}
-
-static void
-eng_gradient2_radial_free(void *data __UNUSED__, void *radial_gradient)
-{
-   evas_common_gradient2_free(radial_gradient);
-}
-
-static void
-eng_gradient2_radial_fill_set(void *data __UNUSED__, void *radial_gradient, float cx, float cy, float rx, float ry)
-{
-   evas_common_gradient2_radial_fill_set(radial_gradient, cx, cy, rx, ry);
-}
-
-static int
-eng_gradient2_radial_is_opaque(void *data __UNUSED__, void *context, void *radial_gradient, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)radial_gradient;
-
-   if (!dc || !gr || !gr->type.geometer)  return 0;
-   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-              gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient2_radial_is_visible(void *data __UNUSED__, void *context, void *radial_gradient, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-
-   if (!dc || !radial_gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient2_radial_render_pre(void *data __UNUSED__, void *context, void *radial_gradient)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)radial_gradient;
-   int  len;
-
-   if (!dc || !gr || !gr->type.geometer)  return;
-   gr->type.geometer->geom_update(gr);
-   len = gr->type.geometer->get_map_len(gr);
-   evas_common_gradient2_map(dc, gr, len);
-}
-
-static void
-eng_gradient2_radial_render_post(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_draw(void *data __UNUSED__, void *context, void *surface, void *radial_gradient, int x, int y, int w, int h)
-{
-#ifdef BUILD_PIPE_RENDER
-   if ((cpunum > 1)
-#ifdef EVAS_FRAME_QUEUING
-        && evas_common_frameq_enabled()
-#endif
-        )
-     evas_common_pipe_grad2_draw(surface, context, x, y, w, h, radial_gradient);
-   else
-#endif
-     evas_common_gradient2_draw(surface, context, x, y, w, h, radial_gradient);
-}
-
-static void *
-eng_gradient_new(void *data __UNUSED__)
-{
-   return evas_common_gradient_new();
-}
-
-static void
-eng_gradient_free(void *data __UNUSED__, void *gradient)
-{
-   evas_common_gradient_free(gradient);
-}
-
-static void
-eng_gradient_color_stop_add(void *data __UNUSED__, void *gradient, int r, int g, int b, int a, int delta)
-{
-   evas_common_gradient_color_stop_add(gradient, r, g, b, a, delta);
-}
-
-static void
-eng_gradient_alpha_stop_add(void *data __UNUSED__, void *gradient, int a, int delta)
-{
-   evas_common_gradient_alpha_stop_add(gradient, a, delta);
-}
-
-static void
-eng_gradient_color_data_set(void *data __UNUSED__, void *gradient, void *map, int len, int has_alpha)
-{
-   evas_common_gradient_color_data_set(gradient, map, len, has_alpha);
-}
-
-static void
-eng_gradient_alpha_data_set(void *data __UNUSED__, void *gradient, void *alpha_map, int len)
-{
-   evas_common_gradient_alpha_data_set(gradient, alpha_map, len);
-}
-
-static void
-eng_gradient_clear(void *data __UNUSED__, void *gradient)
-{
-   evas_common_gradient_clear(gradient);
-}
-
-static void
-eng_gradient_fill_set(void *data __UNUSED__, void *gradient, int x, int y, int w, int h)
-{
-   evas_common_gradient_fill_set(gradient, x, y, w, h);
-}
-
-static void
-eng_gradient_fill_angle_set(void *data __UNUSED__, void *gradient, double angle)
-{
-   evas_common_gradient_fill_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_fill_spread_set(void *data __UNUSED__, void *gradient, int spread)
-{
-   evas_common_gradient_fill_spread_set(gradient, spread);
-}
-
-static void
-eng_gradient_angle_set(void *data __UNUSED__, void *gradient, double angle)
-{
-   evas_common_gradient_map_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_offset_set(void *data __UNUSED__, void *gradient, float offset)
-{
-   evas_common_gradient_map_offset_set(gradient, offset);
-}
-
-static void
-eng_gradient_direction_set(void *data __UNUSED__, void *gradient, int direction)
-{
-   evas_common_gradient_map_direction_set(gradient, direction);
-}
-
-static void
-eng_gradient_type_set(void *data __UNUSED__, void *gradient, char *name, char *params)
-{
-   evas_common_gradient_type_set(gradient, name, params);
-}
-
-static int
-eng_gradient_is_opaque(void *data __UNUSED__, void *context, void *gradient, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient *gr = (RGBA_Gradient *)gradient;
-
-   if (!dc || !gr || !gr->type.geometer)  return 0;
-   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
-              gr->type.geometer->has_mask(gr, dc->render_op));
-}
-
-static int
-eng_gradient_is_visible(void *data __UNUSED__, void *context, void *gradient, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-
-   if (!dc || !gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient_render_pre(void *data __UNUSED__, void *context, void *gradient)
-{
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-   RGBA_Gradient *gr = (RGBA_Gradient *)gradient;
-   int  len;
-
-   if (!dc || !gr || !gr->type.geometer)  return;
-   gr->type.geometer->geom_set(gr);
-   len = gr->type.geometer->get_map_len(gr);
-   evas_common_gradient_map(dc, gr, len);
-}
-
-static void
-eng_gradient_render_post(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient_draw(void *data __UNUSED__, void *context, void *surface, void *gradient, int x, int y, int w, int h)
-{
-#ifdef BUILD_PIPE_RENDER
-   if ((cpunum > 1)
-#ifdef EVAS_FRAME_QUEUING
-        && evas_common_frameq_enabled()
-#endif
-        )
-     evas_common_pipe_grad_draw(surface, context, x, y, w, h, gradient);
-   else
-#endif   
-     {
-       evas_common_gradient_draw(surface, context, x, y, w, h, gradient);
-       evas_common_cpu_end_opt();
-     }
-}
-
 static int
 eng_image_alpha_get(void *data __UNUSED__, void *image)
 {
@@ -607,9 +301,10 @@ eng_image_colorspace_set(void *data __UNUSED__, void *image, int cspace)
    evas_cache_image_colorspace(im, cspace);
 }
 
-static void
-eng_image_native_set(void *data __UNUSED__, void *image __UNUSED__, void *native __UNUSED__)
+static void *
+eng_image_native_set(void *data __UNUSED__, void *image, void *native __UNUSED__)
 {
+   return image;
 }
 
 static void *
@@ -775,7 +470,8 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image,
 #endif
         )
      {
-        evas_common_rgba_image_scalecache_prepare(im, surface, context, smooth,
+        evas_common_rgba_image_scalecache_prepare((Image_Entry *)(im), 
+                                                  surface, context, smooth,
                                                   src_x, src_y, src_w, src_h,
                                                   dst_x, dst_y, dst_w, dst_h);
         
@@ -813,7 +509,7 @@ static void
 eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level)
 {
    RGBA_Image *im, *srf;
-   RGBA_Map_Point *pt = p;
+//   RGBA_Map_Point *pt = p;
 
    if (!image) return;
    im = image;
@@ -862,7 +558,6 @@ eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *i
           evas_common_map4_rgba(im, surface, context, p, smooth, level);
      }
    evas_common_cpu_end_opt();
-
 }
 
 static void *
@@ -982,55 +677,55 @@ eng_font_max_descent_get(void *data __UNUSED__, void *font)
 }
 
 static void
-eng_font_string_size_get(void *data __UNUSED__, void *font, const char *text, int *w, int *h)
+eng_font_string_size_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props, int *w, int *h)
 {
-   evas_common_font_query_size(font, text, w, h);
+   evas_common_font_query_size(font, text, intl_props, w, h);
 }
 
 static int
-eng_font_inset_get(void *data __UNUSED__, void *font, const char *text)
+eng_font_inset_get(void *data __UNUSED__, void *font, const Eina_Unicode *text)
 {
    return evas_common_font_query_inset(font, text);
 }
 
 static int
-eng_font_h_advance_get(void *data __UNUSED__, void *font, const char *text)
+eng_font_h_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
 {
    int h, v;
 
-   evas_common_font_query_advance(font, text, &h, &v);
+   evas_common_font_query_advance(font, text, intl_props, &h, &v);
    return h;
 }
 
 static int
-eng_font_v_advance_get(void *data __UNUSED__, void *font, const char *text)
+eng_font_v_advance_get(void *data __UNUSED__, void *font, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
 {
    int h, v;
 
-   evas_common_font_query_advance(font, text, &h, &v);
+   evas_common_font_query_advance(font, text, intl_props, &h, &v);
    return v;
 }
 
 static int
-eng_font_char_coords_get(void *data __UNUSED__, void *font, const char *text, int pos, int *cx, int *cy, int *cw, int *ch)
+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)
 {
-   return evas_common_font_query_char_coords(font, text, pos, cx, cy, cw, ch);
+   return evas_common_font_query_char_coords(font, text, intl_props, pos, cx, cy, cw, ch);
 }
 
 static int
-eng_font_char_at_coords_get(void *data __UNUSED__, void *font, const char *text, 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_BiDi_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch)
 {
-   return evas_common_font_query_text_at_pos(font, text, x, y, cx, cy, cw, ch);
+   return evas_common_font_query_char_at_coords(font, text, intl_props, x, y, cx, cy, cw, ch);
 }
 
 static int
-eng_font_last_up_to_pos(void *data __UNUSED__, void *font, const char *text, int x, int y)
+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)
 {
-   return evas_common_font_query_last_up_to_pos(font, text, x, y);
+   return evas_common_font_query_last_up_to_pos(font, text, intl_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 char *text)
+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)
 {
 #ifdef BUILD_PIPE_RENDER
    if ((cpunum > 1)
@@ -1038,11 +733,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);
+     evas_common_pipe_text_draw(surface, context, font, x, y, text, intl_props);
    else
 #endif   
      {
-       evas_common_font_draw(surface, context, font, x, y, text);
+       evas_common_font_draw(surface, context, font, x, y, text, intl_props);
        evas_common_cpu_end_opt();
      }
 }
@@ -1136,49 +831,6 @@ static Evas_Func func =
      eng_polygon_point_add,
      eng_polygon_points_clear,
      eng_polygon_draw,
-     /* gradient draw funcs */
-     eng_gradient2_color_np_stop_insert,
-     eng_gradient2_clear,
-     eng_gradient2_fill_transform_set,
-     eng_gradient2_fill_spread_set,
-
-     eng_gradient2_linear_new,
-     eng_gradient2_linear_free,
-     eng_gradient2_linear_fill_set,
-     eng_gradient2_linear_is_opaque,
-     eng_gradient2_linear_is_visible,
-     eng_gradient2_linear_render_pre,
-     eng_gradient2_linear_render_post,
-     eng_gradient2_linear_draw,
-
-     eng_gradient2_radial_new,
-     eng_gradient2_radial_free,
-     eng_gradient2_radial_fill_set,
-     eng_gradient2_radial_is_opaque,
-     eng_gradient2_radial_is_visible,
-     eng_gradient2_radial_render_pre,
-     eng_gradient2_radial_render_post,
-     eng_gradient2_radial_draw,
-
-     eng_gradient_new,
-     eng_gradient_free,
-     eng_gradient_color_stop_add,
-     eng_gradient_alpha_stop_add,
-     eng_gradient_color_data_set,
-     eng_gradient_alpha_data_set,
-     eng_gradient_clear,
-     eng_gradient_fill_set,
-     eng_gradient_fill_angle_set,
-     eng_gradient_fill_spread_set,
-     eng_gradient_angle_set,
-     eng_gradient_offset_set,
-     eng_gradient_direction_set,
-     eng_gradient_type_set,
-     eng_gradient_is_opaque,
-     eng_gradient_is_visible,
-     eng_gradient_render_pre,
-     eng_gradient_render_post,
-     eng_gradient_draw,
      /* image draw funcs */
      eng_image_load,
      eng_image_new_from_data,
@@ -1238,7 +890,9 @@ static Evas_Func func =
      /* FUTURE software generic calls go here (done) */
      eng_image_map4_draw,
      eng_image_map_surface_new,
-     eng_image_map_surface_free
+     eng_image_map_surface_free,
+     NULL, // eng_image_content_hint_set - software doesnt use it
+     NULL // eng_image_content_hint_get - software doesnt use it
      /* FUTURE software generic calls go here */
 };
 
index a8ac900..a4202a9 100644 (file)
@@ -23,7 +23,8 @@ SOFTWARE_QTOPIA_LIBADD = @evas_engine_software_qtopia_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/software_qtopia/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Software_Qtopia.h
+includes_HEADERS = Evas_Engine_Software_Qtopia.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_SOFTWARE_QTOPIA
 
index bee5a80..a30cb7c 100644 (file)
@@ -53,7 +53,6 @@ _output_setup(int w, int h, int rot, QWidget *target)
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
index 8f075c3..4e3e386 100644 (file)
@@ -19,7 +19,8 @@ SOFTWARE_SDL_LIBADD = @evas_engine_software_sdl_libs@
 
 pkgdir = $(libdir)/evas/modules/engines/software_sdl/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_SDL.h
+includes_HEADERS = Evas_Engine_SDL.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_SOFTWARE_SDL
 
index db1e590..bcaa3c9 100644 (file)
@@ -5,7 +5,7 @@
 #include <time.h>
 #include <SDL/SDL.h>
 
-#include "evas_common.h"
+#include "evas_common.h" /* Also includes international specific stuff */
 #include "evas_engine.h"
 
 int _evas_engine_soft_sdl_log_dom = -1;
@@ -739,7 +739,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 char *text)
+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)
 {
    SDL_Engine_Image_Entry       *eim = surface;
    int                           mustlock_im = 0;
@@ -751,7 +751,7 @@ evas_engine_sdl_font_draw(void *data __UNUSED__, void *context, void *surface, v
        _SDL_UPDATE_PIXELS(eim);
      }
 
-   evas_common_font_draw((RGBA_Image *) eim->cache_entry.src, context, font, x, y, text);
+   evas_common_font_draw((RGBA_Image *) eim->cache_entry.src, context, font, x, y, text, intl_props);
    evas_common_cpu_end_opt();
 
    if (mustlock_im)
@@ -857,26 +857,6 @@ evas_engine_sdl_polygon_draw(void *data __UNUSED__, void *context, void *surface
      SDL_UnlockSurface(eim->surface);
 }
 
-static void
-evas_engine_sdl_gradient_draw(void *data __UNUSED__, void *context, void *surface, void *gradient, int x, int y, int w, int h)
-{
-   SDL_Engine_Image_Entry       *eim = surface;
-   int                           mustlock_im = 0;
-
-   if (eim->surface && SDL_MUSTLOCK(eim->surface))
-     {
-        mustlock_im = 1;
-       SDL_LockSurface(eim->surface);
-       _SDL_UPDATE_PIXELS(eim);
-     }
-
-   evas_common_gradient_draw((RGBA_Image *) eim->cache_entry.src, context, x, y, w, h, gradient);
-   evas_common_cpu_end_opt();
-
-   if (mustlock_im)
-     SDL_UnlockSurface(eim->surface);
-}
-
 static int module_open(Evas_Module *em)
 {
    if (!em) return 0;
@@ -935,11 +915,10 @@ static int module_open(Evas_Module *em)
    ORD(line_draw);
    ORD(rectangle_draw);
    ORD(polygon_draw);
-   ORD(gradient_draw);
-   
+
    ORD(image_scale_hint_set);
    ORD(image_scale_hint_get);
-   
+
    /* now advertise out own api */
    em->functions = (void *)(&func);
    return 1;
@@ -982,7 +961,6 @@ _sdl_output_setup           (int w, int h, int fullscreen, int noframe, int alpha, int hw
    evas_common_convert_init();
    evas_common_scale_init();
    evas_common_rectangle_init();
-   evas_common_gradient_init();
    evas_common_polygon_init();
    evas_common_line_init();
    evas_common_font_init();
index 8d7ae13..7e20f2d 100644 (file)
@@ -39,7 +39,8 @@ endif
 
 pkgdir = $(libdir)/evas/modules/engines/software_x11/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_Software_X11.h
+includes_HEADERS = Evas_Engine_Software_X11.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_SOFTWARE_X11
 
index 0812e4c..bc1d8ca 100644 (file)
@@ -475,7 +475,6 @@ eng_setup(Evas *e, void *in)
         evas_common_convert_init();
         evas_common_scale_init();
         evas_common_rectangle_init();
-        evas_common_gradient_init();
         evas_common_polygon_init();
         evas_common_line_init();
         evas_common_font_init();
index 83d1a77..74df4bd 100644 (file)
@@ -15,7 +15,6 @@ if BUILD_ENGINE_XRENDER_X11
 
 XRENDER_X11_SOURCES = \
 evas_engine_xlib_font.c \
-evas_engine_xlib_gradient.c \
 evas_engine_xlib_image.c \
 evas_engine_xlib_render.c \
 evas_engine_xlib_ximage.c \
@@ -25,7 +24,6 @@ if BUILD_ENGINE_XRENDER_XCB
 
 XRENDER_X11_SOURCES += \
 evas_engine_xcb_font.c \
-evas_engine_xcb_gradient.c \
 evas_engine_xcb_image.c \
 evas_engine_xcb_render.c \
 evas_engine_xcb_ximage.c
@@ -36,7 +34,8 @@ XRENDER_X11_LIBADD = @evas_engine_xrender_xcb_libs@ @evas_engine_xrender_x11_lib
 
 pkgdir = $(libdir)/evas/modules/engines/xrender_x11/$(MODULE_ARCH)
 
-include_HEADERS = Evas_Engine_XRender_X11.h
+includes_HEADERS = Evas_Engine_XRender_X11.h
+includesdir = $(includedir)/evas-@VMAJ@
 
 if !EVAS_STATIC_BUILD_XRENDER_X11
 
index fcb4f09..697689b 100644 (file)
@@ -1,4 +1,4 @@
-#include "evas_common.h"
+#include "evas_common.h" /* Also includes international specific stuff */
 #include "evas_private.h"
 
 #include "Evas_Engine_XRender_X11.h"
@@ -95,27 +95,11 @@ struct _Render_Engine
 
    Eina_List       *updates;
 
-   void *(*font_surface_new)(void *xinf, RGBA_Font_Glyph *fg);
-   void (*font_surface_free)(void *fs);
-   void (*font_surface_draw)(void *xinf, void *surface, void *dc, RGBA_Font_Glyph *fg, int x, int y);
-
-   XR_Gradient *(*gradient_new)(Ximage_Info *xinf);
-   void (*gradient_free)(XR_Gradient *gr);
-   void (*gradient_color_stop_add)(XR_Gradient *gr, int r, int g, int b, int a, int delta);
-   void (*gradient_alpha_stop_add)(XR_Gradient *gr, int a, int delta);
-   void (*gradient_color_data_set)(XR_Gradient *gr, void *map, int len, int has_alpha);
-   void (*gradient_alpha_data_set)(XR_Gradient *gr, void *alpha_map, int len);
-   void (*gradient_clear)(XR_Gradient *gr);
-   void (*gradient_fill_set)(XR_Gradient *gr, int x, int y, int w, int h);
-   void (*gradient_fill_angle_set)(XR_Gradient *gr, double angle);
-   void (*gradient_fill_spread_set)(XR_Gradient *gr, int spread);
-   void (*gradient_angle_set)(XR_Gradient *gr, double angle);
-   void (*gradient_offset_set)(XR_Gradient *gr, float offset);
-   void (*gradient_direction_set)(XR_Gradient *gr, int direction);
-   void (*gradient_type_set)(XR_Gradient *gr, char *name, char *params);
-   void (*gradient_draw)(Xrender_Surface *rs, RGBA_Draw_Context *dc, XR_Gradient *gr, int x, int y, int w, int h);
-
-   XR_Image *(*image_load)(Ximage_Info *xinf, const char *file, const char *key, Evas_Image_Load_Opts *lo);
+   XR_Font_Surface *(*font_surface_new)(Ximage_Info *xinf, RGBA_Font_Glyph *fg);
+   void (*font_surface_free)(XR_Font_Surface *fs);
+   void (*font_surface_draw)(Ximage_Info *xinf, RGBA_Image *surface, RGBA_Draw_Context *dc, RGBA_Font_Glyph *fg, int x, int y);
+
+   XR_Image *(*image_load)(Ximage_Info *xinf, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error);
    XR_Image *(*image_new_from_data)(Ximage_Info *xinf, int w, int h, void *data, int alpha, int cspace);
    XR_Image *(*image_new_from_copied_data)(Ximage_Info *xinf, int w, int h, void *data, int alpha, int cspace);
    XR_Image *(*image_new)(Ximage_Info *xinf, int w, int h);
@@ -135,7 +119,7 @@ struct _Render_Engine
    void (*image_cache_set)(int size);
    int  (*image_cache_get)(void);
 
-   Ximage_Info *(*ximage_info_get)(void *connection, unsigned int draw, void *vis);
+   Ximage_Info *(*ximage_info_get)(Display *connection, Drawable draw, Visual *vis);
    void (*ximage_info_free)(Ximage_Info *xinf);
    void (*ximage_info_pool_flush)(Ximage_Info *xinf, int max_num, int max_mem);
    Ximage_Image *(*ximage_new)(Ximage_Info *xinf, int w, int h, int depth);
@@ -143,8 +127,8 @@ struct _Render_Engine
    void (*ximage_put)(Ximage_Image *xim, Drawable draw, int x, int y, int w, int h);
 
    Xrender_Surface *(*render_surface_new)(Ximage_Info *xinf, int w, int h, XRenderPictFormat *fmt, int alpha);
-   Xrender_Surface *(*render_surface_adopt)(Ximage_Info *xinf, unsigned int draw, int w, int h, int alpha);
-   Xrender_Surface *(*render_surface_format_adopt)(Ximage_Info *xinf, unsigned int draw, int w, int h, void *fmt, int alpha);
+   Xrender_Surface *(*render_surface_adopt)(Ximage_Info *xinf, Drawable draw, int w, int h, int alpha);
+   Xrender_Surface *(*render_surface_format_adopt)(Ximage_Info *xinf, Drawable draw, int w, int h, XRenderPictFormat *fmt, int alpha);
    void (*render_surface_free)(Xrender_Surface *rs);
    void (*render_surface_repeat_set)(Xrender_Surface *rs, int repeat);
    void (*render_surface_solid_rectangle_set)(Xrender_Surface *rs, int r, int g, int b, int a, int x, int y, int w, int h);
@@ -213,22 +197,6 @@ _output_xlib_setup(int           width,
    re->font_surface_free = _xre_xlib_font_surface_free;
    re->font_surface_draw = _xre_xlib_font_surface_draw;
 
-   re->gradient_new = _xre_xlib_gradient_new;
-   re->gradient_free = _xre_xlib_gradient_free;
-   re->gradient_color_stop_add = _xre_xlib_gradient_color_stop_add;
-   re->gradient_alpha_stop_add = _xre_xlib_gradient_alpha_stop_add;
-   re->gradient_color_data_set = _xre_xlib_gradient_color_data_set;
-   re->gradient_alpha_data_set = _xre_xlib_gradient_alpha_data_set;
-   re->gradient_clear = _xre_xlib_gradient_clear;
-   re->gradient_fill_set = _xre_xlib_gradient_fill_set;
-   re->gradient_fill_angle_set = _xre_xlib_gradient_fill_angle_set;
-   re->gradient_fill_spread_set = _xre_xlib_gradient_fill_spread_set;
-   re->gradient_angle_set = _xre_xlib_gradient_angle_set;
-   re->gradient_offset_set = _xre_xlib_gradient_offset_set;
-   re->gradient_direction_set = _xre_xlib_gradient_direction_set;
-   re->gradient_type_set = _xre_xlib_gradient_type_set;
-   re->gradient_draw = _xre_xlib_gradient_draw;
-
    re->image_load = _xre_xlib_image_load;
    re->image_new_from_data = _xre_xlib_image_new_from_data;
    re->image_new_from_copied_data = _xre_xlib_image_new_from_copied_data;
@@ -391,22 +359,6 @@ _output_xcb_setup(int           width,
    re->font_surface_free = _xre_xcb_font_surface_free;
    re->font_surface_draw = _xre_xcb_font_surface_draw;
 
-   re->gradient_new = _xre_xcb_gradient_new;
-   re->gradient_free = _xre_xcb_gradient_free;
-   re->gradient_color_stop_add = _xre_xcb_gradient_color_stop_add;
-   re->gradient_alpha_stop_add = _xre_xcb_gradient_alpha_stop_add;
-   re->gradient_color_data_set = _xre_xcb_gradient_color_data_set;
-   re->gradient_alpha_data_set = _xre_xcb_gradient_alpha_data_set;
-   re->gradient_clear = _xre_xcb_gradient_clear;
-   re->gradient_fill_set = _xre_xcb_gradient_fill_set;
-   re->gradient_fill_angle_set = _xre_xcb_gradient_fill_angle_set;
-   re->gradient_fill_spread_set = _xre_xcb_gradient_fill_spread_set;
-   re->gradient_angle_set = _xre_xcb_gradient_angle_set;
-   re->gradient_offset_set = _xre_xcb_gradient_offset_set;
-   re->gradient_direction_set = _xre_xcb_gradient_direction_set;
-   re->gradient_type_set = _xre_xcb_gradient_type_set;
-   re->gradient_draw = _xre_xcb_gradient_draw;
-
    re->image_load = _xre_xcb_image_load;
    re->image_new_from_data = _xre_xcb_image_new_from_data;
    re->image_new_from_copied_data = _xre_xcb_image_new_from_copied_data;
@@ -474,7 +426,7 @@ eng_info_free(Evas *e __UNUSED__, void *info)
    free(in);
 }
 
-static void
+static int
 eng_setup(Evas *e, void *in)
 {
    Render_Engine *re = NULL;
@@ -490,7 +442,6 @@ eng_setup(Evas *e, void *in)
        evas_common_convert_init();
        evas_common_scale_init();
        evas_common_rectangle_init();
-       evas_common_gradient_init();
        evas_common_polygon_init();
        evas_common_line_init();
        evas_common_font_init();
@@ -548,6 +499,8 @@ eng_setup(Evas *e, void *in)
         if (re->tb)
          evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
      }
+
+   return 1;
 }
 
 static void
@@ -787,272 +740,6 @@ eng_polygon_draw(void *data, void *context, void *surface, void *polygon, int x,
    re->render_surface_polygon_draw((Xrender_Surface *)surface, (RGBA_Draw_Context *)context, (RGBA_Polygon_Point *)polygon, x, y);
 }
 
-
-static void
-eng_gradient2_color_np_stop_insert(void *data __UNUSED__, void *gradient __UNUSED__, int r __UNUSED__, int g __UNUSED__, int b __UNUSED__, int a __UNUSED__, float pos __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_clear(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_fill_transform_set(void *data __UNUSED__, void *gradient __UNUSED__, void *transform __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_fill_spread_set(void *data __UNUSED__, void *gradient __UNUSED__, int spread __UNUSED__)
-{
-}
-
-static void *
-eng_gradient2_linear_new(void *data __UNUSED__)
-{
-   return NULL;
-}
-
-static void
-eng_gradient2_linear_free(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_fill_set(void *data __UNUSED__, void *linear_gradient __UNUSED__, int x0 __UNUSED__, int y0 __UNUSED__, int x1 __UNUSED__, int y1 __UNUSED__)
-{
-}
-
-static int
-eng_gradient2_linear_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static int
-eng_gradient2_linear_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static void
-eng_gradient2_linear_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_render_post(void *data __UNUSED__, void *linear_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_linear_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *linear_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-}
-
-static void *
-eng_gradient2_radial_new(void *data __UNUSED__)
-{
-   return NULL;
-}
-
-static void
-eng_gradient2_radial_free(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_fill_set(void *data __UNUSED__, void *radial_gradient __UNUSED__, float cx __UNUSED__, float cy __UNUSED__, float rx __UNUSED__, float ry __UNUSED__)
-{
-}
-
-static int
-eng_gradient2_radial_is_opaque(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static int
-eng_gradient2_radial_is_visible(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   return 1;
-}
-
-static void
-eng_gradient2_radial_render_pre(void *data __UNUSED__, void *context __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_render_post(void *data __UNUSED__, void *radial_gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient2_radial_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *radial_gradient __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-}
-
-static void *
-eng_gradient_new(void *data)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   return re->gradient_new(re->xinf);
-}
-
-static void
-eng_gradient_free(void *data, void *gradient)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_free(gradient);
-}
-
-static void
-eng_gradient_color_stop_add(void *data, void *gradient, int r, int g, int b, int a, int delta)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_color_stop_add(gradient, r, g, b, a, delta);
-}
-
-static void
-eng_gradient_alpha_stop_add(void *data, void *gradient, int a, int delta)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_alpha_stop_add(gradient, a, delta);
-}
-
-static void
-eng_gradient_color_data_set(void *data, void *gradient, void *map, int len, int has_alpha)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_color_data_set(gradient, map, len, has_alpha);
-}
-
-static void
-eng_gradient_alpha_data_set(void *data, void *gradient, void *alpha_map, int len)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_alpha_data_set(gradient, alpha_map, len);
-}
-
-static void
-eng_gradient_clear(void *data, void *gradient)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_clear(gradient);
-}
-
-static void
-eng_gradient_fill_set(void *data, void *gradient, int x, int y, int w, int h)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_fill_set(gradient, x, y, w, h);
-}
-
-static void
-eng_gradient_fill_angle_set(void *data, void *gradient, double angle)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_fill_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_fill_spread_set(void *data, void *gradient, int spread)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_fill_spread_set(gradient, spread);
-}
-
-static void
-eng_gradient_angle_set(void *data, void *gradient, double angle)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_angle_set(gradient, angle);
-}
-
-static void
-eng_gradient_offset_set(void *data, void *gradient, float offset)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_offset_set(gradient, offset);
-}
-
-static void
-eng_gradient_direction_set(void *data, void *gradient, int direction)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_direction_set(gradient, direction);
-}
-
-static void
-eng_gradient_type_set(void *data, void *gradient, char *name, char *params)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_type_set(gradient, name, params);
-}
-
-static int
-eng_gradient_is_opaque(void *data __UNUSED__, void *context, void *gradient, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   RGBA_Gradient  *grad;
-   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
-
-   if (!dc || !gradient) return 0;
-   grad = ((XR_Gradient *)gradient)->grad;
-   if(!grad || !grad->type.geometer)  return 0;
-   return !(grad->type.geometer->has_alpha(grad, dc->render_op) |
-              grad->type.geometer->has_mask(grad, dc->render_op));
-}
-
-static int
-eng_gradient_is_visible(void *data __UNUSED__, void *context, void *gradient, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
-{
-   if (!context || !gradient)  return 0;
-   return 1;
-}
-
-static void
-eng_gradient_render_pre(void *data __UNUSED__, void *context, void *gradient)
-{
-   int  len;
-   RGBA_Gradient  *grad;
-
-   if (!context || !gradient) return;
-   grad = ((XR_Gradient *)gradient)->grad;
-   if(!grad || !grad->type.geometer)  return;
-   grad->type.geometer->geom_set(grad);
-   len = grad->type.geometer->get_map_len(grad);
-   evas_common_gradient_map(context, grad, len);
-}
-
-static void
-eng_gradient_render_post(void *data __UNUSED__, void *gradient __UNUSED__)
-{
-}
-
-static void
-eng_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h)
-{
-   Render_Engine *re = (Render_Engine *)data;
-
-   re->gradient_draw(surface, context, gradient, x, y, w, h);
-}
-
 static int
 eng_image_alpha_get(void *data, void *image)
 {
@@ -1183,9 +870,10 @@ eng_image_colorspace_set(void *data, void *image, int cspace)
    re->image_region_dirty(im, 0, 0, im->w, im->h);
 }
 
-static void
+static void *
 eng_image_native_set(void *data __UNUSED__, void *image __UNUSED__, void *native __UNUSED__)
 {
+   return NULL;
 }
 
 static void *
@@ -1202,7 +890,7 @@ eng_image_load(void *data, const char *file, const char *key, int *error, Evas_I
 
    re = (Render_Engine *)data;
    *error = 0;
-   im = re->image_load(re->xinf, file, key, lo);
+   im = re->image_load(re->xinf, file, key, lo, error);
    return im;
 }
 
@@ -1484,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 char *text)
+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)
 {
    Render_Engine        *re;
    RGBA_Image           *im;
@@ -1500,10 +1188,11 @@ eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y
                                              0, EVAS_COLORSPACE_ARGB8888);
    evas_common_draw_context_font_ext_set((RGBA_Draw_Context *)context,
                                          re->xinf,
-                                         re->font_surface_new,
-                                         re->font_surface_free,
-                                         re->font_surface_draw);
-   evas_common_font_draw(im, context, font, x, y, text);
+            (void *(*)(void *, RGBA_Font_Glyph *)) re->font_surface_new,
+            (void (*)(void *))           re->font_surface_free,
+            (void  (*) (void *, void *, void *, RGBA_Font_Glyph *, int, int))
+                 re->font_surface_draw);
+   evas_common_font_draw(im, context, font, x, y, text, intl_props);
    evas_common_draw_context_font_ext_set(context,
                                          NULL,
                                          NULL,
@@ -1568,46 +1257,6 @@ module_open(Evas_Module *em)
    ORD(line_draw);
    ORD(polygon_draw);
 
-   ORD(gradient2_color_np_stop_insert);
-   ORD(gradient2_clear);
-   ORD(gradient2_fill_transform_set);
-   ORD(gradient2_fill_spread_set);
-   ORD(gradient2_linear_new);
-   ORD(gradient2_linear_free);
-   ORD(gradient2_linear_fill_set);
-   ORD(gradient2_linear_is_opaque);
-   ORD(gradient2_linear_is_visible);
-   ORD(gradient2_linear_render_pre);
-   ORD(gradient2_linear_render_post);
-   ORD(gradient2_linear_draw);
-   ORD(gradient2_radial_new);
-   ORD(gradient2_radial_free);
-   ORD(gradient2_radial_fill_set);
-   ORD(gradient2_radial_is_opaque);
-   ORD(gradient2_radial_is_visible);
-   ORD(gradient2_radial_render_pre);
-   ORD(gradient2_radial_render_post);
-   ORD(gradient2_radial_draw);
-
-   ORD(gradient_new);
-   ORD(gradient_free);
-   ORD(gradient_color_stop_add);
-   ORD(gradient_alpha_stop_add);
-   ORD(gradient_color_data_set);
-   ORD(gradient_alpha_data_set);
-   ORD(gradient_clear);
-   ORD(gradient_fill_set);
-   ORD(gradient_fill_angle_set);
-   ORD(gradient_fill_spread_set);
-   ORD(gradient_angle_set);
-   ORD(gradient_offset_set);
-   ORD(gradient_direction_set);
-   ORD(gradient_type_set);
-   ORD(gradient_is_opaque);
-   ORD(gradient_is_visible);
-   ORD(gradient_render_pre);
-   ORD(gradient_render_post);
-   ORD(gradient_draw);
    ORD(image_load);
    ORD(image_new_from_data);
    ORD(image_new_from_copied_data);
index d5bea6e..d58e547 100644 (file)
@@ -261,49 +261,4 @@ void             _xre_xcb_font_surface_free(XR_Font_Surface *fs);
 void             _xre_xcb_font_surface_draw(Ximage_Info *xinf, RGBA_Image *surface, RGBA_Draw_Context *dc, RGBA_Font_Glyph *fg, int x, int y);
 #endif
 
-typedef struct _XR_Gradient XR_Gradient;
-
-struct _XR_Gradient
-{
-   Ximage_Info     *xinf;
-   Xrender_Surface *surface;
-   RGBA_Gradient   *grad;
-   unsigned char    changed : 1;
-   int              sw, sh;
-};
-
-XR_Gradient *_xre_xlib_gradient_new(Ximage_Info *xinf);
-void         _xre_xlib_gradient_free(XR_Gradient *gr);
-void         _xre_xlib_gradient_color_stop_add(XR_Gradient *gr, int r, int g, int b, int a, int delta);
-void         _xre_xlib_gradient_alpha_stop_add(XR_Gradient *gr, int a, int delta);
-void         _xre_xlib_gradient_color_data_set(XR_Gradient *gr, void *map, int len, int has_alpha);
-void         _xre_xlib_gradient_alpha_data_set(XR_Gradient *gr, void *alpha_map, int len);
-void         _xre_xlib_gradient_clear(XR_Gradient *gr);
-void         _xre_xlib_gradient_fill_set(XR_Gradient *gr, int x, int y, int w, int h);
-void         _xre_xlib_gradient_fill_angle_set(XR_Gradient *gr, double angle);
-void         _xre_xlib_gradient_fill_spread_set(XR_Gradient *gr, int spread);
-void         _xre_xlib_gradient_angle_set(XR_Gradient *gr, double angle);
-void         _xre_xlib_gradient_offset_set(XR_Gradient *gr, float offset);
-void         _xre_xlib_gradient_direction_set(XR_Gradient *gr, int direction);
-void         _xre_xlib_gradient_type_set(XR_Gradient *gr, char *name, char *params);
-void         _xre_xlib_gradient_draw(Xrender_Surface *rs, RGBA_Draw_Context *dc, XR_Gradient *gr, int x, int y, int w, int h);
-
-#ifdef BUILD_ENGINE_XRENDER_XCB
-XR_Gradient *_xre_xcb_gradient_new(Ximage_Info *xinf);
-void         _xre_xcb_gradient_free(XR_Gradient *gr);
-void         _xre_xcb_gradient_color_stop_add(XR_Gradient *gr, int r, int g, int b, int a, int delta);
-void         _xre_xcb_gradient_alpha_stop_add(XR_Gradient *gr, int a, int delta);
-void         _xre_xcb_gradient_color_data_set(XR_Gradient *gr, void *map, int len, int has_alpha);
-void         _xre_xcb_gradient_alpha_data_set(XR_Gradient *gr, void *alpha_map, int len);
-void         _xre_xcb_gradient_clear(XR_Gradient *gr);
-void         _xre_xcb_gradient_fill_set(XR_Gradient *gr, int x, int y, int w, int h);
-void         _xre_xcb_gradient_fill_angle_set(XR_Gradient *gr, double angle);
-void         _xre_xcb_gradient_fill_spread_set(XR_Gradient *gr, int spread);
-void         _xre_xcb_gradient_angle_set(XR_Gradient *gr, double angle);
-void         _xre_xcb_gradient_offset_set(XR_Gradient *gr, float offset);
-void         _xre_xcb_gradient_direction_set(XR_Gradient *gr, int direction);
-void         _xre_xcb_gradient_type_set(XR_Gradient *gr, char *name, char *params);
-void         _xre_xcb_gradient_draw(Xrender_Surface *rs, RGBA_Draw_Context *dc, XR_Gradient *gr, int x, int y, int w, int h);
-#endif
-
 #endif
index 9b4825b..c5a283e 100644 (file)
@@ -1,6 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
 #include "evas_common.h"
 /* #include "evas_macros.h" */
 #include "evas_private.h"
index 2a597ef..404567b 100644 (file)
@@ -1,6 +1,3 @@
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
 #include "evas_common.h"
 //#include "evas_macros.h"
 #include "evas_private.h"
index 8b0d6f0..6fd0aa0 100644 (file)
@@ -1,4 +1,3 @@
-
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
@@ -34,13 +33,31 @@ read_short(FILE *file, short *ret)
    *ret = (b[1] << 8) | b[0];
    return 1;
 }
-      
+
+static int
+read_ushort(FILE *file, unsigned short *ret)
+{
+   unsigned char b[2];
+   if (fread(b, sizeof(unsigned char), 2, file) != 2) return 0;
+   *ret = (b[1] << 8) | b[0];
+   return 1;
+}
+
 static int
 read_int(FILE *file, int *ret)
 {
+   unsigned char b[4];
+   if (fread(b, sizeof(unsigned char), 4, file) != 4) return 0;
+   *ret = ARGB_JOIN(b[3], b[2], b[1], b[0]);
+   return 1;
+}
+
+static int
+read_uint(FILE *file, unsigned int *ret)
+{
    unsigned char       b[4];
    if (fread(b, sizeof(unsigned char), 4, file) != 4) return 0;
-   *ret = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
+   *ret = ARGB_JOIN(b[3], b[2], b[1], b[0]);
    return 1;
 }
 
@@ -48,13 +65,13 @@ static Eina_Bool
 evas_image_load_file_head_bmp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
 {
    FILE *f;
-   unsigned char buf[4096];
+   char buf[4096];
    char hasa = 0;
-   int w = 0, h = 0, planes = 0, bit_count = 0, 
-     image_size = 0, comp = 0, hdpi = 0, vdpi = 0, 
-     palette_size = -1, important_colors = 0, rowlen = 0;
+   int w = 0, h = 0, planes = 0, bit_count = 0,
+     image_size = 0, comp = 0, hdpi = 0, vdpi = 0,
+     palette_size = -1, important_colors = 0;
    unsigned int offset, head_size, rmask = 0, gmask = 0, bmask = 0, amask = 0;
-   unsigned int *pal = NULL, pal_num = 0;
+   unsigned int pal_num = 0;
    int right_way_up = 0;
    int fsize = 0;
    unsigned int bmpsize;
@@ -76,11 +93,11 @@ evas_image_load_file_head_bmp(Image_Entry *ie, const char *file, const char *key
    if (fread(buf, 2, 1, f) != 1) goto close_file;
    if (strncmp(buf, "BM", 2)) goto close_file; // magic number
    *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
-   if (!read_int(f, &bmpsize)) goto close_file;
-   if (!read_short(f, &res1)) goto close_file;
-   if (!read_short(f, &res2)) goto close_file;
-   if (!read_int(f, &offset)) goto close_file;
-   if (!read_int(f, &head_size)) goto close_file;
+   if (!read_uint(f, &bmpsize)) goto close_file;
+   if (!read_ushort(f, &res1)) goto close_file;
+   if (!read_ushort(f, &res2)) goto close_file;
+   if (!read_uint(f, &offset)) goto close_file;
+   if (!read_uint(f, &head_size)) goto close_file;
    if (head_size == 12) // OS/2 V1 + Windows 3.0
      {
         short tmp;
@@ -247,8 +264,6 @@ evas_image_load_file_head_bmp(Image_Entry *ie, const char *file, const char *key
    
    if (bit_count < 16)
      {
-        int i;
-        
         if ((palette_size < 0) || (palette_size > 256)) pal_num = 256;
         else pal_num = palette_size;
         if (bit_count == 1)
@@ -319,11 +334,12 @@ static Eina_Bool
 evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
 {
    FILE *f;
-   unsigned char buf[4096], *buffer = NULL, *buffer_end = NULL, *p;
+   char buf[4096];
+   unsigned char *buffer = NULL, *buffer_end = NULL, *p;
    char hasa = 0;
-   int x = 0, y = 0, w = 0, h = 0, planes = 0, bit_count = 0, image_size = 0, 
-     comp = 0, hdpi = 0, vdpi = 0, palette_size = -1, important_colors = 0
-     offset = 0, head_size = 0;
+   int x = 0, y = 0, w = 0, h = 0, planes = 0, bit_count = 0, image_size = 0,
+     comp = 0, hdpi = 0, vdpi = 0, palette_size = -1, important_colors = 0;
+   unsigned int offset = 0, head_size = 0;
    unsigned int *pal = NULL, pal_num = 0, *pix = NULL, *surface = NULL, fix,
      rmask = 0, gmask = 0, bmask = 0, amask = 0;
    int right_way_up = 0;
@@ -348,11 +364,11 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
    if (fread(buf, 2, 1, f) != 1) goto close_file;
    if (strncmp(buf, "BM", 2)) goto close_file; // magic number
    *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
-   if (!read_int(f, &bmpsize)) goto close_file;
-   if (!read_short(f, &res1)) goto close_file;
-   if (!read_short(f, &res2)) goto close_file;
-   if (!read_int(f, &offset)) goto close_file;
-   if (!read_int(f, &head_size)) goto close_file;
+   if (!read_uint(f, &bmpsize)) goto close_file;
+   if (!read_ushort(f, &res1)) goto close_file;
+   if (!read_ushort(f, &res2)) goto close_file;
+   if (!read_uint(f, &offset)) goto close_file;
+   if (!read_uint(f, &head_size)) goto close_file;
    image_size = fsize - offset;
    if (image_size < 1) goto close_file;
    
@@ -534,8 +550,8 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
    
    if (bit_count < 16)
      {
-        int i;
-        
+        unsigned int i;
+
         if (bit_count == 1)
           {
              if ((palette_size <= 0) || (palette_size > 2)) pal_num = 2;
@@ -562,7 +578,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                   if (fread(&a, 1, 1, f) != 1) goto close_file;
                }
              a = 0xff; // fillin a as solid for paletted images
-             pal[i] = (a << 24) | (r << 16) | (g << 8) | b;
+             pal[i] = ARGB_JOIN(a, r, g, b);
           }
         fseek(f, offset, SEEK_SET);
         buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
@@ -900,7 +916,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             r = (tmp >> 7) & 0xf8; r |= r >> 5;
                             g = (tmp >> 2) & 0xf8; g |= g >> 5;
                             b = (tmp << 3) & 0xf8; b |= b >> 5;
-                            *pix = 0xff000000 | (r << 16) | (g << 8) | (b);
+                            *pix = ARGB_JOIN(0xff, r, g, b);
                             p += 2;
                             if (p >= buffer_end) break;
                             pix++;
@@ -921,7 +937,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             b = p[0];
                             g = p[1];
                             r = p[2];
-                            *pix = 0xff000000 | (r << 16) | (g << 8) | (b);
+                            *pix = ARGB_JOIN(0xff, r, g, b);
                             p += 3;
                             if (p >= buffer_end) break;
                             pix++;
@@ -944,7 +960,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             r = p[2];
                             a = p[3];
                             if (!hasa) a = 0xff;
-                            *pix = (a << 24) | (r << 16) | (g << 8) | (b);
+                            *pix = ARGB_JOIN(a, r, g, b);
                             p += 4;
                             if (p >= buffer_end) break;
                             pix++;
@@ -959,9 +975,9 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
           }
         else if (comp == 3) // bit field
           {
-             if (!read_int(f, &rmask)) goto close_file;
-             if (!read_int(f, &gmask)) goto close_file;
-             if (!read_int(f, &bmask)) goto close_file;
+             if (!read_uint(f, &rmask)) goto close_file;
+             if (!read_uint(f, &gmask)) goto close_file;
+             if (!read_uint(f, &bmask)) goto close_file;
 
              fseek(f, offset, SEEK_SET);
              buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
@@ -990,7 +1006,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             r = (tmp >> 8) & 0xf8; r |= r >> 5;
                             g = (tmp >> 3) & 0xfc; g |= g >> 6;
                             b = (tmp << 3) & 0xf8; b |= b >> 5;
-                            *pix = 0xff000000 | (r << 16) | (g << 8) | (b);
+                            *pix = ARGB_JOIN(0xff, r, g, b);
                             p += 2;
                             if (p >= buffer_end) break;
                             pix++;
@@ -1017,7 +1033,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             r = (tmp >> 7) & 0xf8; r |= r >> 5;
                             g = (tmp >> 2) & 0xf8; g |= g >> 5;
                             b = (tmp << 3) & 0xf8; b |= b >> 5;
-                            *pix = 0xff000000 | (r << 16) | (g << 8) | (b);
+                            *pix = ARGB_JOIN(0xff, r, g, b);
                             p += 2;
                             if (p >= buffer_end) break;
                             pix++;
@@ -1040,7 +1056,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             r = p[2];
                             a = p[3];
                             if (!hasa) a = 0xff;
-                            *pix = (a << 24) | (r << 16) | (g << 8) | (b);
+                            *pix = ARGB_JOIN(a, r, g, b);
                             p += 4;
                             if (p >= buffer_end) break;
                             pix++;
@@ -1089,7 +1105,7 @@ module_open(Evas_Module *em)
 }
 
 static void
-module_close(Evas_Module *em)
+module_close(Evas_Module *em __UNUSED__)
 {
 }
 
index 1bf75b9..304181b 100644 (file)
@@ -272,14 +272,14 @@ evas_image_load_file_data_gif(Image_Entry *ie, const char *file, const char *key
                r = cmap->Colors[bg].Red;
                g = cmap->Colors[bg].Green;
                b = cmap->Colors[bg].Blue;
-               *ptr++ = 0x00ffffff & ((r << 16) | (g << 8) | b);
+               *ptr++ = 0x00ffffff & RGB_JOIN(r, g, b);
              }
            else
              {
                r = cmap->Colors[rows[i][j]].Red;
                g = cmap->Colors[rows[i][j]].Green;
                b = cmap->Colors[rows[i][j]].Blue;
-               *ptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
+               *ptr++ = ARGB_JOIN(0xff, r, g, b);
              }
            per += per_inc;
          }
index 59fb79c..65f7fc7 100644 (file)
@@ -228,7 +228,7 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f, int *error)
    struct _JPEG_error_mgr jerr;
    DATA8 *ptr, *line[16], *data;
    DATA32 *ptr2;
-   int x, y, l, i, scans, count;
+   int x, y, l, i, scans;
    int region = 0;
 
    cinfo.err = jpeg_std_error(&(jerr.pub));
@@ -331,7 +331,7 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f, int *error)
        return EINA_TRUE;
      }
    ptr2 = evas_cache_image_pixels(ie);
-   count = 0;
+
    /* We handle first CMYK (4 components) */
    if (cinfo.output_components == 4)
      {
@@ -493,8 +493,7 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f, int *error)
                     {
                        for (x = 0; x < w; x++)
                          {
-                            *ptr2 =
-                              (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
+                            *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[1], ptr[2]);
                             ptr += 3;
                             ptr2++;
                          }
@@ -525,8 +524,7 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f, int *error)
                                  ptr += (3 * ie->load_opts.region.x);
                                  for (x = 0; x < ie->load_opts.region.w; x++)
                                    {
-                                      *ptr2 =
-                                        (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
+                                      *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[1], ptr[2]);
                                       ptr += 3;
                                       ptr2++;
                                    }
@@ -560,8 +558,7 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f, int *error)
                     {
                        for (x = 0; x < w; x++)
                          {
-                            *ptr2 =
-                              (0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]);
+                            *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[0], ptr[0]);
                             ptr++;
                             ptr2++;
                          }
@@ -588,8 +585,7 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f, int *error)
                                  ptr += ie->load_opts.region.x;
                                  for (x = 0; x < ie->load_opts.region.w; x++)
                                    {
-                                      *ptr2 =
-                                        (0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]);
+                                      *ptr2 = ARGB_JOIN(0xff, ptr[0], ptr[0], ptr[0]);
                                       ptr++;
                                       ptr2++;
                                    }
@@ -618,7 +614,7 @@ evas_image_load_file_data_jpeg_alpha_internal(Image_Entry *ie, FILE *f, int *err
    struct _JPEG_error_mgr jerr;
    DATA8 *ptr, *line[16], *data;
    DATA32 *ptr2;
-   int x, y, l, i, scans, count, prevy;
+   int x, y, l, i, scans, prevy;
 
    if (!f)
      {
@@ -661,7 +657,6 @@ evas_image_load_file_data_jpeg_alpha_internal(Image_Entry *ie, FILE *f, int *err
        return EINA_TRUE;
      }
    ptr2 = evas_cache_image_pixels(ie);
-   count = 0;
    prevy = 0;
    if (cinfo.output_components == 3)
      {
index 4c7e709..7281391 100644 (file)
@@ -1,4 +1,3 @@
-
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
@@ -494,7 +493,7 @@ pmaps_buffer_rgb_get(Pmaps_Buffer *b, DATA32 *color)
    if (vb > 255)
       vb = 255;
 
-   *color = 0xff000000 | (vr << 16) | (vg << 8) | vb;
+   *color = ARGB_JOIN(0xff, vr, vg, vb);
 
    return 1;
 }
@@ -511,7 +510,7 @@ pmaps_buffer_gray_get(Pmaps_Buffer *b, DATA32 *color)
       val = (val * 255) / b->max;
    if (val > 255)
       val = 255;
-   *color = 0xff000000 | (val << 16) | (val << 8) | val;
+   *color = ARGB_JOIN(0xff, val, val, val);
 
    return 1;
 }
index 8ce68f7..a2350f9 100644 (file)
@@ -1,4 +1,3 @@
-
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
@@ -245,13 +244,9 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                   for (x = 0; (x < w) && ((bufptr + 4) <= bufend); x++)
                     {
                        if (hasa)
-                         *dataptr = 
-                         ((255 - bufptr[3]) << 24) | (bufptr[2] << 16) |
-                         (bufptr[1] <<  8) | (bufptr[0]      );
+                         *dataptr = ARGB_JOIN(255 - bufptr[3], bufptr[2], bufptr[1], bufptr[0]);
                        else
-                         *dataptr = 
-                         (0xff      << 24) | (bufptr[2] << 16) |
-                         (bufptr[1] <<  8) | (bufptr[0]      );
+                         *dataptr = ARGB_JOIN(0xff, bufptr[2], bufptr[1], bufptr[0]);
                        dataptr++;
                        bufptr += 4;
                     }
@@ -259,9 +254,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                case 24:
                   for (x = 0; (x < w) && ((bufptr + 3) <= bufend); x++)
                     {
-                       *dataptr = 
-                         (0xff      << 24) | (bufptr[2] << 16) |
-                         (bufptr[1] <<  8) | (bufptr[0]      );
+                       *dataptr = ARGB_JOIN(0xff, bufptr[2], bufptr[1], bufptr[0]);
                        dataptr++;
                        bufptr += 3;
                     }
@@ -280,9 +273,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                        b = (tmp << 3) & 0xf8; b |= b >> 5;
                        a = 0xff;
                        if ((hasa) && (tmp & 0x8000)) a = 0;
-                       *dataptr = 
-                         (a    << 24) | (r << 16) |
-                         (g    <<  8) | (b      );
+                       *dataptr = ARGB_JOIN(a, r, g, b);
                        dataptr++;
                        bufptr += 2;
                     }
@@ -290,9 +281,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                case 8:
                   for (x = 0; (x < w) && ((bufptr + 1) <= bufend); x++)
                     {
-                       *dataptr = 
-                         (0xff      << 24) | (bufptr[0] << 16) |
-                         (bufptr[0] <<  8) | (bufptr[0]      );
+                       *dataptr = ARGB_JOIN(0xff, bufptr[0], bufptr[0], bufptr[0]);
                        dataptr++;
                        bufptr += 1;
                     }
@@ -332,8 +321,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                             bufptr += 4;
                             for (i = 0; (i < count) && (dataptr < dataend); i++)
                               {
-                                 *dataptr = 
-                                   (a << 24) | (r << 16) | (g <<  8) | (b);
+                                 *dataptr = ARGB_JOIN(a, r, g, b);
                                  dataptr++;
                               }
                          }
@@ -349,8 +337,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                             bufptr += 3;
                             for (i = 0; (i < count) && (dataptr < dataend); i++)
                               {
-                                 *dataptr = 
-                                   (0xff << 24) | (r << 16) | (g <<  8) | (b);
+                                 *dataptr = ARGB_JOIN(0xff, r, g, b);
                                  dataptr++;
                               }
                          }
@@ -372,10 +359,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                             bufptr += 2;
                             for (i = 0; (i < count) && (dataptr < dataend); i++)
                               {
-                                 *dataptr = 
-                                   *dataptr = 
-                                   (a    << 24) | (r << 16) |
-                                   (g    <<  8) | (b      );
+                                 *dataptr = ARGB_JOIN(a, r, g, b);
                                  dataptr++;
                               }
                          }
@@ -389,8 +373,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                             bufptr += 1;
                             for (i = 0; (i < count) && (dataptr < dataend); i++)
                               {
-                                 *dataptr = 
-                                   (0xff << 24) | (g << 16) | (g <<  8) | (g);
+                                 *dataptr = ARGB_JOIN(0xff, g, g, g);
                                  dataptr++;
                               }
                          }
@@ -407,13 +390,9 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                        for (i = 0; (i < count) && (bufptr < (bufend - 4)) && (dataptr < dataend); i++)
                          {
                             if (hasa)
-                              *dataptr = 
-                              ((255 - bufptr[3]) << 24) | (bufptr[2] << 16) |
-                              (bufptr[1] <<  8) | (bufptr[0]      );
+                              *dataptr = ARGB_JOIN(255 - bufptr[3], bufptr[2], bufptr[1], bufptr[0]);
                             else
-                              *dataptr = 
-                              (0xff      << 24) | (bufptr[2] << 16) |
-                              (bufptr[1] <<  8) | (bufptr[0]      );
+                              *dataptr = ARGB_JOIN(0xff, bufptr[2], bufptr[1], bufptr[0]);
                             dataptr++;
                             bufptr += 4;
                          }
@@ -421,9 +400,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                     case 24:
                        for (i = 0; (i < count) && (bufptr < (bufend - 3)) && (dataptr < dataend); i++)
                          {
-                            *dataptr = 
-                              (0xff      << 24) | (bufptr[2] << 16) |
-                              (bufptr[1] <<  8) | (bufptr[0]      );
+                            *dataptr = ARGB_JOIN(0xff, bufptr[2], bufptr[1], bufptr[0]);
                             dataptr++;
                             bufptr += 3;
                          }
@@ -442,9 +419,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                             b = (tmp << 3) & 0xf8; b |= b >> 5;
                             a = 0xff;
                             if ((hasa) && (tmp & 0x8000)) a = 0;
-                            *dataptr = 
-                              (a    << 24) | (r << 16) |
-                              (g    <<  8) | (b      );
+                            *dataptr = ARGB_JOIN(a, r, g, b);
                             dataptr++;
                             bufptr += 2;
                          }
@@ -452,9 +427,7 @@ evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key
                     case 8:
                        for (i = 0; (i < count) && (bufptr < (bufend - 1)) && (dataptr < dataend); i++)
                          {
-                            *dataptr = 
-                              (0xff      << 24) | (bufptr[0] << 16) |
-                              (bufptr[0] <<  8) | (bufptr[0]      );
+                            *dataptr = ARGB_JOIN(0xff, bufptr[0], bufptr[0], bufptr[0]);
                             dataptr++;
                             bufptr += 1;
                          }
index 20ce7ee..f6a70cd 100644 (file)
@@ -1,4 +1,3 @@
-
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
@@ -125,7 +124,7 @@ raster(TIFFRGBAImage_Extra * img, uint32 * rast,
                  g = (g * (a + 1)) >> 8;
                  b = (b * (a + 1)) >> 8;
               }
-             (*(buffer_pixel++)) = (a << 24) | (r << 16) | (g << 8) | b;
+             (*(buffer_pixel++)) = ARGB_JOIN(a, r, g, b);
           }
      }
 }
index e7778de..6e93d00 100644 (file)
@@ -1,4 +1,3 @@
-
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
@@ -443,7 +442,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
                                           r = (unsigned char)cmap[lookup[lu1][0]].r;
                                            g = (unsigned char)cmap[lookup[lu1][0]].g;
                                            b = (unsigned char)cmap[lookup[lu1][0]].b;
-                                           *ptr = (r << 16) | (g << 8) | b;
+                                           *ptr = RGB_JOIN(r, g, b);
                                           ptr++;
                                            count++;
                                         }
@@ -452,7 +451,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
                                            r = (unsigned char)cmap[lookup[lu1][0]].r;
                                            g = (unsigned char)cmap[lookup[lu1][0]].g;
                                            b = (unsigned char)cmap[lookup[lu1][0]].b;
-                                           *ptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+                                           *ptr = ARGB_JOIN(0xff, r, g, b);
                                           ptr++;
                                            count++;
                                         }
@@ -469,7 +468,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
                                      r = (unsigned char)cmap[lookup[lu1][0]].r;
                                      g = (unsigned char)cmap[lookup[lu1][0]].g;
                                      b = (unsigned char)cmap[lookup[lu1][0]].b;
-                                     *ptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+                                     *ptr = ARGB_JOIN(0xff, r, g, b);
                                      ptr++;
                                      count++;
                                    }
@@ -493,7 +492,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
                                           r = (unsigned char)cmap[lookup[lu1][lu2]].r;
                                            g = (unsigned char)cmap[lookup[lu1][lu2]].g;
                                            b = (unsigned char)cmap[lookup[lu1][lu2]].b;
-                                           *ptr = (r << 16) | (g << 8) | b;
+                                           *ptr = RGB_JOIN(r, g, b);
                                           ptr++;
                                            count++;
                                         }
@@ -502,7 +501,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
                                            r = (unsigned char)cmap[lookup[lu1][lu2]].r;
                                            g = (unsigned char)cmap[lookup[lu1][lu2]].g;
                                            b = (unsigned char)cmap[lookup[lu1][lu2]].b;
-                                           *ptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+                                           *ptr = ARGB_JOIN(0xff, r, g, b);
                                           ptr++;
                                            count++;
                                         }
@@ -522,7 +521,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
                                      r = (unsigned char)cmap[lookup[lu1][lu2]].r;
                                      g = (unsigned char)cmap[lookup[lu1][lu2]].g;
                                      b = (unsigned char)cmap[lookup[lu1][lu2]].b;
-                                     *ptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+                                     *ptr = ARGB_JOIN(0xff, r, g, b);
                                      ptr++;
                                      count++;
                                    }
@@ -552,7 +551,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
                                                      r = (unsigned char)cmap[j].r;
                                                      g = (unsigned char)cmap[j].g;
                                                      b = (unsigned char)cmap[j].b;
-                                                    *ptr = (r << 16) | (g << 8) | b;
+                                                    *ptr = RGB_JOIN(r, g, b);
                                                     ptr++;
                                                      count++;
                                                   }
@@ -561,7 +560,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
                                                     r = (unsigned char)cmap[j].r;
                                                      g = (unsigned char)cmap[j].g;
                                                      b = (unsigned char)cmap[j].b;
-                                                    *ptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+                                                    *ptr = ARGB_JOIN(0xff, r, g, b);
                                                     ptr++;
                                                      count++;
                                                   }
@@ -589,7 +588,7 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
                                                 r = (unsigned char)cmap[j].r;
                                                 g = (unsigned char)cmap[j].g;
                                                 b = (unsigned char)cmap[j].b;
-                                               *ptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+                                               *ptr = ARGB_JOIN(0xff, r, g, b);
                                                ptr++;
                                                count++;
                                                 break;
@@ -631,9 +630,9 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
          break;
      }
 
-   if (cmap) free(cmap);
-   if (line) free(line);
-   if (f) fclose(f);
+   free(cmap);
+   free(line);
+   fclose(f);
 
    xpm_parse_done();
    *error = EVAS_LOAD_ERROR_NONE;
index d3b0f75..ddc2e27 100644 (file)
                                        >\r
                                </File>\r
                                <File\r
-                                       RelativePath="..\..\src\lib\engines\common\evas_image_fill_main.c"\r
-                                       >\r
-                                       <FileConfiguration\r
-                                               Name="Debug|Win32"\r
-                                               ExcludedFromBuild="true"\r
-                                               >\r
-                                               <Tool\r
-                                                       Name="VCCLCompilerTool"\r
-                                               />\r
-                                       </FileConfiguration>\r
-                                       <FileConfiguration\r
-                                               Name="Release|Win32"\r
-                                               ExcludedFromBuild="true"\r
-                                               >\r
-                                               <Tool\r
-                                                       Name="VCCLCompilerTool"\r
-                                               />\r
-                                       </FileConfiguration>\r
-                               </File>\r
-                               <File\r
                                        RelativePath="..\..\src\lib\engines\common\evas_image_load.c"\r
                                        >\r
                                </File>\r
index 1e307a7..08d6f0b 100644 (file)
                                        >\r
                                </File>\r
                                <File\r
-                                       RelativePath="..\..\src\lib\engines\common\evas_image_fill_main.c"\r
-                                       >\r
-                                       <FileConfiguration\r
-                                               Name="Debug|Win32"\r
-                                               ExcludedFromBuild="true"\r
-                                               >\r
-                                               <Tool\r
-                                                       Name="VCCLCompilerTool"\r
-                                               />\r
-                                       </FileConfiguration>\r
-                                       <FileConfiguration\r
-                                               Name="Release|Win32"\r
-                                               ExcludedFromBuild="true"\r
-                                               >\r
-                                               <Tool\r
-                                                       Name="VCCLCompilerTool"\r
-                                               />\r
-                                       </FileConfiguration>\r
-                               </File>\r
-                               <File\r
                                        RelativePath="..\..\src\lib\engines\common\evas_image_load.c"\r
                                        >\r
                                </File>\r