ector : integration of ector library in efl1.30.0 branch for tizen2.4 99/43299/1
authorSubhransu Sekhar Mohanty <sub.mohanty@samsung.com>
Wed, 11 Mar 2015 10:22:43 +0000 (19:22 +0900)
committerSubhransu Mohanty <sub.mohanty@samsung.com>
Wed, 8 Jul 2015 02:13:56 +0000 (11:13 +0900)
Change-Id: I1f5e8482e4d8003e21afe75f51a2839a736567c7

85 files changed:
configure.ac
pc/ector.pc [new file with mode: 0644]
src/Makefile_Ector.am
src/Makefile_Efl.am
src/Makefile_Evas.am
src/lib/ector/Ector.h
src/lib/ector/cairo/ector_cairo_private.h
src/lib/ector/cairo/ector_cairo_surface.c
src/lib/ector/cairo/ector_cairo_surface.eo
src/lib/ector/cairo/ector_renderer_cairo_base.c [new file with mode: 0644]
src/lib/ector/cairo/ector_renderer_cairo_base.eo
src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.c
src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.eo
src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.c
src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.eo
src/lib/ector/cairo/ector_renderer_cairo_shape.c
src/lib/ector/cairo/ector_renderer_cairo_shape.eo
src/lib/ector/ector_generic_surface.eo
src/lib/ector/ector_main.c
src/lib/ector/ector_private.h
src/lib/ector/ector_renderer_base.c
src/lib/ector/ector_renderer_generic_base.eo
src/lib/ector/ector_renderer_generic_gradient.eo
src/lib/ector/ector_renderer_generic_gradient_linear.eo
src/lib/ector/ector_renderer_generic_gradient_radial.eo
src/lib/ector/ector_renderer_generic_shape.eo
src/lib/ector/ector_renderer_gradient.c
src/lib/ector/ector_renderer_shape.c
src/lib/ector/ector_surface.c
src/lib/ector/ector_util.h [new file with mode: 0644]
src/lib/ector/software/ector_blend_private.h [deleted file]
src/lib/ector/software/ector_drawhelper.c [new file with mode: 0644]
src/lib/ector/software/ector_drawhelper_private.h [new file with mode: 0644]
src/lib/ector/software/ector_drawhelper_sse2.c [new file with mode: 0644]
src/lib/ector/software/ector_renderer_software_base.eo
src/lib/ector/software/ector_renderer_software_gradient_linear.c
src/lib/ector/software/ector_renderer_software_gradient_linear.eo
src/lib/ector/software/ector_renderer_software_gradient_radial.c
src/lib/ector/software/ector_renderer_software_gradient_radial.eo
src/lib/ector/software/ector_renderer_software_shape.c
src/lib/ector/software/ector_renderer_software_shape.eo
src/lib/ector/software/ector_software_gradient.c
src/lib/ector/software/ector_software_private.h
src/lib/ector/software/ector_software_rasterizer.c
src/lib/ector/software/ector_software_surface.c
src/lib/ector/software/ector_software_surface.eo
src/lib/efl/Efl.h
src/lib/efl/interfaces/efl_gfx_base.eo
src/lib/efl/interfaces/efl_gfx_fill.eo [new file with mode: 0644]
src/lib/efl/interfaces/efl_gfx_gradient_base.eo [new file with mode: 0644]
src/lib/efl/interfaces/efl_gfx_gradient_linear.eo
src/lib/efl/interfaces/efl_gfx_gradient_radial.eo
src/lib/efl/interfaces/efl_gfx_shape.c [new file with mode: 0644]
src/lib/efl/interfaces/efl_gfx_shape.eo
src/lib/efl/interfaces/efl_gfx_stack.eo [new file with mode: 0644]
src/lib/efl/interfaces/efl_gfx_view.eo [new file with mode: 0644]
src/lib/efl/interfaces/efl_interfaces_main.c
src/lib/evas/Evas_Common.h
src/lib/evas/Evas_Eo.h
src/lib/evas/Evas_Legacy.h
src/lib/evas/canvas/efl_vg_base.eo [new file with mode: 0644]
src/lib/evas/canvas/efl_vg_container.eo [new file with mode: 0644]
src/lib/evas/canvas/efl_vg_gradient.eo [new file with mode: 0644]
src/lib/evas/canvas/efl_vg_gradient_linear.eo [new file with mode: 0644]
src/lib/evas/canvas/efl_vg_gradient_radial.eo [new file with mode: 0644]
src/lib/evas/canvas/efl_vg_image.eo [new file with mode: 0644]
src/lib/evas/canvas/efl_vg_root_node.eo [new file with mode: 0644]
src/lib/evas/canvas/efl_vg_shape.eo [new file with mode: 0644]
src/lib/evas/canvas/evas_object_vg.c
src/lib/evas/canvas/evas_vg.eo
src/lib/evas/canvas/evas_vg_container.c
src/lib/evas/canvas/evas_vg_gradient.c
src/lib/evas/canvas/evas_vg_gradient_linear.c
src/lib/evas/canvas/evas_vg_gradient_radial.c
src/lib/evas/canvas/evas_vg_image.c
src/lib/evas/canvas/evas_vg_loader_svg.c
src/lib/evas/canvas/evas_vg_node.c
src/lib/evas/canvas/evas_vg_private.h
src/lib/evas/canvas/evas_vg_root_node.c
src/lib/evas/canvas/evas_vg_shape.c
src/lib/evas/include/evas_private.h
src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo [new file with mode: 0644]
src/modules/evas/engines/gl_generic/evas_engine.c
src/modules/evas/engines/software_generic/ector_cairo_software_surface.eo
src/modules/evas/engines/software_generic/evas_engine.c

index a62495c..b20af4f 100644 (file)
@@ -4617,6 +4617,8 @@ AM_CONDITIONAL([BUILD_ECORE_BUFFER_TBM], [test "${build_ecore_buffer_tbm}" = "ye
 
 #### End of Ecore_Buffer
 
+
+#### src/examples/ephysics/Makefile
 AC_CONFIG_FILES([
 Makefile
 data/Makefile
diff --git a/pc/ector.pc b/pc/ector.pc
new file mode 100644 (file)
index 0000000..3df0995
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=/usr/local
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: ector
+Description: Enlightenned retained mode drawing library
+Requires.private: efl >= 1.13.0 eo >= 1.13.0 eina >= 1.13.0
+Version: 1.13.0
+Libs: -L${libdir} -lector
+Libs.private:  -lm
+Cflags: -I${includedir}/efl-1 -I${includedir}/ector-1
index 9ed32d5..d6ff0ad 100644 (file)
@@ -21,8 +21,8 @@ ector_eolian_files += \
        lib/ector/software/ector_software_surface.eo \
        lib/ector/software/ector_renderer_software_base.eo \
        lib/ector/software/ector_renderer_software_shape.eo \
-       lib/ector/software/ector_renderer_software_gradient_linear.eo \
-       lib/ector/software/ector_renderer_software_gradient_radial.eo   
+       lib/ector/software/ector_renderer_software_gradient_radial.eo \
+       lib/ector/software/ector_renderer_software_gradient_linear.eo
 
 ector_eolian_c = $(ector_eolian_files:%.eo=%.eo.c)
 ector_eolian_h = $(ector_eolian_files:%.eo=%.eo.h)
@@ -40,10 +40,11 @@ lib_LTLIBRARIES += lib/ector/libector.la
 installed_ectormainheadersdir = $(includedir)/ector-@VMAJ@
 dist_installed_ectormainheaders_DATA = \
 lib/ector/Ector.h \
+lib/ector/ector_util.h \
 lib/ector/cairo/Ector_Cairo.h \
 lib/ector/software/Ector_Software.h
 
-# And the cairo header
+# And the generic implementation
 
 lib_ector_libector_la_SOURCES = \
 lib/ector/ector_main.c \
@@ -59,6 +60,7 @@ lib_ector_libector_la_SOURCES += \
 lib/ector/cairo/ector_renderer_cairo_gradient_linear.c \
 lib/ector/cairo/ector_renderer_cairo_gradient_radial.c \
 lib/ector/cairo/ector_renderer_cairo_shape.c \
+lib/ector/cairo/ector_renderer_cairo_base.c \
 lib/ector/cairo/ector_cairo_surface.c
 
 # And now the software backend
@@ -66,19 +68,22 @@ lib_ector_libector_la_SOURCES += \
 lib/ector/software/ector_renderer_software_gradient_linear.c \
 lib/ector/software/ector_renderer_software_gradient_radial.c \
 lib/ector/software/ector_renderer_software_shape.c \
-lib/ector/software/ector_software_surface.c \
 lib/ector/software/ector_software_gradient.c \
+lib/ector/software/ector_software_rasterizer.c \
+lib/ector/software/ector_software_surface.c \
 lib/ector/software/sw_ft_math.c \
 lib/ector/software/sw_ft_raster.c \
 lib/ector/software/sw_ft_stroker.c \
-lib/ector/software/ector_software_rasterizer.c
+lib/ector/software/ector_drawhelper.c \
+lib/ector/software/ector_drawhelper_sse2.c
 
 lib_ector_libector_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 @ECTOR_CFLAGS@ \
 -DPACKAGE_BIN_DIR=\"$(bindir)\" \
 -DPACKAGE_LIB_DIR=\"$(libdir)\" \
 -DPACKAGE_DATA_DIR=\"$(datadir)/ector\" \
-@VALGRIND_CFLAGS@
+@VALGRIND_CFLAGS@ \
+@SSE3_CFLAGS@
 
 lib_ector_libector_la_LIBADD = @ECTOR_LIBS@ @DL_LIBS@
 lib_ector_libector_la_DEPENDENCIES = @ECTOR_INTERNAL_LIBS@ @DL_INTERNAL_LIBS@
@@ -116,9 +121,10 @@ endif
 
 EXTRA_DIST += \
 src/lib/ector/ector_private.h \
-src/lib/ector/cairo/ector_cairo_private,h \
-src/lib/ector/software/sw_ft_types.h \
+src/lib/ector/cairo/ector_cairo_private.h \
+src/lib/ector/software/ector_drawhelper_private.h \
+src/lib/ector/software/ector_software_private.h \
 src/lib/ector/software/sw_ft_math.h \
 src/lib/ector/software/sw_ft_raster.h \
 src/lib/ector/software/sw_ft_stroker.h \
-src/lib/ector/software/ector_software_private.h
\ No newline at end of file
+src/lib/ector/software/sw_ft_types.h
index 2525020..b65dafc 100644 (file)
@@ -6,8 +6,11 @@ efl_eolian_files = \
       lib/efl/interfaces/efl_text.eo \
       lib/efl/interfaces/efl_text_properties.eo \
       lib/efl/interfaces/efl_gfx_base.eo \
+      lib/efl/interfaces/efl_gfx_stack.eo \
+      lib/efl/interfaces/efl_gfx_fill.eo \
+      lib/efl/interfaces/efl_gfx_view.eo \
       lib/efl/interfaces/efl_gfx_shape.eo \
-      lib/efl/interfaces/efl_gfx_gradient.eo \
+      lib/efl/interfaces/efl_gfx_gradient_base.eo \
       lib/efl/interfaces/efl_gfx_gradient_linear.eo \
       lib/efl/interfaces/efl_gfx_gradient_radial.eo
 
@@ -25,7 +28,6 @@ CLEANFILES += \
 EXTRA_DIST += \
       lib/efl/Efl_Config.h \
       lib/efl/Efl.h \
-      lib/efl/interfaces/efl_gfx_utils.h \
       $(efl_eolian_files)
 
 efleolianfilesdir = $(datadir)/eolian/include/efl-@VMAJ@
@@ -35,7 +37,7 @@ lib_LTLIBRARIES += lib/efl/libefl.la
 
 lib_efl_libefl_la_SOURCES = \
 lib/efl/interfaces/efl_interfaces_main.c \
-lib/efl/interfaces/efl_gfx_utils.c
+lib/efl/interfaces/efl_gfx_shape.c
 
 lib_efl_libefl_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl -I$(top_srcdir)/src/lib/efl @EFL_CFLAGS@
 lib_efl_libefl_la_LIBADD = @EFL_LIBS@
@@ -49,8 +51,7 @@ dist_installed_eflheaders_DATA = \
 
 installed_eflinterfacesdir = $(includedir)/efl-@VMAJ@/interfaces
 nodist_installed_eflinterfaces_DATA = \
-$(efl_eolian_files_h) \
-lib/efl/interfaces/efl_gfx_utils.h
+$(efl_eolian_files_h)
 
 if HAVE_ELUA
 
index abf22bd..d3ad0f7 100644 (file)
@@ -33,14 +33,14 @@ evas_eolian_files = \
        lib/evas/canvas/evas_3d_scene.eo\
        lib/evas/canvas/evas_3d_object.eo \
        lib/evas/canvas/evas_vg.eo \
-       lib/evas/canvas/evas_vg_node.eo \
-       lib/evas/canvas/evas_vg_container.eo \
-       lib/evas/canvas/evas_vg_shape.eo \
-       lib/evas/canvas/evas_vg_root_node.eo \
-       lib/evas/canvas/evas_vg_gradient.eo \
-       lib/evas/canvas/evas_vg_gradient_radial.eo \
-       lib/evas/canvas/evas_vg_gradient_linear.eo \
-       lib/evas/canvas/evas_vg_image.eo
+       lib/evas/canvas/efl_vg_base.eo \
+       lib/evas/canvas/efl_vg_container.eo \
+       lib/evas/canvas/efl_vg_shape.eo \
+       lib/evas/canvas/efl_vg_root_node.eo \
+       lib/evas/canvas/efl_vg_gradient.eo \
+       lib/evas/canvas/efl_vg_gradient_radial.eo \
+       lib/evas/canvas/efl_vg_gradient_linear.eo \
+       lib/evas/canvas/efl_vg_image.eo
 
 evas_eolian_c = $(evas_eolian_files:%.eo=%.eo.c)
 evas_eolian_h = $(evas_eolian_files:%.eo=%.eo.h) \
@@ -514,11 +514,18 @@ lib/evas/filters/blur/blur_box_rgba_i386.c \
 lib/evas/filters/blur/blur_box_rgba_sse3.c \
 lib/evas/filters/blur/blur_box_rgba_neon.c
 
+### Vector surface helper
+
+EXTRA_DIST += \
+modules/evas/engines/software_generic/ector_cairo_software_surface.eo \
+modules/evas/engines/gl_generic/ector_cairo_software_surface.eo
 
 ### Engines
 
 if EVAS_STATIC_BUILD_SOFTWARE_GENERIC
-evas_eolian_files += modules/evas/engines/software_generic/ector_cairo_software_surface.eo
+BUILT_SOURCES += \
+modules/evas/engines/software_generic/ector_cairo_software_surface.eo.c \
+modules/evas/engines/software_generic/ector_cairo_software_surface.eo.h
 lib_evas_libevas_la_SOURCES += modules/evas/engines/software_generic/evas_engine.c modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h
 lib_evas_libevas_la_LIBADD +=
 else
@@ -589,6 +596,10 @@ endif
 endif
 
 if BUILD_ENGINE_GL_COMMON
+BUILT_SOURCES += \
+modules/evas/engines/gl_generic/ector_cairo_software_surface.eo.c \
+modules/evas/engines/gl_generic/ector_cairo_software_surface.eo.h
+
 GL_COMMON_SOURCES = \
 modules/evas/engines/gl_common/evas_gl_private.h \
 modules/evas/engines/gl_common/evas_gl_common.h \
index fe8d13c..0a53fac 100644 (file)
@@ -174,6 +174,7 @@ EAPI int ector_shutdown(void);
 
 #include "ector_surface.h"
 #include "ector_renderer.h"
+#include "ector_util.h"
 
 #endif
 
index eef2d10..07446a8 100644 (file)
@@ -7,12 +7,17 @@ typedef struct _Ector_Cairo_Surface_Data Ector_Cairo_Surface_Data;
 struct _Ector_Cairo_Surface_Data
 {
    cairo_t *cairo;
+   struct {
+      double x, y;
+   } current;
+
+   Eina_Bool internal : 1;
 };
 
 #define CHECK_CAIRO(Parent) (!(Parent && Parent->cairo))
 
-#define USE(Obj, Sym, Error)                     \
-  if (!Sym) _ector_cairo_symbol_get(Obj, #Sym);  \
+#define USE(Obj, Sym, Error)                            \
+  if (!Sym) Sym = _ector_cairo_symbol_get(Obj, #Sym);   \
   if (!Sym) return Error;
 
 static inline void *
index c2d42a9..8875c04 100644 (file)
@@ -42,29 +42,67 @@ _ector_cairo_surface_symbol_get(Eo *obj EINA_UNUSED,
 #undef LOAD
      }
 
+   if (!_cairo_so)
+     {
+        ERR("Couldn't find cairo library. Please make sure that your system can locate it.");
+        return NULL;
+     }
+
    return eina_module_symbol_get(_cairo_so, name);
 }
 
+#undef USE
+#define USE(Obj, Sym, Error)                                            \
+  if (!Sym) Sym = _ector_cairo_surface_symbol_get(Obj, NULL, #Sym);     \
+  if (!Sym) return Error;
 
 static Ector_Renderer *
 _ector_cairo_surface_ector_generic_surface_renderer_factory_new(Eo *obj,
                                                                 Ector_Cairo_Surface_Data *pd EINA_UNUSED,
                                                                 const Eo_Class *type)
 {
-   if (eo_isa(type, ECTOR_RENDERER_CAIRO_SHAPE_CLASS))
+   if (type == ECTOR_RENDERER_GENERIC_SHAPE_MIXIN)
      return eo_add(ECTOR_RENDERER_CAIRO_SHAPE_CLASS, obj);
-   else if (eo_isa(type, ECTOR_RENDERER_CAIRO_GRADIENT_LINEAR_CLASS))
+   else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN)
      return eo_add(ECTOR_RENDERER_CAIRO_GRADIENT_LINEAR_CLASS, obj);
-   else if (eo_isa(type, ECTOR_RENDERER_CAIRO_GRADIENT_RADIAL_CLASS))
+   else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN)
      return eo_add(ECTOR_RENDERER_CAIRO_GRADIENT_RADIAL_CLASS, obj);
+   ERR("Couldn't find class for type: %s\n", eo_class_name_get(type));
    return NULL;
 }
 
+typedef struct _cairo_surface_t cairo_surface_t;
+
+static void (*cairo_translate)(cairo_t *cr, double tx, double ty) = NULL;
+static void (*cairo_destroy)(cairo_t *cr) = NULL;
+static cairo_surface_t *(*cairo_image_surface_create)(int format,
+                                                      int width,
+                                                      int height) = NULL;
+static cairo_t *(*cairo_create)(cairo_surface_t *target) = NULL;
+
+static cairo_surface_t *internal = NULL;
+
 static void
-_ector_cairo_surface_context_set(Eo *obj EINA_UNUSED,
+_ector_cairo_surface_context_set(Eo *obj,
                                  Ector_Cairo_Surface_Data *pd,
                                  cairo_t *ctx)
 {
+   if (pd->internal)
+     {
+        USE(obj, cairo_destroy, );
+
+        if (pd->cairo) cairo_destroy(pd->cairo);
+        pd->internal = EINA_FALSE;
+     }
+   if (!ctx)
+     {
+        USE(obj, cairo_image_surface_create, );
+        USE(obj, cairo_create, );
+
+        if (!internal) internal = cairo_image_surface_create(0, 1, 1);
+        ctx = cairo_create(internal);
+     }
+   pd->current.x = pd->current.y = 0;
    pd->cairo = ctx;
 }
 
@@ -76,21 +114,36 @@ _ector_cairo_surface_context_get(Eo *obj EINA_UNUSED,
 }
 
 static void
-_ector_cairo_surface_eo_base_constructor(Eo *obj EINA_UNUSED,
-                                         Ector_Cairo_Surface_Data *pd EINA_UNUSED)
+_ector_cairo_surface_ector_generic_surface_reference_point_set(Eo *obj EINA_UNUSED,
+                                                               Ector_Cairo_Surface_Data *pd,
+                                                               int x, int y)
 {
+   if (pd->cairo)
+     {
+        USE(obj, cairo_translate, );
+        cairo_translate(pd->cairo, x, y);
+     }
+}
+
+static void
+_ector_cairo_surface_eo_base_constructor(Eo *obj,
+                                         Ector_Cairo_Surface_Data *pd)
+{
+   eo_do_super(obj, ECTOR_CAIRO_SURFACE_CLASS, eo_constructor());
    _cairo_count++;
+
+   _ector_cairo_surface_context_set(obj, pd, NULL);
 }
 
 static void
 _ector_cairo_surface_eo_base_destructor(Eo *obj EINA_UNUSED,
                                         Ector_Cairo_Surface_Data *pd EINA_UNUSED)
 {
+   eo_do_super(obj, ECTOR_CAIRO_SURFACE_CLASS, eo_destructor());
+
    if (--_cairo_count) return ;
    if (_cairo_so) eina_module_free(_cairo_so);
    _cairo_so = NULL;
 }
 
-
 #include "ector_cairo_surface.eo.c"
-#include "ector_renderer_cairo_base.eo.c"
index 10f6d9f..298c681 100644 (file)
@@ -23,6 +23,7 @@ class Ector.Cairo.Surface (Ector.Generic.Surface)
    }
    implements {
       Ector.Generic.Surface.renderer_factory_new;
+      Ector.Generic.Surface.reference_point.set;
       Eo.Base.destructor;
       Eo.Base.constructor;
    }
diff --git a/src/lib/ector/cairo/ector_renderer_cairo_base.c b/src/lib/ector/cairo/ector_renderer_cairo_base.c
new file mode 100644 (file)
index 0000000..190fb8a
--- /dev/null
@@ -0,0 +1,208 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>
+#include <float.h>
+
+#include <Eina.h>
+#include <Ector.h>
+#include <cairo/Ector_Cairo.h>
+
+#include "ector_private.h"
+#include "ector_cairo_private.h"
+
+typedef struct {
+   double xx; double yx;
+   double xy; double yy;
+   double x0; double y0;
+} cairo_matrix_t;
+
+typedef enum {
+  CAIRO_OPERATOR_CLEAR,
+
+  CAIRO_OPERATOR_SOURCE,
+  CAIRO_OPERATOR_OVER,
+  CAIRO_OPERATOR_IN,
+  CAIRO_OPERATOR_OUT,
+  CAIRO_OPERATOR_ATOP,
+
+  CAIRO_OPERATOR_DEST,
+  CAIRO_OPERATOR_DEST_OVER,
+  CAIRO_OPERATOR_DEST_IN,
+  CAIRO_OPERATOR_DEST_OUT,
+  CAIRO_OPERATOR_DEST_ATOP,
+
+  CAIRO_OPERATOR_XOR,
+  CAIRO_OPERATOR_ADD,
+  CAIRO_OPERATOR_SATURATE,
+
+  CAIRO_OPERATOR_MULTIPLY,
+  CAIRO_OPERATOR_SCREEN,
+  CAIRO_OPERATOR_OVERLAY,
+  CAIRO_OPERATOR_DARKEN,
+  CAIRO_OPERATOR_LIGHTEN,
+  CAIRO_OPERATOR_COLOR_DODGE,
+  CAIRO_OPERATOR_COLOR_BURN,
+  CAIRO_OPERATOR_HARD_LIGHT,
+  CAIRO_OPERATOR_SOFT_LIGHT,
+  CAIRO_OPERATOR_DIFFERENCE,
+  CAIRO_OPERATOR_EXCLUSION,
+  CAIRO_OPERATOR_HSL_HUE,
+  CAIRO_OPERATOR_HSL_SATURATION,
+  CAIRO_OPERATOR_HSL_COLOR,
+  CAIRO_OPERATOR_HSL_LUMINOSITY
+} cairo_operator_t;
+
+static void (*cairo_translate)(cairo_t *cr, double tx, double ty) = NULL;
+static void (*cairo_matrix_init)(cairo_matrix_t *matrix,
+                                 double xx, double yx,
+                                 double xy, double yy,
+                                 double x0, double y0) = NULL;
+static void (*cairo_transform)(cairo_t *cr, const cairo_matrix_t *matrix) = NULL;
+static void (*cairo_set_source_rgba)(cairo_t *cr,
+                                     double red, double green, double blue,
+                                     double alpha) = NULL;
+static void (*cairo_set_operator)(cairo_t *cr, cairo_operator_t op) = NULL;
+static void (*cairo_matrix_init_identity)(cairo_matrix_t *matrix) = NULL;
+
+typedef struct _Ector_Renderer_Cairo_Base_Data Ector_Renderer_Cairo_Base_Data;
+struct _Ector_Renderer_Cairo_Base_Data
+{
+   Ector_Cairo_Surface_Data *parent;
+   Ector_Renderer_Generic_Base_Data *generic;
+
+   cairo_matrix_t *m;
+};
+
+static cairo_matrix_t identity;
+
+// Cairo need unpremul color, so force unpremul here
+void
+_ector_renderer_cairo_base_ector_renderer_generic_base_color_set(Eo *obj EINA_UNUSED,
+                                                                 Ector_Renderer_Cairo_Base_Data *pd,
+                                                                 int r, int g, int b, int a)
+{
+   ector_color_argb_unpremul(a, &r ,&g, &b);
+   pd->generic->color.r = r;
+   pd->generic->color.g = g;
+   pd->generic->color.b = b;
+   pd->generic->color.a = a;
+}
+
+void
+_ector_renderer_cairo_base_ector_renderer_generic_base_color_get(Eo *obj EINA_UNUSED,
+                                                                 Ector_Renderer_Cairo_Base_Data *pd,
+                                                                 int *r, int *g, int *b, int *a)
+{
+   if (r) *r = pd->generic->color.r;
+   if (g) *g = pd->generic->color.g;
+   if (b) *b = pd->generic->color.b;
+   if (a) *a = pd->generic->color.a;
+
+   ector_color_argb_premul(pd->generic->color.a, r, g, b);
+}
+
+static Eina_Bool
+_ector_renderer_cairo_base_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Cairo_Base_Data *pd)
+{
+   if (!pd->parent)
+     {
+        Eo *parent;
+
+        eo_do(obj, parent = eo_parent_get());
+        if (!parent) return EINA_FALSE;
+        pd->parent = eo_data_xref(parent, ECTOR_CAIRO_SURFACE_CLASS, obj);
+     }
+   if (pd->generic->m)
+     {
+        USE(obj, cairo_matrix_init, EINA_FALSE);
+
+        if (!pd->m) pd->m = malloc(sizeof (cairo_matrix_t));
+        cairo_matrix_init(pd->m,
+                          pd->generic->m->xx, pd->generic->m->yx,
+                          pd->generic->m->xy, pd->generic->m->yy,
+                          pd->generic->m->xz, pd->generic->m->yz);
+     }
+   else
+     {
+        free(pd->m);
+        pd->m = NULL;
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_ector_renderer_cairo_base_ector_renderer_generic_base_draw(Eo *obj,
+                                                            Ector_Renderer_Cairo_Base_Data *pd,
+                                                            Ector_Rop op,
+                                                            Eina_Array *clips EINA_UNUSED,
+                                                            unsigned int mul_col)
+{
+   double r, g, b, a;
+   cairo_operator_t cop;
+   double cx, cy;
+
+   USE(obj, cairo_translate, EINA_FALSE);
+   USE(obj, cairo_set_source_rgba, EINA_FALSE);
+   USE(obj, cairo_transform, EINA_FALSE);
+   USE(obj, cairo_set_operator, EINA_FALSE);
+
+   switch (op)
+     {
+      case ECTOR_ROP_BLEND:
+         cop = CAIRO_OPERATOR_OVER;
+         break;
+      case ECTOR_ROP_COPY:
+      default:
+         cop = CAIRO_OPERATOR_SOURCE;
+         break;
+     }
+
+   r = ((double)((pd->generic->color.r * R_VAL(&mul_col)) >> 8)) / 255;
+   g = ((double)((pd->generic->color.g * G_VAL(&mul_col)) >> 8)) / 255;
+   b = ((double)((pd->generic->color.b * B_VAL(&mul_col)) >> 8)) / 255;
+   a = ((double)((pd->generic->color.a * A_VAL(&mul_col)) >> 8)) / 255;
+
+   cairo_set_operator(pd->parent->cairo, cop);
+   cairo_transform(pd->parent->cairo, &identity);
+   if (pd->m) cairo_transform(pd->parent->cairo, pd->m);
+   cx = pd->generic->origin.x - pd->parent->current.x;
+   cy = pd->generic->origin.y - pd->parent->current.y;
+   cairo_translate(pd->parent->cairo, cx, cy);
+   pd->parent->current.x = pd->generic->origin.x;
+   pd->parent->current.y = pd->generic->origin.y;
+
+   cairo_set_source_rgba(pd->parent->cairo, r, g, b, a);
+
+   return EINA_TRUE;
+}
+
+static void
+_ector_renderer_cairo_base_eo_base_constructor(Eo *obj, Ector_Renderer_Cairo_Base_Data *pd EINA_UNUSED)
+{
+   eo_do_super(obj, ECTOR_RENDERER_CAIRO_BASE_CLASS, eo_constructor());
+
+   pd->generic = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj);
+
+   USE(obj, cairo_matrix_init_identity, );
+
+   cairo_matrix_init_identity(&identity);
+}
+
+static void
+_ector_renderer_cairo_base_eo_base_destructor(Eo *obj, Ector_Renderer_Cairo_Base_Data *pd)
+{
+   Eo *parent;
+
+   free(pd->m);
+
+   eo_do(obj, parent = eo_parent_get());
+   eo_data_xunref(parent, pd->parent, obj);
+   eo_data_xunref(obj, pd->generic, obj);
+
+   eo_do_super(obj, ECTOR_RENDERER_CAIRO_BASE_CLASS, eo_destructor());
+}
+
+#include "ector_renderer_cairo_base.eo.c"
index 7075710..c34b9a8 100644 (file)
@@ -1,4 +1,4 @@
-interface Ector.Renderer.Cairo.Base
+abstract Ector.Renderer.Cairo.Base (Ector.Renderer.Generic.Base)
 {
    legacy_prefix: null;
    methods {
@@ -6,4 +6,13 @@ interface Ector.Renderer.Cairo.Base
          return: bool;
       }
    }
+   implements {
+      @virtual .fill;
+      Ector.Renderer.Generic.Base.prepare;
+      Ector.Renderer.Generic.Base.draw;
+      Ector.Renderer.Generic.Base.color.set;
+      Ector.Renderer.Generic.Base.color.get;
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+   }
 }
index d0a39f8..19f3055 100644 (file)
@@ -35,10 +35,12 @@ _ector_renderer_cairo_gradient_linear_ector_renderer_generic_base_prepare(Eo *ob
    Ector_Renderer_Generic_Gradient_Data *gd;
    unsigned int i;
 
+   eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_LINEAR_CLASS, ector_renderer_prepare());
+
    if (pd->pat) return EINA_FALSE;
 
-   gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS);
-   gd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_CLASS);
+   gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN);
+   gd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN);
    if (!gld || !gd) return EINA_FALSE;
 
    USE(obj, cairo_pattern_create_linear, EINA_FALSE);
@@ -66,17 +68,20 @@ _ector_renderer_cairo_gradient_linear_ector_renderer_generic_base_prepare(Eo *ob
 static Eina_Bool
 _ector_renderer_cairo_gradient_linear_ector_renderer_generic_base_draw(Eo *obj,
                                                                        Ector_Renderer_Cairo_Gradient_Linear_Data *pd,
-                                                                       Ector_Rop op, Eina_Array *clips, int x, int y, unsigned int mul_col)
+                                                                       Ector_Rop op, Eina_Array *clips, unsigned int mul_col)
 {
    Ector_Renderer_Generic_Gradient_Linear_Data *gld;
 
    // FIXME: don't ignore clipping !
-   gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS);
-   if (!pd->pat || !gld || CHECK_CAIRO(pd->parent)) return EINA_FALSE;
+   gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN);
+   if (!pd->pat || !gld) return EINA_FALSE;
+
+   eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_LINEAR_CLASS, ector_renderer_draw(op, clips, mul_col));
 
    USE(obj, cairo_rectangle, EINA_FALSE);
+   USE(obj, cairo_fill, EINA_FALSE);
 
-   cairo_rectangle(pd->parent->cairo, gld->start.x - x, gld->start.y - y,
+   cairo_rectangle(pd->parent->cairo, gld->start.x, gld->start.y,
                    gld->end.x - gld->start.x,
                    gld->end.y - gld->start.y);
    eo_do(obj, ector_renderer_cairo_base_fill());
@@ -89,7 +94,7 @@ static Eina_Bool
 _ector_renderer_cairo_gradient_linear_ector_renderer_cairo_base_fill(Eo *obj,
                                                                      Ector_Renderer_Cairo_Gradient_Linear_Data *pd)
 {
-   if (!pd->pat || CHECK_CAIRO(pd->parent)) return EINA_FALSE;
+   if (!pd->pat) return EINA_FALSE;
 
    USE(obj, cairo_set_source, EINA_FALSE);
 
@@ -116,7 +121,7 @@ _ector_renderer_cairo_gradient_linear_eo_base_destructor(Eo *obj,
 }
 
 void
-_ector_renderer_cairo_gradient_linear_efl_gfx_gradient_stop_set(Eo *obj, Ector_Renderer_Cairo_Gradient_Linear_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
+_ector_renderer_cairo_gradient_linear_efl_gfx_gradient_base_stop_set(Eo *obj, Ector_Renderer_Cairo_Gradient_Linear_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
 {
    USE(obj, cairo_pattern_destroy, );
 
index 6007fd3..3d4ed9a 100644 (file)
@@ -1,4 +1,4 @@
-class Ector.Renderer.Cairo.Gradient_Linear (Ector.Renderer.Cairo.Base, Ector.Renderer.Generic.Gradient_Linear)
+class Ector.Renderer.Cairo.Gradient_Linear (Ector.Renderer.Cairo.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Linear)
 {
    eo_prefix: ector_renderer_cairo_gradient_linear;
    legacy_prefix: null;
@@ -7,6 +7,6 @@ class Ector.Renderer.Cairo.Gradient_Linear (Ector.Renderer.Cairo.Base, Ector.Ren
       Ector.Renderer.Generic.Base.draw;
       Ector.Renderer.Cairo.Base.fill;
       Eo.Base.destructor;
-      Efl.Gfx.Gradient.stop.set;
+      Efl.Gfx.Gradient.Base.stop.set;
    }
 }
index 84207ef..521b06d 100644 (file)
@@ -15,9 +15,10 @@ static cairo_pattern_t *(*cairo_pattern_create_radial)(double cx0, double cy0,
                                                        double radius1) = NULL;
 static void (*cairo_set_source)(cairo_t *cr, cairo_pattern_t *source) = NULL;
 static void (*cairo_fill)(cairo_t *cr) = NULL;
-static void (*cairo_rectangle)(cairo_t *cr,
-                               double x, double y,
-                               double width, double height) = NULL;
+static void (*cairo_arc)(cairo_t *cr,
+                         double xc, double yc,
+                         double radius,
+                         double angle1, double angle2) = NULL;
 static void (*cairo_pattern_add_color_stop_rgba)(cairo_pattern_t *pattern, double offset,
                                                  double red, double green, double blue, double alpha) = NULL;
 static void (*cairo_pattern_destroy)(cairo_pattern_t *pattern) = NULL;
@@ -39,10 +40,12 @@ _ector_renderer_cairo_gradient_radial_ector_renderer_generic_base_prepare(Eo *ob
    Ector_Renderer_Generic_Gradient_Data *gd;
    unsigned int i;
 
+   eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_RADIAL_CLASS, ector_renderer_prepare());
+
    if (pd->pat) return EINA_FALSE;
 
-   grd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_CLASS);
-   gd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_CLASS);
+   grd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN);
+   gd = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN);
    if (!grd || !gd) return EINA_FALSE;
 
    USE(obj, cairo_pattern_create_radial, EINA_FALSE);
@@ -69,18 +72,23 @@ _ector_renderer_cairo_gradient_radial_ector_renderer_generic_base_prepare(Eo *ob
 
 // Clearly duplicated and should be in a common place...
 static Eina_Bool
-_ector_renderer_cairo_gradient_radial_ector_renderer_generic_base_draw(Eo *obj, Ector_Renderer_Cairo_Gradient_Radial_Data *pd, Ector_Rop op, Eina_Array *clips, int x, int y, unsigned int mul_col)
+_ector_renderer_cairo_gradient_radial_ector_renderer_generic_base_draw(Eo *obj, Ector_Renderer_Cairo_Gradient_Radial_Data *pd, Ector_Rop op, Eina_Array *clips, unsigned int mul_col)
 {
-   Ector_Renderer_Generic_Gradient_Linear_Data *gld;
+   Ector_Renderer_Generic_Gradient_Radial_Data *gld;
 
    // FIXME: don't ignore clipping !
-   gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS);
-   if (!pd->pat || !gld || CHECK_CAIRO(pd->parent)) return EINA_FALSE;
+   gld = eo_data_scope_get(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN);
+   if (!pd->pat || !gld) return EINA_FALSE;
+
+   eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_RADIAL_CLASS, ector_renderer_draw(op, clips, mul_col));
 
-   USE(obj, cairo_rectangle, EINA_FALSE);
+   USE(obj, cairo_arc, EINA_FALSE);
+   USE(obj, cairo_fill, EINA_FALSE);
 
-   cairo_rectangle(pd->parent->cairo, gld->start.x - x, gld->start.y - y,
-                   gld->end.x - gld->start.x, gld->end.y - gld->start.y);
+   cairo_arc(pd->parent->cairo,
+             gld->radial.x, gld->radial.y,
+             gld->radius,
+             0, 2 * M_PI);
    eo_do(obj, ector_renderer_cairo_base_fill());
    cairo_fill(pd->parent->cairo);
 
@@ -91,7 +99,7 @@ _ector_renderer_cairo_gradient_radial_ector_renderer_generic_base_draw(Eo *obj,
 static Eina_Bool
 _ector_renderer_cairo_gradient_radial_ector_renderer_cairo_base_fill(Eo *obj, Ector_Renderer_Cairo_Gradient_Radial_Data *pd)
 {
-   if (!pd->pat || CHECK_CAIRO(pd->parent)) return EINA_FALSE;
+   if (!pd->pat) return EINA_FALSE;
 
    USE(obj, cairo_set_source, EINA_FALSE);
 
@@ -118,14 +126,14 @@ _ector_renderer_cairo_gradient_radial_eo_base_destructor(Eo *obj,
 }
 
 void
-_ector_renderer_cairo_gradient_radial_efl_gfx_gradient_stop_set(Eo *obj, Ector_Renderer_Cairo_Gradient_Radial_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
+_ector_renderer_cairo_gradient_radial_efl_gfx_gradient_base_stop_set(Eo *obj, Ector_Renderer_Cairo_Gradient_Radial_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
 {
    USE(obj, cairo_pattern_destroy, );
 
    if (pd->pat) cairo_pattern_destroy(pd->pat);
    pd->pat = NULL;
 
-   eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_LINEAR_CLASS,
+   eo_do_super(obj, ECTOR_RENDERER_CAIRO_GRADIENT_RADIAL_CLASS,
                efl_gfx_gradient_stop_set(colors, length));
 }
 
index ab9595f..fb79bec 100644 (file)
@@ -1,4 +1,4 @@
-class Ector.Renderer.Cairo.Gradient_Radial (Ector.Renderer.Cairo.Base, Ector.Renderer.Generic.Gradient_Radial)
+class Ector.Renderer.Cairo.Gradient_Radial (Ector.Renderer.Cairo.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Radial)
 {
    eo_prefix: ector_renderer_cairo_gradient_radial;
    legacy_prefix: null;
@@ -7,6 +7,6 @@ class Ector.Renderer.Cairo.Gradient_Radial (Ector.Renderer.Cairo.Base, Ector.Ren
       Ector.Renderer.Generic.Base.draw;
       Ector.Renderer.Cairo.Base.fill;
       Eo.Base.destructor;
-      Efl.Gfx.Gradient.stop.set;
+      Efl.Gfx.Gradient.Base.stop.set;
    }
 }
index dcdedea..babf113 100644 (file)
@@ -46,16 +46,32 @@ struct _Ector_Renderer_Cairo_Shape_Data
 };
 
 static Eina_Bool
+_ector_renderer_cairo_shape_path_changed(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info)
+{
+   Ector_Renderer_Cairo_Shape_Data *pd = data;
+
+   USE(obj, cairo_path_destroy, EINA_TRUE);
+
+   if (pd->path) cairo_path_destroy(pd->path);
+   pd->path = NULL;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
 _ector_renderer_cairo_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Cairo_Shape_Data *pd)
 {
-   // FIXME: shouldn't that be part of the shape generic implementation ?
+   const Efl_Gfx_Path_Command *cmds = NULL;
+   const double *pts = NULL;
+
+   eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, ector_renderer_prepare());
+
    if (pd->shape->fill)
      eo_do(pd->shape->fill, ector_renderer_prepare());
    if (pd->shape->stroke.fill)
      eo_do(pd->shape->stroke.fill, ector_renderer_prepare());
    if (pd->shape->stroke.marker)
      eo_do(pd->shape->stroke.marker, ector_renderer_prepare());
-   eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, ector_renderer_prepare());
 
    // shouldn't that be moved to the cairo base object
    if (!pd->parent)
@@ -68,19 +84,16 @@ _ector_renderer_cairo_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_R
         if (!pd->parent) return EINA_FALSE;
      }
 
-   if (!pd->path && pd->shape->path.cmd)
+   eo_do(obj, efl_gfx_shape_path_get(&cmds, &pts));
+   if (!pd->path && cmds)
      {
-        double *pts;
-        unsigned int i;
-
         USE(obj, cairo_new_path, EINA_FALSE);
 
         cairo_new_path(pd->parent->cairo);
 
-        pts = pd->shape->path.pts;
-        for (i = 0; pd->shape->path.cmd[i] != EFL_GFX_PATH_COMMAND_TYPE_END; i++)
+        for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++)
           {
-             switch (pd->shape->path.cmd[i])
+             switch (*cmds)
                {
                 case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
                    USE(obj, cairo_move_to, EINA_FALSE);
@@ -128,13 +141,12 @@ _ector_renderer_cairo_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_R
 }
 
 static Eina_Bool
-_ector_renderer_cairo_shape_ector_renderer_generic_base_draw(Eo *obj, Ector_Renderer_Cairo_Shape_Data *pd, Ector_Rop op, Eina_Array *clips, int x, int y, unsigned int mul_col)
+_ector_renderer_cairo_shape_ector_renderer_generic_base_draw(Eo *obj, Ector_Renderer_Cairo_Shape_Data *pd, Ector_Rop op, Eina_Array *clips, unsigned int mul_col)
 {
    if (pd->path == NULL) return EINA_FALSE;
 
-   // FIXME: find a way to offset the drawing and setting multiple clips
-
-   eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, ector_renderer_draw(op, clips, x, y, mul_col));
+   // FIXME: find a way to set multiple clips
+   eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, ector_renderer_draw(op, clips, mul_col));
 
    USE(obj, cairo_new_path, EINA_FALSE);
    USE(obj, cairo_append_path, EINA_FALSE);
@@ -174,31 +186,25 @@ _ector_renderer_cairo_shape_ector_renderer_generic_base_draw(Eo *obj, Ector_Rend
 }
 
 static Eina_Bool
-_ector_renderer_cairo_shape_ector_renderer_cairo_base_fill(Eo *obj, Ector_Renderer_Cairo_Shape_Data *pd)
+_ector_renderer_cairo_shape_ector_renderer_cairo_base_fill(Eo *obj EINA_UNUSED,
+                                                           Ector_Renderer_Cairo_Shape_Data *pd EINA_UNUSED)
 {
    // FIXME: let's find out how to fill a shape with a shape later.
    // I need to read SVG specification and see how to map that with cairo.
+#warning "fill for a shape object is unhandled at this moment in cairo backend."
+   ERR("fill with shape not implemented\n");
+   return EINA_FALSE;
 }
 
-static void
-_ector_renderer_cairo_shape_efl_gfx_shape_path_set(Eo *obj, Ector_Renderer_Cairo_Shape_Data *pd,
-                                                   const Efl_Gfx_Path_Command *op, const double *points)
-{
-   USE(obj, cairo_path_destroy, );
-
-   if (pd->path) cairo_path_destroy(pd->path);
-   pd->path = NULL;
-
-   eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, efl_gfx_shape_path_set(op, points));
-}
-
-
 void
 _ector_renderer_cairo_shape_eo_base_constructor(Eo *obj, Ector_Renderer_Cairo_Shape_Data *pd)
 {
    eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, eo_constructor());
-   pd->shape = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_SHAPE_CLASS, obj);
+   pd->shape = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_SHAPE_MIXIN, obj);
    pd->base = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj);
+
+   eo_do(obj,
+         eo_event_callback_add(EFL_GFX_PATH_CHANGED, _ector_renderer_cairo_shape_path_changed, pd));
 }
 
 void
@@ -206,15 +212,16 @@ _ector_renderer_cairo_shape_eo_base_destructor(Eo *obj, Ector_Renderer_Cairo_Sha
 {
    Eo *parent;
 
-   USE(obj, cairo_path_destroy, );
-   if (pd->path) cairo_path_destroy(pd->path);
-
    eo_do(obj, parent = eo_parent_get());
    eo_data_xunref(parent, pd->parent, obj);
 
    eo_data_xunref(obj, pd->shape, obj);
    eo_data_xunref(obj, pd->base, obj);
+
    eo_do_super(obj, ECTOR_RENDERER_CAIRO_SHAPE_CLASS, eo_destructor());
+
+   USE(obj, cairo_path_destroy, );
+   if (pd->path) cairo_path_destroy(pd->path);
 }
 
 
index 55bd049..7dd1b31 100644 (file)
@@ -6,7 +6,6 @@ class Ector.Renderer.Cairo.Shape (Ector.Renderer.Cairo.Base, Ector.Renderer.Gene
       Ector.Renderer.Generic.Base.prepare;
       Ector.Renderer.Generic.Base.draw;
       Ector.Renderer.Cairo.Base.fill;
-      Efl.Gfx.Shape.path.set;
       Eo.Base.constructor;
       Eo.Base.destructor;
    }
index b8a60b5..42a5f3e 100644 (file)
@@ -14,17 +14,15 @@ abstract Ector.Generic.Surface (Eo.Base)
             int h; /*@ in */
          }
       }
-      surface {
+      reference_point {
          set {
-         }
-         get {
-         }
-         values {
-            void *pixels;
-            uint width;
-            uint height;
-         }
-      }      
+           /*@ This define where is (0,0) in pixels coordinate inside the surface */
+        }
+        values {
+           int x;
+           int y;
+        }
+      }
    }
    methods {
       renderer_factory_new {
@@ -46,5 +44,6 @@ abstract Ector.Generic.Surface (Eo.Base)
    }
    implements {
       @virtual .renderer_factory_new;
+      @virtual .reference_point.set;
    }
 }
index 5f09214..fa7413e 100644 (file)
@@ -22,7 +22,7 @@
 #include <Ector.h>
 #include "ector_private.h"
 
-int _ector_log_dom = 0;
+int _ector_log_dom_global = 0;
 
 static int _ector_main_count = 0;
 
@@ -35,8 +35,8 @@ ector_init(void)
    eina_init();
    eo_init();
 
-   _ector_log_dom = eina_log_domain_register("ector", ECTOR_DEFAULT_LOG_COLOR);
-   if (_ector_log_dom < 0)
+   _ector_log_dom_global = eina_log_domain_register("ector", ECTOR_DEFAULT_LOG_COLOR);
+   if (_ector_log_dom_global < 0)
      {
         EINA_LOG_ERR("Could not register log domain: ector");
         goto on_error;
@@ -44,7 +44,7 @@ ector_init(void)
 
    _ector_main_count = 1;
 
-   eina_log_timing(_ector_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT);
+   eina_log_timing(_ector_log_dom_global, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT);
 
    return _ector_main_count;
 
@@ -68,13 +68,13 @@ ector_shutdown(void)
    if (EINA_LIKELY(_ector_main_count > 0))
      return _ector_main_count;
 
-   eina_log_timing(_ector_log_dom,
+   eina_log_timing(_ector_log_dom_global,
                    EINA_LOG_STATE_START,
                    EINA_LOG_STATE_SHUTDOWN);
 
    eo_shutdown();
 
-   eina_log_domain_unregister(_ector_log_dom);
+   eina_log_domain_unregister(_ector_log_dom_global);
 
    eina_shutdown();
    return _ector_main_count;
index 896c849..49f772b 100644 (file)
@@ -36,6 +36,52 @@ extern int _ector_log_dom_global;
 #endif /* ifdef CRI */
 #define CRI(...) EINA_LOG_DOM_CRIT(_ector_log_dom_global, __VA_ARGS__)
 
+typedef unsigned char DATA8;
+typedef unsigned short DATA16;
+
+#ifndef WORDS_BIGENDIAN
+/* x86 */
+#define A_VAL(p) (((DATA8 *)(p))[3])
+#define R_VAL(p) (((DATA8 *)(p))[2])
+#define G_VAL(p) (((DATA8 *)(p))[1])
+#define B_VAL(p) (((DATA8 *)(p))[0])
+#define AR_VAL(p) ((DATA16 *)(p)[1])
+#define GB_VAL(p) ((DATA16 *)(p)[0])
+#else
+/* ppc */
+#define A_VAL(p) (((DATA8 *)(p))[0])
+#define R_VAL(p) (((DATA8 *)(p))[1])
+#define G_VAL(p) (((DATA8 *)(p))[2])
+#define B_VAL(p) (((DATA8 *)(p))[3])
+#define AR_VAL(p) ((DATA16 *)(p)[0])
+#define GB_VAL(p) ((DATA16 *)(p)[1])
+#endif
+
+#define RGB_JOIN(r,g,b) \
+  (((r) << 16) + ((g) << 8) + (b))
+
+#define ARGB_JOIN(a,r,g,b) \
+  (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
+
+static inline void
+ector_color_argb_premul(int a, int *r, int *g, int *b)
+{
+   a++;
+   if (r) { *r = (a * *r) >> 8; }
+   if (g) { *g = (a * *g) >> 8; }
+   if (b) { *b = (a * *b) >> 8; }
+}
+
+static inline void
+ector_color_argb_unpremul(int a, int *r, int *g, int *b)
+{
+   if (!a) return;
+   if (r) { *r = (255 * *r) / a; }
+   if (g) { *g = (255 * *g) / a; }
+   if (b) { *b = (255 * *b) / a; }
+}
+
+
 static inline void
 _ector_renderer_replace(Ector_Renderer **d, const Ector_Renderer *s)
 {
@@ -95,11 +141,6 @@ struct _Ector_Renderer_Generic_Gradient_Radial_Data
 
 struct _Ector_Renderer_Generic_Shape_Data
 {
-   struct {
-      Efl_Gfx_Path_Command *cmd;
-      double *pts;
-   } path;
-
    Ector_Renderer *fill;
    struct {
       Ector_Renderer *fill;
index 70b636b..4f45542 100644 (file)
@@ -123,4 +123,14 @@ _ector_renderer_generic_base_quality_get(Eo *obj EINA_UNUSED,
    return pd->q;
 }
 
+static Eina_Bool
+_ector_renderer_generic_base_prepare(Eo *obj EINA_UNUSED,
+                                     Ector_Renderer_Generic_Base_Data *pd)
+{
+   if (pd->mask)
+     eo_do(pd->mask, ector_renderer_prepare());
+
+   return EINA_TRUE;
+}
+
 #include "ector_renderer_generic_base.eo.c"
index 91275d5..50e7e94 100644 (file)
@@ -96,8 +96,6 @@ abstract Ector.Renderer.Generic.Base (Eo.Base)
         params {
            @in Ector_Rop op;
            @in array<Eina_Rectangle *> *clips; /*@ array of Eina_Rectangle clip */
-           @in int x;
-           @in int y;
            @in uint mul_col;
         }
       }
@@ -113,7 +111,6 @@ abstract Ector.Renderer.Generic.Base (Eo.Base)
    implements {
       @virtual .draw;
       @virtual .bounds_get;
-      @virtual .prepare;
       @virtual .done;
    }
 }
index 4a34141..2c0cc83 100644 (file)
@@ -1,11 +1,11 @@
-abstract Ector.Renderer.Generic.Gradient (Ector.Renderer.Generic.Base, Efl.Gfx.Gradient)
+mixin Ector.Renderer.Generic.Gradient (Efl.Gfx.Gradient.Base)
 {
    eo_prefix: ector_renderer_gradient;
    legacy_prefix: null;
    implements {
-      Efl.Gfx.Gradient.stop.set;
-      Efl.Gfx.Gradient.stop.get;
-      Efl.Gfx.Gradient.spread.set;
-      Efl.Gfx.Gradient.spread.get;
+      Efl.Gfx.Gradient.Base.stop.set;
+      Efl.Gfx.Gradient.Base.stop.get;
+      Efl.Gfx.Gradient.Base.spread.set;
+      Efl.Gfx.Gradient.Base.spread.get;
    }
 }
index 89ab3e1..13ab2e6 100644 (file)
@@ -1,11 +1,11 @@
-abstract Ector.Renderer.Generic.Gradient_Linear (Ector.Renderer.Generic.Gradient, Efl.Gfx.Gradient_Linear)
+mixin Ector.Renderer.Generic.Gradient_Linear (Efl.Gfx.Gradient.Linear)
 {
    eo_prefix: ector_renderer_gradient_linear;
    legacy_prefix: null;
    implements {
-      Efl.Gfx.Gradient_Linear.start.set;
-      Efl.Gfx.Gradient_Linear.start.get;
-      Efl.Gfx.Gradient_Linear.end.set;
-      Efl.Gfx.Gradient_Linear.end.get;
+      Efl.Gfx.Gradient.Linear.start.set;
+      Efl.Gfx.Gradient.Linear.start.get;
+      Efl.Gfx.Gradient.Linear.end.set;
+      Efl.Gfx.Gradient.Linear.end.get;
    }
 }
index 563c954..cef25eb 100644 (file)
@@ -1,13 +1,13 @@
-abstract Ector.Renderer.Generic.Gradient_Radial (Ector.Renderer.Generic.Gradient, Efl.Gfx.Gradient_Radial)
+mixin Ector.Renderer.Generic.Gradient_Radial (Efl.Gfx.Gradient.Radial)
 {
    eo_prefix: ector_renderer_gradient_radial;
    legacy_prefix: null;
    implements {
-      Efl.Gfx.Gradient_Radial.center.set;
-      Efl.Gfx.Gradient_Radial.center.get;
-      Efl.Gfx.Gradient_Radial.radius.set;
-      Efl.Gfx.Gradient_Radial.radius.get;
-      Efl.Gfx.Gradient_Radial.focal.set;
-      Efl.Gfx.Gradient_Radial.focal.get;
+      Efl.Gfx.Gradient.Radial.center.set;
+      Efl.Gfx.Gradient.Radial.center.get;
+      Efl.Gfx.Gradient.Radial.radius.set;
+      Efl.Gfx.Gradient.Radial.radius.get;
+      Efl.Gfx.Gradient.Radial.focal.set;
+      Efl.Gfx.Gradient.Radial.focal.get;
    }
 }
index edbec7b..2205b79 100644 (file)
@@ -1,4 +1,4 @@
-class Ector.Renderer.Generic.Shape (Ector.Renderer.Generic.Base, Efl.Gfx.Shape)
+mixin Ector.Renderer.Generic.Shape (Efl.Gfx.Shape)
 {
    eo_prefix: ector_renderer_shape;
    legacy_prefix: null;
@@ -39,8 +39,5 @@ class Ector.Renderer.Generic.Shape (Ector.Renderer.Generic.Base, Efl.Gfx.Shape)
       Efl.Gfx.Shape.stroke_dash;
       Efl.Gfx.Shape.stroke_cap;
       Efl.Gfx.Shape.stroke_join;
-      Efl.Gfx.Shape.path;
-      Eo.Base.constructor;
-      Eo.Base.destructor;
    }
 }
\ No newline at end of file
index 792f839..6cf676f 100644 (file)
@@ -8,10 +8,10 @@
 #include "ector_private.h"
 
 static void
-_ector_renderer_generic_gradient_efl_gfx_gradient_stop_set(Eo *obj,
-                                                           Ector_Renderer_Generic_Gradient_Data *pd,
-                                                           const Efl_Gfx_Gradient_Stop *colors,
-                                                           unsigned int length)
+_ector_renderer_generic_gradient_efl_gfx_gradient_base_stop_set(Eo *obj EINA_UNUSED,
+                                                                Ector_Renderer_Generic_Gradient_Data *pd,
+                                                                const Efl_Gfx_Gradient_Stop *colors,
+                                                                unsigned int length)
 {
    pd->colors = realloc(pd->colors, length * sizeof(Efl_Gfx_Gradient_Stop));
    if (!pd->colors)
@@ -25,26 +25,26 @@ _ector_renderer_generic_gradient_efl_gfx_gradient_stop_set(Eo *obj,
 }
 
 static void
-_ector_renderer_generic_gradient_efl_gfx_gradient_stop_get(Eo *obj,
-                                                           Ector_Renderer_Generic_Gradient_Data *pd,
-                                                           const Efl_Gfx_Gradient_Stop **colors,
-                                                           unsigned int *length)
+_ector_renderer_generic_gradient_efl_gfx_gradient_base_stop_get(Eo *obj EINA_UNUSED,
+                                                                Ector_Renderer_Generic_Gradient_Data *pd,
+                                                                const Efl_Gfx_Gradient_Stop **colors,
+                                                                unsigned int *length)
 {
    if (colors) *colors = pd->colors;
    if (length) *length = pd->colors_count;
 }
 
 static void
-_ector_renderer_generic_gradient_efl_gfx_gradient_spread_set(Eo *obj,
-                                                             Ector_Renderer_Generic_Gradient_Data *pd,
-                                                             Efl_Gfx_Gradient_Spread s)
+_ector_renderer_generic_gradient_efl_gfx_gradient_base_spread_set(Eo *obj EINA_UNUSED,
+                                                                  Ector_Renderer_Generic_Gradient_Data *pd,
+                                                                  Efl_Gfx_Gradient_Spread s)
 {
    pd->s = s;
 }
 
 static Efl_Gfx_Gradient_Spread
-_ector_renderer_generic_gradient_efl_gfx_gradient_spread_get(Eo *obj,
-                                                             Ector_Renderer_Generic_Gradient_Data *pd)
+_ector_renderer_generic_gradient_efl_gfx_gradient_base_spread_get(Eo *obj EINA_UNUSED,
+                                                                  Ector_Renderer_Generic_Gradient_Data *pd)
 {
    return pd->s;
 }
index feab722..cda749d 100644 (file)
@@ -136,7 +136,7 @@ _ector_renderer_generic_shape_efl_gfx_shape_stroke_dash_set(Eo *obj EINA_UNUSED,
      }
 
    tmp = realloc(pd->stroke.dash, length * sizeof (Efl_Gfx_Dash));
-   if (!tmp) return ;
+   if (!tmp && length) return ;
    memcpy(tmp, dash, length * sizeof (Efl_Gfx_Dash));
 
    pd->stroke.dash = tmp;
@@ -183,41 +183,4 @@ _ector_renderer_generic_shape_efl_gfx_shape_stroke_join_get(Eo *obj EINA_UNUSED,
    return pd->stroke.join;
 }
 
-static void
-_ector_renderer_generic_shape_efl_gfx_shape_path_set(Eo *obj EINA_UNUSED,
-                                                     Ector_Renderer_Generic_Shape_Data *pd,
-                                                     const Efl_Gfx_Path_Command *cmd,
-                                                     const double *points)
-{
-   free(pd->path.cmd);
-   pd->path.cmd = NULL;
-   free(pd->path.pts);
-   pd->path.pts = NULL;
-
-   efl_gfx_path_dup(&pd->path.cmd, &pd->path.pts, cmd, points);
-}
-
-void
-_ector_renderer_generic_shape_efl_gfx_shape_path_get(Eo *obj EINA_UNUSED,
-                                                     Ector_Renderer_Generic_Shape_Data *pd,
-                                                     const Efl_Gfx_Path_Command **op,
-                                                     const double **points)
-{
-   if (op) *op = pd->path.cmd;
-   if (points) *points = pd->path.pts;
-}
-
-static void
-_ector_renderer_generic_shape_eo_base_constructor(Eo *obj,
-                                                  Ector_Renderer_Generic_Shape_Data *pd)
-{
-    eo_do_super(obj, ECTOR_RENDERER_GENERIC_SHAPE_CLASS, eo_constructor());
-}
-
-static void
-_ector_renderer_generic_shape_eo_base_destructor(Eo *obj, Ector_Renderer_Generic_Shape_Data *pd)
-{
-  eo_do_super(obj, ECTOR_RENDERER_GENERIC_SHAPE_CLASS, eo_destructor());
-}
-
 #include "ector_renderer_generic_shape.eo.c"
index 949a4ef..eda912f 100644 (file)
@@ -26,21 +26,6 @@ _ector_generic_surface_size_get(Eo *obj,
 {
 }
 
-void _ector_generic_surface_surface_set(Eo *obj, 
-                                           Ector_Generic_Surface_Data *pd, 
-                                           void *pixels, unsigned int width, unsigned int height)
-{
-
-}
-
-void _ector_generic_surface_surface_get(Eo *obj, 
-                                                                               Ector_Generic_Surface_Data *pd, 
-                                                                               void **pixels, unsigned int *width, unsigned int *height)
-{
-
-}
-
-
 Eina_Bool
 _ector_generic_surface_update_push(Eo *obj,
                                    Ector_Generic_Surface_Data *pd,
diff --git a/src/lib/ector/ector_util.h b/src/lib/ector/ector_util.h
new file mode 100644 (file)
index 0000000..af8b591
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef ECTOR_UTIL_H
+# define ECTOR_UTIL_H
+
+static inline unsigned int
+ector_color_multiply(unsigned int c1, unsigned int c2)
+{
+   return ( ((((((c1) >> 16) & 0xff00) * (((c2) >> 16) & 0xff00)) + 0xff0000) & 0xff000000) +
+            ((((((c1) >> 8) & 0xff00) * (((c2) >> 16) & 0xff)) + 0xff00) & 0xff0000) +
+            ((((((c1) & 0xff00) * ((c2) & 0xff00)) + 0xff0000) >> 16) & 0xff00) +
+            (((((c1) & 0xff) * ((c2) & 0xff)) + 0xff) >> 8) );
+}
+
+#endif
diff --git a/src/lib/ector/software/ector_blend_private.h b/src/lib/ector/software/ector_blend_private.h
deleted file mode 100644 (file)
index ba48a03..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef ECTOR_BLEND_PRIVATE_H
-#define ECTOR_BLEND_PRIVATE_H
-
-#ifndef MIN
-#define MIN( a, b )  ( (a) < (b) ? (a) : (b) )
-#endif
-
-#ifndef MAX
-#define MAX( a, b )  ( (a) > (b) ? (a) : (b) )
-#endif
-
-#define ECTOR_ARGB_JOIN(a,r,g,b) \
-        (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
-
-#define ECTOR_MUL4_SYM(x, y) \
- ( ((((((x) >> 16) & 0xff00) * (((y) >> 16) & 0xff00)) + 0xff0000) & 0xff000000) + \
-   ((((((x) >> 8) & 0xff00) * (((y) >> 16) & 0xff)) + 0xff00) & 0xff0000) + \
-   ((((((x) & 0xff00) * ((y) & 0xff00)) + 0xff0000) >> 16) & 0xff00) + \
-   (((((x) & 0xff) * ((y) & 0xff)) + 0xff) >> 8) )
-
-#define ECTOR_MUL_256(c, a) \
- ( (((((c) >> 8) & 0x00ff00ff) * (a)) & 0xff00ff00) + \
-   (((((c) & 0x00ff00ff) * (a)) >> 8) & 0x00ff00ff) )
-
-
-static inline void
-_ector_memfill(DATA32 *dest, uint value, int count)
-{
-    if (!count)
-        return;
-
-    int n = (count + 7) / 8;
-    switch (count & 0x07)
-    {
-    case 0: do { *dest++ = value;
-    case 7:      *dest++ = value;
-    case 6:      *dest++ = value;
-    case 5:      *dest++ = value;
-    case 4:      *dest++ = value;
-    case 3:      *dest++ = value;
-    case 2:      *dest++ = value;
-    case 1:      *dest++ = value;
-    } while (--n > 0);
-    }
-}
-
-
-static inline void 
-_ector_comp_func_source_over_mul_c(uint *dest, uint *src, DATA32 c, int length, uint const_alpha)
-{
-    if (const_alpha == 255) {
-        for (int i = 0; i < length; ++i) {
-            uint s = src[i];
-            DATA32 sc = ECTOR_MUL4_SYM(c, s);
-            uint a = (~sc) >> 24;
-            dest[i] = sc + ECTOR_MUL_256(dest[i], a);
-        }
-    } else {
-        for (int i = 0; i < length; ++i) {
-            uint s = src[i];
-            DATA32 sc = ECTOR_MUL4_SYM(c, s);
-            sc = ECTOR_MUL_256(sc, const_alpha);
-            uint a = (~sc) >> 24;
-            dest[i] = sc + ECTOR_MUL_256(dest[i], a);
-        }
-    }
-}
-
-
-static inline void 
-_ector_comp_func_source_over(uint *dest, uint *src, int length, uint const_alpha)
-{
-    if (const_alpha == 255) {
-        for (int i = 0; i < length; ++i) {
-            uint s = src[i];
-            if (s >= 0xff000000)
-                dest[i] = s;
-            else if (s != 0) {
-                uint a = (~s) >> 24;
-                dest[i] = s + ECTOR_MUL_256(dest[i], a);
-            }
-        }
-    } else {
-        for (int i = 0; i < length; ++i) {
-            uint s = ECTOR_MUL_256(src[i], const_alpha);
-            uint a = (~s) >> 24;
-            dest[i] = s + ECTOR_MUL_256(dest[i], a);
-        }
-    }
-}
-
-
-static inline uint 
-_ector_premultiply(uint data)
-{
-    DATA32  a = 1 + (data >> 24);
-    data = ( data & 0xff000000) +
-      (((((data) >> 8) & 0xff) * a) & 0xff00) +
-      (((((data) & 0x00ff00ff) * a) >> 8) & 0x00ff00ff);
-
-    return data;
-}
-
-static inline uint 
-INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
-    uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
-    t >>= 8;
-    t &= 0xff00ff;
-
-    x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
-    x &= 0xff00ff00;
-    x |= t;
-    return x;
-}
-
-
-#endif
\ No newline at end of file
diff --git a/src/lib/ector/software/ector_drawhelper.c b/src/lib/ector/software/ector_drawhelper.c
new file mode 100644 (file)
index 0000000..8612199
--- /dev/null
@@ -0,0 +1,176 @@
+
+#include <Ector.h>
+#include "ector_drawhelper_private.h"
+
+/*
+  s = source pixel
+  d = destination pixel
+  ca = const_alpha
+  sia = source inverse alpha
+  cia = const inverse alpha
+
+*/
+
+/*
+  result = s + d * sia  
+  dest = (s + d * sia) * ca + d * cia
+       = s * ca + d * (sia * ca + cia)
+       = s * ca + d * (1 - sa*ca)
+*/
+void
+comp_func_solid_source_over(uint *dest, int length, uint color, uint const_alpha)
+{
+   int ialpha, i = 0;
+   if (const_alpha != 255)
+     color = BYTE_MUL(color, const_alpha);
+   ialpha = Alpha(~color);
+   for (; i < length; ++i)
+     dest[i] = color + BYTE_MUL(dest[i], ialpha);
+}
+
+
+static void
+comp_func_source_over(uint *dest, const uint *src, int length, uint color, uint const_alpha)
+{
+   if (color == 0xffffffff) // No color multiplier
+     {
+        if (const_alpha == 255)
+          {
+             for (int i = 0; i < length; ++i)
+               {
+                  uint s = src[i];
+                  if (s >= 0xff000000)
+                    dest[i] = s;
+                  else if (s != 0)
+                    {
+                       uint sia = Alpha(~s);
+                       dest[i] = s + BYTE_MUL(dest[i], sia);
+                    }
+              }
+          }
+        else
+          {
+             for (int i = 0; i < length; ++i)
+               {
+                  uint s = BYTE_MUL(src[i], const_alpha);
+                  uint sia = Alpha(~s);
+                  dest[i] = s + BYTE_MUL(dest[i], sia);
+               }
+          }
+     }
+   else
+     {
+        if (const_alpha == 255)
+          {
+             for (int i = 0; i < length; ++i)
+               {
+                  uint s = src[i];
+                  uint sc = ECTOR_MUL4_SYM(color, s);
+                  uint sia = Alpha(~sc);
+                  dest[i] = sc + BYTE_MUL(dest[i], sia);
+               }
+          }
+        else
+          {
+             for (int i = 0; i < length; ++i)
+               {
+                  uint s = src[i];
+                  uint sc = ECTOR_MUL4_SYM(color, s);
+                  sc = BYTE_MUL(sc, const_alpha);
+                  uint sia = Alpha(~sc);
+                  dest[i] = sc + BYTE_MUL(dest[i], sia);
+               }
+          }
+     }
+}
+
+/*
+  result = s
+  dest = s * ca + d * cia
+*/
+static void
+comp_func_solid_source(uint *dest, int length, uint color, uint const_alpha)
+{
+   if (const_alpha == 255) _ector_memfill(dest, length, color);
+   else
+     {
+        int ialpha, i = 0;
+        ialpha = 255 - const_alpha;
+        color = BYTE_MUL(color, const_alpha);
+        for (; i < length; ++i)
+          dest[i] = color + BYTE_MUL(dest[i], ialpha);
+     }
+}
+
+static void
+comp_func_source(uint *dest, const uint *src, int length, uint color, uint const_alpha)
+{
+   if (color == 0xffffffff) // No color multiplier
+     {
+        if (const_alpha == 255)
+          memcpy(dest, src, length * sizeof(uint));
+        else
+         {
+            int i, ialpha = 255 - const_alpha;
+            for (i = 0; i < length; ++i)
+              dest[i] = INTERPOLATE_PIXEL_256(src[i], const_alpha, dest[i], ialpha);
+         }
+     }
+   else
+     {
+        if (const_alpha == 255)
+          {
+             int i = 0;
+             for (; i < length; ++i)
+               dest[i] = ECTOR_MUL4_SYM(src[i], color);
+          }
+        else
+          {
+            int i, ialpha = 255 - const_alpha;
+            for (i = 0; i < length; ++i)
+              {
+                 uint src_color = ECTOR_MUL4_SYM(src[i], color);
+                 dest[i] = INTERPOLATE_PIXEL_256(src_color, const_alpha, dest[i], ialpha);
+            }
+          }
+     }
+}
+
+RGBA_Comp_Func_Solid func_for_mode_solid[ECTOR_ROP_LAST] = {
+        comp_func_solid_source_over,
+        comp_func_solid_source
+};
+
+RGBA_Comp_Func func_for_mode[ECTOR_ROP_LAST] = {
+        comp_func_source_over,
+        comp_func_source
+};
+
+RGBA_Comp_Func_Solid
+ector_comp_func_solid_span_get(Ector_Rop op, uint color)
+{
+   if ((color & 0xff000000) == 0xff000000)
+     {
+        if (op == ECTOR_ROP_BLEND) op = ECTOR_ROP_COPY;
+     }
+
+   return func_for_mode_solid[op];
+}
+
+RGBA_Comp_Func ector_comp_func_span_get(Ector_Rop op, uint color, Eina_Bool src_alpha)
+{
+   if (((color & 0xff000000) == 0xff000000) && !src_alpha)
+     {
+        if (op == ECTOR_ROP_BLEND) op = ECTOR_ROP_COPY;
+     }
+   return func_for_mode[op];
+}
+
+extern void init_drawhelper_gradient();
+extern void init_draw_helper_sse2();
+
+void init_draw_helper()
+{
+   init_drawhelper_gradient();
+   init_draw_helper_sse2();
+}
diff --git a/src/lib/ector/software/ector_drawhelper_private.h b/src/lib/ector/software/ector_drawhelper_private.h
new file mode 100644 (file)
index 0000000..4a7d59a
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef ECTOR_DRAWHELPER_PRIVATE_H
+#define ECTOR_DRAWHELPER_PRIVATE_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef MIN
+#define MIN( a, b )  ( (a) < (b) ? (a) : (b) )
+#endif
+
+#ifndef MAX
+#define MAX( a, b )  ( (a) > (b) ? (a) : (b) )
+#endif
+
+#ifndef uint
+typedef unsigned int uint;
+#endif
+
+inline int Alpha(uint c)
+{
+   return c>>24;
+}
+
+
+
+#define ECTOR_ARGB_JOIN(a,r,g,b) \
+        (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
+
+#define ECTOR_MUL4_SYM(x, y) \
+ ( ((((((x) >> 16) & 0xff00) * (((y) >> 16) & 0xff00)) + 0xff0000) & 0xff000000) + \
+   ((((((x) >> 8) & 0xff00) * (((y) >> 16) & 0xff)) + 0xff00) & 0xff0000) + \
+   ((((((x) & 0xff00) * ((y) & 0xff00)) + 0xff0000) >> 16) & 0xff00) + \
+   (((((x) & 0xff) * ((y) & 0xff)) + 0xff) >> 8) )
+
+#define BYTE_MUL(c, a) \
+ ( (((((c) >> 8) & 0x00ff00ff) * (a)) & 0xff00ff00) + \
+   (((((c) & 0x00ff00ff) * (a)) >> 8) & 0x00ff00ff) )
+
+#define LOOP_ALIGNED_U1_A4(DEST, LENGTH, UOP, A4OP) \
+   { \
+      while((uintptr_t)DEST & 0xF && LENGTH) UOP \
+   \
+      while(LENGTH) { \
+         switch(LENGTH) { \
+            case 3: \
+            case 2: \
+            case 1: \
+               UOP \
+               break; \
+            default: \
+               A4OP \
+               break; \
+         } \
+      } \
+   }
+
+static inline void
+_ector_memfill(uint *dest, int length, uint value)
+{
+   if (!length)
+     return;
+
+   int n = (length + 7) / 8;
+   switch (length & 0x07)
+     {
+        case 0: do { *dest++ = value;
+        case 7:      *dest++ = value;
+        case 6:      *dest++ = value;
+        case 5:      *dest++ = value;
+        case 4:      *dest++ = value;
+        case 3:      *dest++ = value;
+        case 2:      *dest++ = value;
+        case 1:      *dest++ = value;
+        } while (--n > 0);
+     }
+}
+
+static inline uint 
+INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b)
+{
+   uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
+   t >>= 8;
+   t &= 0xff00ff;
+   x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
+   x &= 0xff00ff00;
+   x |= t;
+   return x;
+}
+
+typedef void (*RGBA_Comp_Func)(uint *dest, const uint *src, int length, uint mul_col, uint const_alpha);
+typedef void (*RGBA_Comp_Func_Solid)(uint *dest, int length, uint color, uint const_alpha);
+extern RGBA_Comp_Func_Solid func_for_mode_solid[ECTOR_ROP_LAST];
+extern RGBA_Comp_Func func_for_mode[ECTOR_ROP_LAST];
+
+void init_draw_helper();
+
+RGBA_Comp_Func_Solid ector_comp_func_solid_span_get(Ector_Rop op, uint color);
+RGBA_Comp_Func ector_comp_func_span_get(Ector_Rop op, uint color, Eina_Bool src_alpha);
+
+#endif
\ No newline at end of file
diff --git a/src/lib/ector/software/ector_drawhelper_sse2.c b/src/lib/ector/software/ector_drawhelper_sse2.c
new file mode 100644 (file)
index 0000000..1199cdb
--- /dev/null
@@ -0,0 +1,359 @@
+
+#include <Ector.h>
+#include "ector_drawhelper_private.h"
+
+#ifdef BUILD_SSE3
+#include <immintrin.h>
+
+// Each 32bits components of alphaChannel must be in the form 0x00AA00AA
+inline static __m128i
+v4_byte_mul_sse2(__m128i c, __m128i a)
+{
+   const __m128i ag_mask = _mm_set1_epi32(0xFF00FF00);
+   const __m128i rb_mask = _mm_set1_epi32(0x00FF00FF);
+
+   /* for AG */
+   __m128i v_ag = _mm_and_si128(ag_mask, c);
+   v_ag = _mm_srli_epi32(v_ag, 8);
+   v_ag = _mm_mullo_epi16(a, v_ag);
+   v_ag = _mm_and_si128(ag_mask, v_ag);
+
+   /* for RB */
+   __m128i v_rb = _mm_and_si128(rb_mask, c);
+   v_rb = _mm_mullo_epi16(a, v_rb);
+   v_rb = _mm_srli_epi32(v_rb, 8);
+   v_rb = _mm_and_si128(rb_mask, v_rb);
+
+   /* combine */
+   return _mm_add_epi32(v_ag, v_rb);
+}
+
+static inline __m128i
+v4_interpolate_color_sse2(__m128i a, __m128i c0, __m128i c1)
+{
+   const __m128i rb_mask = _mm_set1_epi32(0xFF00FF00);
+   const __m128i zero = _mm_setzero_si128();
+
+   __m128i a_l = a;
+   __m128i a_h = a;
+   a_l = _mm_unpacklo_epi16(a_l, a_l);
+   a_h = _mm_unpackhi_epi16(a_h, a_h);
+
+   __m128i a_t = _mm_slli_epi64(a_l, 32);
+   __m128i a_t0 = _mm_slli_epi64(a_h, 32);
+
+   a_l = _mm_add_epi32(a_l, a_t);
+   a_h = _mm_add_epi32(a_h, a_t0);
+
+   __m128i c0_l = c0;
+   __m128i c0_h = c0;
+
+   c0_l = _mm_unpacklo_epi8(c0_l, zero);
+   c0_h = _mm_unpackhi_epi8(c0_h, zero);
+
+   __m128i c1_l = c1;
+   __m128i c1_h = c1;
+
+   c1_l = _mm_unpacklo_epi8(c1_l, zero);
+   c1_h = _mm_unpackhi_epi8(c1_h, zero);
+
+   __m128i cl_sub = _mm_sub_epi16(c0_l, c1_l);
+   __m128i ch_sub = _mm_sub_epi16(c0_h, c1_h);
+
+   cl_sub = _mm_mullo_epi16(cl_sub, a_l);
+   ch_sub = _mm_mullo_epi16(ch_sub, a_h);
+
+   __m128i c1ls = _mm_slli_epi16(c1_l, 8);
+   __m128i c1hs = _mm_slli_epi16(c1_h, 8);
+
+   cl_sub = _mm_add_epi16(cl_sub, c1ls);
+   ch_sub = _mm_add_epi16(ch_sub, c1hs);
+
+   cl_sub = _mm_and_si128(cl_sub, rb_mask);
+   ch_sub = _mm_and_si128(ch_sub, rb_mask);
+
+   cl_sub = _mm_srli_epi64(cl_sub, 8);
+   ch_sub = _mm_srli_epi64(ch_sub, 8);
+
+   cl_sub = _mm_packus_epi16(cl_sub, cl_sub);
+   ch_sub = _mm_packus_epi16(ch_sub, ch_sub);
+
+   return  (__m128i) _mm_shuffle_ps( (__m128)cl_sub, (__m128)ch_sub, 0x44);
+}
+
+static inline __m128i
+v4_mul_color_sse2(__m128i x, __m128i y)
+{
+   const __m128i zero = _mm_setzero_si128();
+   const __m128i sym4_mask = _mm_set_epi32(0x00FF00FF, 0x000000FF, 0x00FF00FF, 0x000000FF);
+   __m128i x_l = _mm_unpacklo_epi8(x, zero);
+   __m128i x_h = _mm_unpackhi_epi8(x, zero);
+
+   __m128i y_l = _mm_unpacklo_epi8(y, zero);
+   __m128i y_h = _mm_unpackhi_epi8(y, zero);
+
+   __m128i r_l = _mm_mullo_epi16(x_l, y_l);
+   __m128i r_h = _mm_mullo_epi16(x_h, y_h);
+
+   r_l = _mm_add_epi16(r_l, sym4_mask);
+   r_h = _mm_add_epi16(r_h, sym4_mask);
+
+   r_l = _mm_srli_epi16(r_l, 8);
+   r_h = _mm_srli_epi16(r_h, 8);
+
+   return  _mm_packus_epi16(r_l, r_h);
+}
+
+static inline __m128i
+v4_ialpha_sse2(__m128i c)
+{
+   __m128i a = _mm_srli_epi32(c, 24);
+   return _mm_sub_epi32(_mm_set1_epi32(0xff), a);
+}
+
+// dest = color + (dest * alpha)
+inline static void
+comp_func_helper_sse2 (uint *dest, int length, uint color, uint alpha)
+{
+   const __m128i v_color = _mm_set1_epi32(color);
+   const __m128i v_a = _mm_set1_epi16(alpha);
+
+   LOOP_ALIGNED_U1_A4(dest, length,
+      { /* UOP */
+         *dest = color + BYTE_MUL(*dest, alpha);
+         dest++; length--;
+      },
+      { /* A4OP */
+         __m128i v_dest = _mm_load_si128((__m128i *)dest);
+
+         v_dest = v4_byte_mul_sse2(v_dest, v_a);
+         v_dest = _mm_add_epi32(v_dest, v_color);
+
+         _mm_store_si128((__m128i *)dest, v_dest);
+
+         dest += 4; length -= 4;
+      })
+}
+
+void
+comp_func_solid_source_sse2(uint *dest, int length, uint color, uint const_alpha)
+{
+   if (const_alpha == 255) _ector_memfill(dest, length, color);
+   else
+     {
+        int ialpha;
+        ialpha = 255 - const_alpha;
+        color = BYTE_MUL(color, const_alpha);
+        comp_func_helper_sse2(dest, length, color, ialpha);
+     }
+}
+
+void
+comp_func_solid_source_over_sse2(uint *dest, int length, uint color, uint const_alpha)
+{
+   int ialpha;
+   if (const_alpha != 255)
+     color = BYTE_MUL(color, const_alpha);
+   ialpha = Alpha(~color);
+   comp_func_helper_sse2(dest, length, color, ialpha);
+}
+
+// Load src and dest vector
+#define V4_FETCH_SRC_DEST \
+  __m128i v_src = _mm_loadu_si128((__m128i *)src); \
+  __m128i v_dest = _mm_load_si128((__m128i *)dest);
+
+#define V4_FETCH_SRC \
+  __m128i v_src = _mm_loadu_si128((__m128i *)src);
+
+#define V4_STORE_DEST \
+  _mm_store_si128((__m128i *)dest, v_src);
+
+#define V4_SRC_DEST_LEN_INC \
+  dest += 4; src +=4; length -= 4;
+
+// Multiply src color with color multiplier
+#define V4_COLOR_MULTIPLY \
+  v_src = v4_mul_color_sse2(v_src, v_color);
+
+// Multiply src color with const_alpha
+#define V4_ALPHA_MULTIPLY \
+  v_src = v4_byte_mul_sse2(v_src, v_alpha);
+
+// dest = src + dest * sia
+#define V4_COMP_OP_SRC_OVER \
+  __m128i v_sia = v4_ialpha_sse2(v_src); \
+  v_sia = _mm_add_epi32(v_sia, _mm_slli_epi32(v_sia, 16)); \
+  v_dest = v4_byte_mul_sse2(v_dest, v_sia); \
+  v_src = _mm_add_epi32(v_src, v_dest);
+
+// dest = src + dest * sia
+#define V4_COMP_OP_SRC \
+  v_src = v4_interpolate_color_sse2(v_alpha, v_src, v_dest);
+
+
+
+static void
+comp_func_source_sse2(uint *dest, const uint *src, int length, uint color, uint const_alpha)
+{
+   if (color == 0xffffffff) // No color multiplier
+     {
+        if (const_alpha == 255)
+          memcpy(dest, src, length * sizeof(uint));
+        else
+          {
+             int ialpha = 255 - const_alpha;
+             __m128i v_alpha = _mm_set1_epi32(const_alpha);
+             LOOP_ALIGNED_U1_A4(dest, length,
+               { /* UOP */
+                  *dest = INTERPOLATE_PIXEL_256(*src, const_alpha, *dest, ialpha);
+                  dest++; src++; length--;
+               },
+               { /* A4OP */
+                  V4_FETCH_SRC_DEST
+                  V4_COMP_OP_SRC
+                  V4_STORE_DEST
+                  V4_SRC_DEST_LEN_INC
+               })
+          }
+     }
+   else
+     {
+        __m128i v_color = _mm_set1_epi32(color);
+        if (const_alpha == 255)
+          {
+             LOOP_ALIGNED_U1_A4(dest, length,
+               { /* UOP */
+                  *dest = ECTOR_MUL4_SYM(*src, color);
+                  dest++; src++; length--;
+               },
+               { /* A4OP */
+                  V4_FETCH_SRC
+                  V4_COLOR_MULTIPLY
+                  V4_STORE_DEST
+                  V4_SRC_DEST_LEN_INC
+               })
+          }
+        else
+          {
+             int ialpha = 255 - const_alpha;
+             __m128i v_alpha = _mm_set1_epi32(const_alpha);
+             LOOP_ALIGNED_U1_A4(dest, length,
+               { /* UOP */
+                  uint src_color = ECTOR_MUL4_SYM(*src, color);
+                  *dest = INTERPOLATE_PIXEL_256(src_color, const_alpha, *dest, ialpha);
+                  dest++; src++; length--;
+               },
+               { /* A4OP */
+                  V4_FETCH_SRC_DEST
+                  V4_COLOR_MULTIPLY
+                  V4_COMP_OP_SRC
+                  V4_STORE_DEST
+                  V4_SRC_DEST_LEN_INC
+               })
+          }
+     }
+}
+
+static void
+comp_func_source_over_sse2(uint *dest, const uint *src, int length, uint color, uint const_alpha)
+{
+   if (color == 0xffffffff) // No color multiplier
+     {
+        if (const_alpha == 255)
+          {
+             LOOP_ALIGNED_U1_A4(dest, length,
+               { /* UOP */
+                  uint s = *src;
+                  uint sia = Alpha(~s);
+                  *dest = s + BYTE_MUL(*dest, sia);
+                  dest++; src++; length--;
+               },
+               { /* A4OP */
+                  V4_FETCH_SRC_DEST
+                  V4_COMP_OP_SRC_OVER
+                  V4_STORE_DEST
+                  V4_SRC_DEST_LEN_INC
+               })
+          }
+        else
+          {
+             __m128i v_alpha = _mm_set1_epi16(const_alpha);
+             LOOP_ALIGNED_U1_A4(dest, length,
+               { /* UOP */
+                  uint s = BYTE_MUL(*src, const_alpha);
+                  uint sia = Alpha(~s);
+                  *dest = s + BYTE_MUL(*dest, sia);
+                  dest++; src++; length--;
+               },
+               { /* A4OP */
+                  V4_FETCH_SRC_DEST
+                  V4_ALPHA_MULTIPLY
+                  V4_COMP_OP_SRC_OVER
+                  V4_STORE_DEST
+                  V4_SRC_DEST_LEN_INC
+               })
+          }
+     }
+   else
+     {
+        __m128i v_color = _mm_set1_epi32(color);
+        if (const_alpha == 255)
+          {
+             LOOP_ALIGNED_U1_A4(dest, length,
+               { /* UOP */
+                  uint s = ECTOR_MUL4_SYM(*src, color);
+                  uint sia = Alpha(~s);
+                  *dest = s + BYTE_MUL(*dest, sia);
+                  dest++; src++; length--;
+               },
+               { /* A4OP */
+                  V4_FETCH_SRC_DEST
+                  V4_COLOR_MULTIPLY
+                  V4_COMP_OP_SRC_OVER
+                  V4_STORE_DEST
+                  V4_SRC_DEST_LEN_INC
+               })
+          }
+        else
+          {
+             __m128i v_alpha = _mm_set1_epi16(const_alpha);
+             LOOP_ALIGNED_U1_A4(dest, length,
+               { /* UOP */
+                  uint s = ECTOR_MUL4_SYM(*src, color);
+                  s = BYTE_MUL(s, const_alpha);
+                  uint sia = Alpha(~s);
+                  *dest = s + BYTE_MUL(*dest, sia);
+                  dest++; src++; length--;
+               },
+               { /* A4OP */
+                  V4_FETCH_SRC_DEST
+                  V4_COLOR_MULTIPLY
+                  V4_ALPHA_MULTIPLY
+                  V4_COMP_OP_SRC_OVER
+                  V4_STORE_DEST
+                  V4_SRC_DEST_LEN_INC
+               })
+          }
+     }
+}
+
+#endif
+
+void
+init_draw_helper_sse2()
+{
+#ifdef BUILD_SSE3
+   if (eina_cpu_features_get() & EINA_CPU_SSE2)
+     {
+        // update the comp_function table for solid color
+        func_for_mode_solid[ECTOR_ROP_COPY] = comp_func_solid_source_sse2;
+        func_for_mode_solid[ECTOR_ROP_BLEND] = comp_func_solid_source_over_sse2;
+
+        // update the comp_function table for source data
+        func_for_mode[ECTOR_ROP_COPY] = comp_func_source_sse2;
+        func_for_mode[ECTOR_ROP_BLEND] = comp_func_source_over_sse2;
+      }
+#endif
+}
+
index 9d9826f..6055be5 100644 (file)
@@ -1,4 +1,4 @@
-interface Ector.Renderer.Software.Base
+class Ector.Renderer.Software.Base (Ector.Renderer.Generic.Base)
 {
    legacy_prefix: null;
    methods {
@@ -6,4 +6,7 @@ interface Ector.Renderer.Software.Base
          return: bool;
       }
    }
+   implements {
+      @virtual .fill;
+   }
 }
index 621d7ff..a6e32b0 100644 (file)
 static void
 _update_linear_data(Ector_Renderer_Software_Gradient_Data *gdata)
 {
-    update_color_table(gdata);
-    gdata->linear.x1 = gdata->gld->start.x;
-    gdata->linear.y1 = gdata->gld->start.y;
-
-    gdata->linear.x2 = gdata->gld->end.x;
-    gdata->linear.y2 = gdata->gld->end.y;
-
-    gdata->linear.dx = gdata->linear.x2 - gdata->linear.x1;
-    gdata->linear.dy = gdata->linear.y2 - gdata->linear.y1;
-    gdata->linear.l = gdata->linear.dx * gdata->linear.dx + gdata->linear.dy * gdata->linear.dy;
-    gdata->linear.off = 0;
-    if (gdata->linear.l != 0) {
+   update_color_table(gdata);
+   gdata->linear.x1 = gdata->gld->start.x;
+   gdata->linear.y1 = gdata->gld->start.y;
+
+   gdata->linear.x2 = gdata->gld->end.x;
+   gdata->linear.y2 = gdata->gld->end.y;
+
+   gdata->linear.dx = gdata->linear.x2 - gdata->linear.x1;
+   gdata->linear.dy = gdata->linear.y2 - gdata->linear.y1;
+   gdata->linear.l = gdata->linear.dx * gdata->linear.dx + gdata->linear.dy * gdata->linear.dy;
+   gdata->linear.off = 0;
+
+   if (gdata->linear.l != 0)
+     {
         gdata->linear.dx /= gdata->linear.l;
         gdata->linear.dy /= gdata->linear.l;
         gdata->linear.off = -gdata->linear.dx * gdata->linear.x1 - gdata->linear.dy * gdata->linear.y1;
-    }
+     }
 }
 
 
 static Eina_Bool
 _ector_renderer_software_gradient_linear_ector_renderer_generic_base_prepare(Eo *obj,
-                                                                          Ector_Renderer_Software_Gradient_Data *pd)
+                                                                             Ector_Renderer_Software_Gradient_Data *pd)
 {
    if (!pd->surface)
      {
@@ -45,7 +47,7 @@ _ector_renderer_software_gradient_linear_ector_renderer_generic_base_prepare(Eo
         pd->surface = eo_data_xref(parent, ECTOR_SOFTWARE_SURFACE_CLASS, obj);
      }
 
-     _update_linear_data(pd);
+   _update_linear_data(pd);
 
 
    return EINA_FALSE;
@@ -53,56 +55,55 @@ _ector_renderer_software_gradient_linear_ector_renderer_generic_base_prepare(Eo
 
 static Eina_Bool
 _ector_renderer_software_gradient_linear_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED,
-                                                                       Ector_Renderer_Software_Gradient_Data *pd EINA_UNUSED,
-                                                                       Ector_Rop op EINA_UNUSED, Eina_Array *clips EINA_UNUSED, 
-                                                                       int x EINA_UNUSED, int y EINA_UNUSED, unsigned int mul_col EINA_UNUSED)
+                                                                          Ector_Renderer_Software_Gradient_Data *pd EINA_UNUSED,
+                                                                          Ector_Rop op EINA_UNUSED, Eina_Array *clips EINA_UNUSED,
+                                                                          unsigned int mul_col EINA_UNUSED)
 {
-
    return EINA_TRUE;
 }
 
 static Eina_Bool
 _ector_renderer_software_gradient_linear_ector_renderer_software_base_fill(Eo *obj EINA_UNUSED,
-                                                                     Ector_Renderer_Software_Gradient_Data *pd)
+                                                                           Ector_Renderer_Software_Gradient_Data *pd)
 {
-  ector_software_rasterizer_linear_gradient_set(pd->surface->software, pd);
+   ector_software_rasterizer_linear_gradient_set(pd->surface->software, pd);
 
    return EINA_TRUE;
 }
 
 void
 _ector_renderer_software_gradient_linear_eo_base_constructor(Eo *obj,
-                                                         Ector_Renderer_Software_Gradient_Data *pd)
+                                                             Ector_Renderer_Software_Gradient_Data *pd)
 {
    eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS, eo_constructor());
-   pd->gd  = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_CLASS, obj);
-   pd->gld = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS, obj);
+   pd->gd  = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN, obj);
+   pd->gld = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN, obj);
 }
 
 void
 _ector_renderer_software_gradient_linear_eo_base_destructor(Eo *obj,
-                                                         Ector_Renderer_Software_Gradient_Data *pd)
+                                                            Ector_Renderer_Software_Gradient_Data *pd)
 {
    Eo *parent;
-   
+
    destroy_color_table(pd);
-   
+
    eo_do(obj, parent = eo_parent_get());
    eo_data_xunref(parent, pd->surface, obj);
 
    eo_data_xunref(obj, pd->gd, obj);
    eo_data_xunref(obj, pd->gld, obj);
-   
+
    eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS, eo_destructor());
 }
 
 void
-_ector_renderer_software_gradient_linear_efl_gfx_gradient_stop_set(Eo *obj, Ector_Renderer_Software_Gradient_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
+_ector_renderer_software_gradient_linear_efl_gfx_gradient_base_stop_set(Eo *obj, Ector_Renderer_Software_Gradient_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
 {
-  eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS,
-              efl_gfx_gradient_stop_set(colors, length));
-  
-  destroy_color_table(pd);
+   eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS,
+               efl_gfx_gradient_stop_set(colors, length));
+
+   destroy_color_table(pd);
 }
 
 #include "ector_renderer_software_gradient_linear.eo.c"
index 77455c0..32f83df 100644 (file)
@@ -1,4 +1,4 @@
-class Ector.Renderer.Software.Gradient_Linear (Ector.Renderer.Generic.Gradient_Linear, Ector.Renderer.Software.Base)
+class Ector.Renderer.Software.Gradient_Linear (Ector.Renderer.Software.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Linear)
 {
    eo_prefix: ector_renderer_software_gradient_linear;
    legacy_prefix: null;
@@ -9,6 +9,6 @@ class Ector.Renderer.Software.Gradient_Linear (Ector.Renderer.Generic.Gradient_L
       Ector.Renderer.Software.Base.fill;
       Eo.Base.constructor;
       Eo.Base.destructor;
-      Efl.Gfx.Gradient.stop.set;
+      Efl.Gfx.Gradient.Base.stop.set;
    }
 }
index d8d1792..a05b487 100644 (file)
 static void
 _update_radial_data(Ector_Renderer_Software_Gradient_Data *gdata)
 {
-    update_color_table(gdata);
+   update_color_table(gdata);
 
-    gdata->radial.cx = gdata->grd->radial.x;
-    gdata->radial.cy = gdata->grd->radial.y;
-    gdata->radial.cradius = gdata->grd->radius;
+   gdata->radial.cx = gdata->grd->radial.x;
+   gdata->radial.cy = gdata->grd->radial.y;
+   gdata->radial.cradius = gdata->grd->radius;
 
-    if(!gdata->grd->focal.x)
-        gdata->radial.fx = gdata->grd->radial.x;
-    else
-        gdata->radial.fx = gdata->grd->focal.x;
+   if (!gdata->grd->focal.x)
+     gdata->radial.fx = gdata->grd->radial.x;
+   else
+     gdata->radial.fx = gdata->grd->focal.x;
 
-    if(!gdata->grd->focal.y)
-        gdata->radial.fy = gdata->grd->radial.y;
-    else
-        gdata->radial.fy = gdata->grd->focal.y;
+   if (!gdata->grd->focal.y)
+     gdata->radial.fy = gdata->grd->radial.y;
+   else
+     gdata->radial.fy = gdata->grd->focal.y;
 
-    gdata->radial.fradius = 0;
+   gdata->radial.fradius = 0;
 
-    gdata->radial.dx = gdata->radial.cx - gdata->radial.fx;
-    gdata->radial.dy = gdata->radial.cy - gdata->radial.fy;
+   gdata->radial.dx = gdata->radial.cx - gdata->radial.fx;
+   gdata->radial.dy = gdata->radial.cy - gdata->radial.fy;
 
-    gdata->radial.dr = gdata->radial.cradius - gdata->radial.fradius;
-    gdata->radial.sqrfr = gdata->radial.fradius * gdata->radial.fradius;
+   gdata->radial.dr = gdata->radial.cradius - gdata->radial.fradius;
+   gdata->radial.sqrfr = gdata->radial.fradius * gdata->radial.fradius;
 
-    gdata->radial.a = gdata->radial.dr * gdata->radial.dr -
-                       gdata->radial.dx * gdata->radial.dx -
-                       gdata->radial.dy * gdata->radial.dy;
-    gdata->radial.inv2a = 1 / (2 * gdata->radial.a);
+   gdata->radial.a = gdata->radial.dr * gdata->radial.dr -
+                     gdata->radial.dx * gdata->radial.dx -
+                     gdata->radial.dy * gdata->radial.dy;
+   gdata->radial.inv2a = 1 / (2 * gdata->radial.a);
 
-    gdata->radial.extended = (gdata->radial.fradius >= 0.00001f) || gdata->radial.a >= 0.00001f;
+   gdata->radial.extended = (gdata->radial.fradius >= 0.00001f) || gdata->radial.a >= 0.00001f;
 }
 
 
@@ -57,16 +57,16 @@ _ector_renderer_software_gradient_radial_ector_renderer_generic_base_prepare(Eo
         pd->surface = eo_data_xref(parent, ECTOR_SOFTWARE_SURFACE_CLASS, obj);
      }
 
-     _update_radial_data(pd);  
+   _update_radial_data(pd);
    return EINA_FALSE;
 }
 
 // Clearly duplicated and should be in a common place...
 static Eina_Bool
 _ector_renderer_software_gradient_radial_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED,
-                                                                       Ector_Renderer_Software_Gradient_Data *pd EINA_UNUSED,
-                                                                       Ector_Rop op EINA_UNUSED, Eina_Array *clips EINA_UNUSED, 
-                                                                       int x EINA_UNUSED, int y EINA_UNUSED, unsigned int mul_col EINA_UNUSED)
+                                                                          Ector_Renderer_Software_Gradient_Data *pd EINA_UNUSED,
+                                                                          Ector_Rop op EINA_UNUSED, Eina_Array *clips EINA_UNUSED,
+                                                                          unsigned int mul_col EINA_UNUSED)
 {
    return EINA_TRUE;
 }
@@ -75,43 +75,43 @@ _ector_renderer_software_gradient_radial_ector_renderer_generic_base_draw(Eo *ob
 static Eina_Bool
 _ector_renderer_software_gradient_radial_ector_renderer_software_base_fill(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Gradient_Data *pd)
 {
-  ector_software_rasterizer_radial_gradient_set(pd->surface->software, pd);
+   ector_software_rasterizer_radial_gradient_set(pd->surface->software, pd);
    return EINA_TRUE;
 }
 
 void
 _ector_renderer_software_gradient_radial_eo_base_constructor(Eo *obj,
-                                                         Ector_Renderer_Software_Gradient_Data *pd)
+                                                             Ector_Renderer_Software_Gradient_Data *pd)
 {
    eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS, eo_constructor());
-   pd->gd  = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_CLASS, obj);
-   pd->gld = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_CLASS, obj);
+   pd->gd  = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN, obj);
+   pd->gld = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN, obj);
 }
 
 void
 _ector_renderer_software_gradient_radial_eo_base_destructor(Eo *obj,
-                                                         Ector_Renderer_Software_Gradient_Data *pd)
+                                                            Ector_Renderer_Software_Gradient_Data *pd)
 {
-  Eo *parent;
+   Eo *parent;
 
-  destroy_color_table(pd);
+   destroy_color_table(pd);
 
-  eo_do(obj, parent = eo_parent_get());
-  eo_data_xunref(parent, pd->surface, obj);
+   eo_do(obj, parent = eo_parent_get());
+   eo_data_xunref(parent, pd->surface, obj);
 
-  eo_data_xunref(obj, pd->gd, obj);
-  eo_data_xunref(obj, pd->gld, obj);
+   eo_data_xunref(obj, pd->gd, obj);
+   eo_data_xunref(obj, pd->gld, obj);
 
-  eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS, eo_destructor());
+   eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS, eo_destructor());
 }
 
 void
-_ector_renderer_software_gradient_radial_efl_gfx_gradient_stop_set(Eo *obj, Ector_Renderer_Software_Gradient_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
+_ector_renderer_software_gradient_radial_efl_gfx_gradient_base_stop_set(Eo *obj, Ector_Renderer_Software_Gradient_Data *pd, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
 {
-  eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS,
-              efl_gfx_gradient_stop_set(colors, length));
+   eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS,
+               efl_gfx_gradient_stop_set(colors, length));
 
-  destroy_color_table(pd);
+   destroy_color_table(pd);
 }
 
 #include "ector_renderer_software_gradient_radial.eo.c"
index 36d61ad..85625f3 100644 (file)
@@ -1,4 +1,4 @@
-class Ector.Renderer.Software.Gradient_Radial (Ector.Renderer.Generic.Gradient_Radial, Ector.Renderer.Software.Base)
+class Ector.Renderer.Software.Gradient_Radial (Ector.Renderer.Software.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Radial)
 {
    eo_prefix: ector_renderer_software_gradient_radial;
    legacy_prefix: null;
@@ -9,6 +9,6 @@ class Ector.Renderer.Software.Gradient_Radial (Ector.Renderer.Generic.Gradient_R
       Ector.Renderer.Software.Base.fill;
       Eo.Base.constructor;
       Eo.Base.destructor;
-      Efl.Gfx.Gradient.stop.set;
+      Efl.Gfx.Gradient.Base.stop.set;
    }
 }
index 49823a1..2e4fbea 100644 (file)
@@ -30,90 +30,90 @@ typedef struct _Outline
    int contours_alloc;
 }Outline;
 
-static Outline * 
+static Outline *
 _outline_create()
 {
-  Outline *outline = (Outline *) calloc(1, sizeof(Outline));
-  
-  outline->ft_outline.points = (SW_FT_Vector *) calloc(50, sizeof(SW_FT_Vector));
-  outline->ft_outline.tags = (char *) calloc(50, sizeof(char));
+   Outline *outline = (Outline *) calloc(1, sizeof(Outline));
 
-  outline->ft_outline.contours = (short *) calloc(5, sizeof(short));
+   outline->ft_outline.points = (SW_FT_Vector *) calloc(50, sizeof(SW_FT_Vector));
+   outline->ft_outline.tags = (char *) calloc(50, sizeof(char));
 
-  outline->points_alloc = 50;
-  outline->contours_alloc = 5;  
-  return outline;
-} 
+   outline->ft_outline.contours = (short *) calloc(5, sizeof(short));
 
-static 
+   outline->points_alloc = 50;
+   outline->contours_alloc = 5;
+   return outline;
+}
+
+static
 void _outline_destroy(Outline *outline)
 {
-    if (outline)
-    {
-      free(outline->ft_outline.points);
-      free(outline->ft_outline.tags);
-      free(outline->ft_outline.contours);
-      free(outline);
-      outline = NULL;
-    }
-
+   if (outline)
+     {
+        free(outline->ft_outline.points);
+        free(outline->ft_outline.tags);
+        free(outline->ft_outline.contours);
+        free(outline);
+        outline = NULL;
+     }
 }
 
 static void
 _outline_move_to(Outline *outline, double x, double y)
 {
-  SW_FT_Outline *ft_outline = &outline->ft_outline;
-
-  if (ft_outline->n_contours == outline->contours_alloc)
-  {
-    outline->contours_alloc += 5;
-    ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short));
-  }
-  ft_outline->points[ft_outline->n_points].x = x;
-  ft_outline->points[ft_outline->n_points].y = y;
-  ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
-
-  if (ft_outline->n_points)
-  {
-     ft_outline->contours[ft_outline->n_contours] = ft_outline->n_points - 1;
-     ft_outline->n_contours++;
-  }
-
-  ft_outline->n_points++;
+   SW_FT_Outline *ft_outline = &outline->ft_outline;
+
+   if (ft_outline->n_contours == outline->contours_alloc)
+     {
+        outline->contours_alloc += 5;
+        ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short));
+     }
+   ft_outline->points[ft_outline->n_points].x = x;
+   ft_outline->points[ft_outline->n_points].y = y;
+   ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
+
+   if (ft_outline->n_points)
+     {
+        ft_outline->contours[ft_outline->n_contours] = ft_outline->n_points - 1;
+        ft_outline->n_contours++;
+     }
+
+   ft_outline->n_points++;
 }
 
 static void
 _outline_end(Outline *outline)
 {
-    SW_FT_Outline *ft_outline = &outline->ft_outline;
-    if (ft_outline->n_contours == outline->contours_alloc)
-    {
-      outline->contours_alloc += 1;
-      ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short));
-    }
-
-    if (ft_outline->n_points)
-    {
-       ft_outline->contours[ft_outline->n_contours] = ft_outline->n_points - 1;
-       ft_outline->n_contours++;
-    }
+   SW_FT_Outline *ft_outline = &outline->ft_outline;
+
+   if (ft_outline->n_contours == outline->contours_alloc)
+     {
+        outline->contours_alloc += 1;
+        ft_outline->contours = (short *) realloc(ft_outline->contours, outline->contours_alloc * sizeof(short));
+     }
+
+   if (ft_outline->n_points)
+     {
+        ft_outline->contours[ft_outline->n_contours] = ft_outline->n_points - 1;
+        ft_outline->n_contours++;
+     }
 }
 
 
 static void  _outline_line_to(Outline *outline, double x, double y)
 {
-  SW_FT_Outline *ft_outline = &outline->ft_outline;
-
-  if (ft_outline->n_points == outline->points_alloc)
-  {
-    outline->points_alloc += 50;
-    ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector));
-    ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char));
-  }
-  ft_outline->points[ft_outline->n_points].x = x;
-  ft_outline->points[ft_outline->n_points].y = y;
-  ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
-  ft_outline->n_points++;
+   SW_FT_Outline *ft_outline = &outline->ft_outline;
+
+   if (ft_outline->n_points == outline->points_alloc)
+     {
+        outline->points_alloc += 50;
+        ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector));
+        ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char));
+     }
+   ft_outline->points[ft_outline->n_points].x = x;
+   ft_outline->points[ft_outline->n_points].y = y;
+   ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
+   ft_outline->n_points++;
 }
 
 
@@ -122,19 +122,20 @@ _outline_close_path(Outline *outline)
 {
    SW_FT_Outline *ft_outline = &outline->ft_outline;
    int index ;
-   
+
    if (ft_outline->n_contours)
-   {
-      index = ft_outline->contours[ft_outline->n_contours - 1] + 1;
+     {
+        index = ft_outline->contours[ft_outline->n_contours - 1] + 1;
+     }
+   else
+     {
+        // first path
+        index = 0;
+     }
 
-   } else {
-      // first path
-      index = 0;
-   }
-   
    // make sure there is atleast one point in the current path
    if (ft_outline->n_points == index) return EINA_FALSE;
-   
+
    _outline_line_to(outline, ft_outline->points[index].x, ft_outline->points[index].y);
    return EINA_TRUE;
 }
@@ -142,54 +143,63 @@ _outline_close_path(Outline *outline)
 
 static void  _outline_cubic_to(Outline *outline, double cx1, double cy1, double cx2, double cy2, double x, double y)
 {
-  SW_FT_Outline *ft_outline = &outline->ft_outline;
-
-  if (ft_outline->n_points == outline->points_alloc)
-  {
-    outline->points_alloc += 50;
-    ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector));
-    ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char));
-  }
-
-  ft_outline->points[ft_outline->n_points].x = cx1;
-  ft_outline->points[ft_outline->n_points].y = cy1;
-  ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_CUBIC;
-  ft_outline->n_points++;
-  
-  ft_outline->points[ft_outline->n_points].x = cx2;
-  ft_outline->points[ft_outline->n_points].y = cy2;
-  ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_CUBIC;
-  ft_outline->n_points++;
-
-  ft_outline->points[ft_outline->n_points].x = x;
-  ft_outline->points[ft_outline->n_points].y = y;
-  ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
-  ft_outline->n_points++;
+   SW_FT_Outline *ft_outline = &outline->ft_outline;
+
+   if (ft_outline->n_points == outline->points_alloc)
+     {
+        outline->points_alloc += 50;
+        ft_outline->points = (SW_FT_Vector *) realloc(ft_outline->points, outline->points_alloc * sizeof(SW_FT_Vector));
+        ft_outline->tags = (char *) realloc(ft_outline->tags, outline->points_alloc * sizeof(char));
+     }
+
+   ft_outline->points[ft_outline->n_points].x = cx1;
+   ft_outline->points[ft_outline->n_points].y = cy1;
+   ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_CUBIC;
+   ft_outline->n_points++;
+
+   ft_outline->points[ft_outline->n_points].x = cx2;
+   ft_outline->points[ft_outline->n_points].y = cy2;
+   ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_CUBIC;
+   ft_outline->n_points++;
+
+   ft_outline->points[ft_outline->n_points].x = x;
+   ft_outline->points[ft_outline->n_points].y = y;
+   ft_outline->tags[ft_outline->n_points] = SW_FT_CURVE_TAG_ON;
+   ft_outline->n_points++;
 }
 
 static void _outline_transform(Outline *outline, Eina_Matrix3 *m)
 {
-    int i;
-    SW_FT_Outline *ft_outline = &outline->ft_outline;
-    if(m) {
+   int i;
+   SW_FT_Outline *ft_outline = &outline->ft_outline;
+
+   if (m)
+     {
         double x, y;
-        for(i = 0; i < ft_outline->n_points ; i++) {
-            eina_matrix3_point_transform(m, ft_outline->points[i].x, ft_outline->points[i].y, &x, &y);
-            ft_outline->points[i].x = (int)(x * 64);// to freetype 26.6 coordinate.
-            ft_outline->points[i].y = (int)(y * 64);
-        }
-    } else {
-        for(i = 0; i < ft_outline->n_points ; i++) {
-            ft_outline->points[i].x = ft_outline->points[i].x <<6;// to freetype 26.6 coordinate.
-            ft_outline->points[i].y = ft_outline->points[i].y <<6;
-        }
-    }  
+        for (i = 0; i < ft_outline->n_points; i++)
+          {
+             eina_matrix3_point_transform(m, ft_outline->points[i].x, ft_outline->points[i].y, &x, &y);
+             ft_outline->points[i].x = (int)(x * 64);// to freetype 26.6 coordinate.
+             ft_outline->points[i].y = (int)(y * 64);
+          }
+     }
+   else
+     {
+        for (i = 0; i < ft_outline->n_points; i++)
+          {
+             ft_outline->points[i].x = ft_outline->points[i].x <<6;// to freetype 26.6 coordinate.
+             ft_outline->points[i].y = ft_outline->points[i].y <<6;
+          }
+     }
 }
 
 
 static Eina_Bool
 _ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_Software_Shape_Data *pd)
 {
+   const Efl_Gfx_Path_Command *cmds = NULL;
+   const double *pts = NULL;
+
    // FIXME: shouldn't that be part of the shape generic implementation ?
    if (pd->shape->fill)
      eo_do(pd->shape->fill, ector_renderer_prepare());
@@ -208,17 +218,15 @@ _ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj, Ecto
         if (!pd->surface) return EINA_FALSE;
      }
 
-   if (!pd->shape_data && pd->shape->path.cmd)
+   eo_do(obj, efl_gfx_shape_path_get(&cmds, &pts));
+   if (!pd->shape_data && cmds)
      {
-        double *pts;
-        unsigned int i;
         Eina_Bool close_path = EINA_FALSE;
         Outline * outline = _outline_create();
 
-        pts = pd->shape->path.pts;
-        for (i = 0; pd->shape->path.cmd[i] != EFL_GFX_PATH_COMMAND_TYPE_END; i++)
+        for (; *cmds != EFL_GFX_PATH_COMMAND_TYPE_END; cmds++)
           {
-             switch (pd->shape->path.cmd[i])
+             switch (*cmds)
                {
                 case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
 
@@ -238,8 +246,8 @@ _ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj, Ecto
                    // cairo, first is destination point, followed by
                    // the control point. The opposite of cairo.
                    _outline_cubic_to(outline,
-                                  pts[2], pts[3], pts[4], pts[5], // control points
-                                  pts[0], pts[1]); // destination point
+                                     pts[2], pts[3], pts[4], pts[5], // control points
+                                     pts[0], pts[1]); // destination point
                    pts += 6;
                    break;
 
@@ -253,54 +261,68 @@ _ector_renderer_software_shape_ector_renderer_generic_base_prepare(Eo *obj, Ecto
                    break;
                }
           }
-          _outline_end(outline);
-          _outline_transform(outline, pd->base->m);
-          // generate the shape data.
-          pd->shape_data = ector_software_rasterizer_generate_rle_data(pd->surface->software, &outline->ft_outline);
-          if (!pd->outline_data) {
+
+        _outline_end(outline);
+        _outline_transform(outline, pd->base->m);
+
+        // generate the shape data.
+        pd->shape_data = ector_software_rasterizer_generate_rle_data(pd->surface->software, &outline->ft_outline);
+        if (!pd->outline_data)
+          {
              ector_software_rasterizer_stroke_set(pd->surface->software, (pd->shape->stroke.width * pd->shape->stroke.scale), pd->shape->stroke.cap,
                                                   pd->shape->stroke.join);
              pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(pd->surface->software, &outline->ft_outline, close_path);
           }
 
-          _outline_destroy(outline);
-    }  
+        _outline_destroy(outline);
+     }
 
    return EINA_TRUE;
 }
 
 static Eina_Bool
-_ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Shape_Data *pd, Ector_Rop op, Eina_Array *clips, int x, int y, unsigned int mul_col)
+_ector_renderer_software_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Shape_Data *pd, Ector_Rop op, Eina_Array *clips, unsigned int mul_col)
 {
+   int x, y;
+
    // adjust the offset
-   x = x + (int)pd->base->origin.x;
-   y = y + (int)pd->base->origin.y;
+   x = pd->surface->x + (int)pd->base->origin.x;
+   y = pd->surface->y + (int)pd->base->origin.y;
 
    // fill the span_data structure
    ector_software_rasterizer_clip_rect_set(pd->surface->software, clips);
    ector_software_rasterizer_transform_set(pd->surface->software, pd->base->m);
 
-   if (pd->shape->fill) {
-     eo_do(pd->shape->fill, ector_renderer_software_base_fill());
-     ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data);
-   } else {
-      if (pd->base->color.a > 0) {
-          ector_software_rasterizer_color_set(pd->surface->software, pd->base->color.r, pd->base->color.g, pd->base->color.b, pd->base->color.a);
-          ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data);
-      }
-   }
-
-  if (pd->shape->stroke.fill) {
-    eo_do(pd->shape->stroke.fill, ector_renderer_software_base_fill());
-    ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data);
-  } else {
-    if (pd->shape->stroke.color.a > 0) {
-      ector_software_rasterizer_color_set(pd->surface->software, pd->shape->stroke.color.r, pd->shape->stroke.color.g, 
-                                          pd->shape->stroke.color.b, pd->shape->stroke.color.a);
-      ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data);
-    }
-
-  }
+   if (pd->shape->fill)
+     {
+        eo_do(pd->shape->fill, ector_renderer_software_base_fill());
+        ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data);
+     }
+   else
+     {
+        if (pd->base->color.a > 0)
+          {
+             ector_software_rasterizer_color_set(pd->surface->software, pd->base->color.r, pd->base->color.g, pd->base->color.b, pd->base->color.a);
+             ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->shape_data);
+          }
+     }
+
+   if (pd->shape->stroke.fill)
+     {
+        eo_do(pd->shape->stroke.fill, ector_renderer_software_base_fill());
+        ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data);
+     }
+   else
+     {
+        if (pd->shape->stroke.color.a > 0)
+          {
+             ector_software_rasterizer_color_set(pd->surface->software,
+                                                 pd->shape->stroke.color.r, pd->shape->stroke.color.g,
+                                                 pd->shape->stroke.color.b, pd->shape->stroke.color.a);
+             ector_software_rasterizer_draw_rle_data(pd->surface->software, x, y, mul_col, op, pd->outline_data);
+          }
+     }
+
    return EINA_TRUE;
 }
 
@@ -309,15 +331,15 @@ _ector_renderer_software_shape_ector_renderer_software_base_fill(Eo *obj EINA_UN
 {
    // FIXME: let's find out how to fill a shape with a shape later.
    // I need to read SVG specification and see how to map that with software.
-  return EINA_FALSE;
+   return EINA_FALSE;
 }
 
 static void
 _ector_renderer_software_shape_efl_gfx_shape_path_set(Eo *obj, Ector_Renderer_Software_Shape_Data *pd,
                                                       const Efl_Gfx_Path_Command *op, const double *points)
 {
-   if(pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
-   if(pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
+   if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
+   if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
    pd->shape_data = NULL;
    pd->outline_data = NULL;
 
@@ -325,12 +347,29 @@ _ector_renderer_software_shape_efl_gfx_shape_path_set(Eo *obj, Ector_Renderer_So
 }
 
 
+static Eina_Bool
+_ector_renderer_software_shape_path_changed(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED,
+                                            void *event_info EINA_UNUSED)
+{
+   Ector_Renderer_Software_Shape_Data *pd = data;
+   
+   if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
+   if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
+   
+   pd->shape_data = NULL;
+   pd->outline_data = NULL;
+
+   return EINA_TRUE;
+}
+
 void
 _ector_renderer_software_shape_eo_base_constructor(Eo *obj, Ector_Renderer_Software_Shape_Data *pd)
 {
    eo_do_super(obj, ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS, eo_constructor());
-   pd->shape = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_SHAPE_CLASS, obj);
+   pd->shape = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_SHAPE_MIXIN, obj);
    pd->base = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj);
+   eo_do(obj,
+         eo_event_callback_add(EFL_GFX_PATH_CHANGED, _ector_renderer_software_shape_path_changed, pd));
 }
 
 void
@@ -338,8 +377,8 @@ _ector_renderer_software_shape_eo_base_destructor(Eo *obj, Ector_Renderer_Softwa
 {
    Eo *parent;
 
-   if(pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
-   if(pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
+   if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
+   if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
 
    eo_do(obj, parent = eo_parent_get());
    eo_data_xunref(parent, pd->surface, obj);
index d5216ba..267ef7c 100644 (file)
@@ -1,4 +1,4 @@
-class Ector.Renderer.Software.Shape (Ector.Renderer.Generic.Shape, Ector.Renderer.Software.Base)
+class Ector.Renderer.Software.Shape (Ector.Renderer.Software.Base, Ector.Renderer.Generic.Shape)
 {
    eo_prefix: ector_renderer_software_shape;
    legacy_prefix: null;
index bf2f8be..028fb9c 100644 (file)
+#include <assert.h>
+#include <math.h>
 
 #include <software/Ector_Software.h>
+
 #include "ector_private.h"
 #include "ector_software_private.h"
-#include "ector_blend_private.h"
+#include "ector_drawhelper_private.h"
 
-//Remove
-#include <assert.h>
-#include  <math.h>
 
 #define GRADIENT_STOPTABLE_SIZE 1024
 #define FIXPT_BITS 8
 #define FIXPT_SIZE (1<<FIXPT_BITS)
 
+typedef void (*Radial_Helper_Func)(uint *buffer, int length, Ector_Renderer_Software_Gradient_Data *g_data,
+                                   float det, float delta_det, float delta_delta_det, float b, float delta_b);
+
+typedef void (*Linear_Helper_Func)(uint *buffer, int length, Ector_Renderer_Software_Gradient_Data *g_data,
+                                   int t_fixed, int inc_fixed);
 
-static inline int _gradient_clamp(const Ector_Renderer_Software_Gradient_Data *data, int ipos)
+Radial_Helper_Func radial_helper;
+Linear_Helper_Func linear_helper;
+
+static inline int
+_gradient_clamp(const Ector_Renderer_Software_Gradient_Data *data, int ipos)
 {
-    if (data->gd->s == EFL_GFX_GRADIENT_SPREAD_REPEAT) {
+   if (data->gd->s == EFL_GFX_GRADIENT_SPREAD_REPEAT)
+     {
         ipos = ipos % GRADIENT_STOPTABLE_SIZE;
         ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos;
-    } else if (data->gd->s == EFL_GFX_GRADIENT_SPREAD_REFLECT) {
+     }
+   else if (data->gd->s == EFL_GFX_GRADIENT_SPREAD_REFLECT)
+     {
         const int limit = GRADIENT_STOPTABLE_SIZE * 2;
         ipos = ipos % limit;
         ipos = ipos < 0 ? limit + ipos : ipos;
         ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - 1 - ipos : ipos;
-    }else {
-        if (ipos < 0)
-            ipos = 0;
+     }
+   else
+     {
+        if (ipos < 0) ipos = 0;
         else if (ipos >= GRADIENT_STOPTABLE_SIZE)
-            ipos = GRADIENT_STOPTABLE_SIZE-1;
-    }
-    
-    return ipos;
+          ipos = GRADIENT_STOPTABLE_SIZE-1;
+     }
+   return ipos;
 }
 
 
-static uint _gradient_pixel_fixed(const Ector_Renderer_Software_Gradient_Data *data, int fixed_pos)
+static uint
+_gradient_pixel_fixed(const Ector_Renderer_Software_Gradient_Data *data, int fixed_pos)
 {
-    int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS;
-    return data->colorTable[_gradient_clamp(data, ipos)];
+   int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS;
+   return data->color_table[_gradient_clamp(data, ipos)];
 }
 
-static inline uint _gradient_pixel(const Ector_Renderer_Software_Gradient_Data *data, float pos)
- {
-     int ipos = (int)(pos * (GRADIENT_STOPTABLE_SIZE - 1) + (float)(0.5));
-     return data->colorTable[_gradient_clamp(data, ipos)];
- }
+static inline uint
+_gradient_pixel(const Ector_Renderer_Software_Gradient_Data *data, float pos)
+{
+   int ipos = (int)(pos * (GRADIENT_STOPTABLE_SIZE - 1) + (float)(0.5));
+   return data->color_table[_gradient_clamp(data, ipos)];
+}
 
 
-typedef double (*BLEND_FUNC)(double progress);
+#ifdef BUILD_SSE3
+#include <immintrin.h>
+
+#define GRADIENT_STOPTABLE_SIZE_SHIFT 10
+typedef union{ __m128i v; int i[4];}vec4_i;
+typedef union{ __m128 v; float f[4];}vec4_f;
+
+#define FETCH_CLAMP_INIT_F \
+  __m128 v_min = _mm_set1_ps(0.0f); \
+  __m128 v_max = _mm_set1_ps((float)(GRADIENT_STOPTABLE_SIZE-1)); \
+  __m128 v_halff = _mm_set1_ps(0.5f); \
+  __m128i v_repeat_mask = _mm_set1_epi32(~((uint)(0xffffff) << GRADIENT_STOPTABLE_SIZE_SHIFT)); \
+  __m128i v_reflect_mask = _mm_set1_epi32(~((uint)(0xffffff) << (GRADIENT_STOPTABLE_SIZE_SHIFT+1))); \
+  __m128i v_reflect_limit = _mm_set1_epi32(2 * GRADIENT_STOPTABLE_SIZE - 1);
+
+#define FETCH_CLAMP_REPEAT_F \
+  vec4_i index_vec; \
+  index_vec.v = _mm_and_si128(v_repeat_mask, _mm_cvttps_epi32(v_index));
+
+#define FETCH_CLAMP_REFLECT_F \
+  vec4_i index_vec; \
+  __m128i v_index_i = _mm_and_si128(v_reflect_mask, _mm_cvttps_epi32(v_index)); \
+  __m128i v_index_i_inv = _mm_sub_epi32(v_reflect_limit, v_index_i); \
+  index_vec.v = _mm_min_epi16(v_index_i, v_index_i_inv);
+
+#define FETCH_CLAMP_PAD_F \
+  vec4_i index_vec; \
+  index_vec.v = _mm_cvttps_epi32(_mm_min_ps(v_max, _mm_max_ps(v_min, v_index)));
+
 
-static double _ease_linear(double t)
+#define FETCH_EPILOGUE_CPY \
+  *buffer++ = g_data->color_table[index_vec.i[0]]; \
+  *buffer++ = g_data->color_table[index_vec.i[1]]; \
+  *buffer++ = g_data->color_table[index_vec.i[2]]; \
+  *buffer++ = g_data->color_table[index_vec.i[3]]; \
+}
+
+static void 
+loop_break(unsigned int *buffer, int length, int *lprealign, int *lby4 , int *lremaining)
+{
+   int l1=0,l2=0,l3=0;
+   while ((int)buffer & 0xF)
+     buffer++ , l1++;
+
+   if(length <= l1)
+     l1 = length;
+   else
+     {
+        l3 = (length - l1)%4;
+        l2 = length - l1 - l3 ;
+     }
+   *lprealign = l1;
+   *lby4 = l2;
+   *lremaining = l3;
+}
+
+static void 
+_radial_helper_sse3(uint *buffer, int length, Ector_Renderer_Software_Gradient_Data *g_data,
+                    float det, float delta_det, float delta_delta_det, float b, float delta_b)
 {
-    return t;
+   int lprealign, lby4, lremaining;
+   loop_break(buffer, length, &lprealign, &lby4, &lremaining);
+   // prealign loop
+   for (int i = 0 ; i < lprealign ; i++)
+     {
+        *buffer++ = _gradient_pixel(g_data, sqrt(det) - b);
+        det += delta_det;
+        delta_det += delta_delta_det;
+        b += delta_b;
+     }
+
+   // lby4 16byte align loop
+   vec4_f det_vec;
+   vec4_f delta_det4_vec;
+   vec4_f b_vec;
+
+   for (int i = 0; i < 4; ++i)
+     {
+        det_vec.f[i] = det;
+        delta_det4_vec.f[i] = 4 * delta_det;
+        b_vec.f[i] = b;
+
+        det += delta_det;
+        delta_det += delta_delta_det;
+        b += delta_b;
+     }
+
+   __m128 v_delta_delta_det16 = _mm_set1_ps(16 * delta_delta_det);
+   __m128 v_delta_delta_det6 = _mm_set1_ps(6 * delta_delta_det);
+   __m128 v_delta_b4 = _mm_set1_ps(4 * delta_b);
+
+#define FETCH_RADIAL_PROLOGUE \
+  for (int i = 0 ; i < lby4 ; i+=4) { \
+    __m128 v_index_local = _mm_sub_ps(_mm_sqrt_ps(det_vec.v), b_vec.v); \
+    __m128 v_index = _mm_add_ps(_mm_mul_ps(v_index_local, v_max), v_halff); \
+    det_vec.v = _mm_add_ps(_mm_add_ps(det_vec.v, delta_det4_vec.v), v_delta_delta_det6); \
+    delta_det4_vec.v = _mm_add_ps(delta_det4_vec.v, v_delta_delta_det16); \
+    b_vec.v = _mm_add_ps(b_vec.v, v_delta_b4);
+
+
+#define FETCH_RADIAL_LOOP(FETCH_CLAMP) \
+  FETCH_RADIAL_PROLOGUE \
+  FETCH_CLAMP \
+  FETCH_EPILOGUE_CPY
+
+  FETCH_CLAMP_INIT_F
+  switch (g_data->gd->s)
+  {
+    case EFL_GFX_GRADIENT_SPREAD_REPEAT:
+      FETCH_RADIAL_LOOP(FETCH_CLAMP_REPEAT_F)
+      break;
+    case EFL_GFX_GRADIENT_SPREAD_REFLECT:
+      FETCH_RADIAL_LOOP( FETCH_CLAMP_REFLECT_F)
+      break;
+    default:
+      FETCH_RADIAL_LOOP(FETCH_CLAMP_PAD_F)
+      break;
+  }
+
+   // remaining loop
+   for (int i = 0 ; i < lremaining ; i++)
+     *buffer++ = _gradient_pixel(g_data, sqrt(det_vec.f[i]) - b_vec.f[i]);
 }
 
 static void
-_generate_gradient_color_table(Efl_Gfx_Gradient_Stop *gradient_stops, int stop_count, uint *colorTable, int size)
+_linear_helper_sse3(uint *buffer, int length, Ector_Renderer_Software_Gradient_Data *g_data, int t, int inc)
 {
-    int pos = 0;
-    Efl_Gfx_Gradient_Stop *curr, *next;
-    assert(stop_count > 0);
+   int lprealign, lby4, lremaining;
+   loop_break(buffer, length, &lprealign, &lby4, &lremaining); 
+   // prealign loop
+   for (int i = 0 ; i < lprealign ; i++)
+     {
+        *buffer++ = _gradient_pixel_fixed(g_data, t);
+        t += inc;
+     }
+
+   // lby4 16byte align loop
+   vec4_i t_vec;
+   for (int i = 0; i < 4; ++i)
+     {
+        t_vec.i[i] = t;
+        t += inc;
+     }
+
+   __m128i v_inc = _mm_set1_epi32(4 * inc);
+   __m128i v_fxtpt_size = _mm_set1_epi32(FIXPT_SIZE * 0.5);
+
+   __m128i v_min = _mm_set1_epi32(0);
+   __m128i v_max = _mm_set1_epi32((GRADIENT_STOPTABLE_SIZE-1));
+
+   __m128i v_repeat_mask = _mm_set1_epi32(~((uint)(0xffffff) << GRADIENT_STOPTABLE_SIZE_SHIFT));
+   __m128i v_reflect_mask = _mm_set1_epi32(~((uint)(0xffffff) << (GRADIENT_STOPTABLE_SIZE_SHIFT+1)));
+
+   __m128i v_reflect_limit = _mm_set1_epi32(2 * GRADIENT_STOPTABLE_SIZE - 1);
+
+#define FETCH_LINEAR_LOOP_PROLOGUE \
+  for (int i = 0 ; i < lby4 ; i+=4) { \
+    vec4_i index_vec;\
+    __m128i v_index;\
+    v_index =  _mm_srai_epi32(_mm_add_epi32(t_vec.v, v_fxtpt_size), FIXPT_BITS); \
+    t_vec.v = _mm_add_epi32(t_vec.v, v_inc);
+
+#define FETCH_LINEAR_LOOP_CLAMP_REPEAT \
+  index_vec.v = _mm_and_si128(v_repeat_mask, v_index);
+
+#define FETCH_LINEAR_LOOP_CLAMP_REFLECT \
+  __m128i v_index_i = _mm_and_si128(v_reflect_mask, v_index); \
+  __m128i v_index_i_inv = _mm_sub_epi32(v_reflect_limit, v_index_i); \
+  index_vec.v = _mm_min_epi16(v_index_i, v_index_i_inv);
+
+#define FETCH_LINEAR_LOOP_CLAMP_PAD \
+  index_vec.v = _mm_min_epi16(v_max, _mm_max_epi16(v_min, v_index));
+
+
+
+#define FETCH_LINEAR_LOOP(FETCH_LINEAR_LOOP_CLAMP) \
+  FETCH_LINEAR_LOOP_PROLOGUE \
+  FETCH_LINEAR_LOOP_CLAMP \
+  FETCH_EPILOGUE_CPY
+
+  switch (g_data->gd->s)
+    {
+      case EFL_GFX_GRADIENT_SPREAD_REPEAT:
+        FETCH_LINEAR_LOOP(FETCH_LINEAR_LOOP_CLAMP_REPEAT)
+        break;
+      case EFL_GFX_GRADIENT_SPREAD_REFLECT:
+        FETCH_LINEAR_LOOP(FETCH_LINEAR_LOOP_CLAMP_REFLECT)
+        break;
+      default:
+        FETCH_LINEAR_LOOP(FETCH_LINEAR_LOOP_CLAMP_PAD)
+        break;
+    }
+
+   // remaining loop
+   for (int i = 0 ; i < lremaining ; i++)
+     *buffer++ = _gradient_pixel_fixed(g_data, t_vec.i[i]);
+}
+
+#endif
 
-    curr = gradient_stops;
-    uint current_color = ECTOR_ARGB_JOIN(curr->a, curr->r, curr->g, curr->b);
-    double incr = 1.0 / (double)size;
-    double fpos = 1.5 * incr;
-    current_color = _ector_premultiply(current_color);
+typedef double (*BLEND_FUNC)(double progress);
 
-    colorTable[pos++] = current_color;
+static double
+_ease_linear(double t)
+{
+   return t;
+}
 
-    while (fpos <= curr->offset) {
-        colorTable[pos] = colorTable[pos - 1];
+static Eina_Bool
+_generate_gradient_color_table(Efl_Gfx_Gradient_Stop *gradient_stops, int stop_count, uint *color_table, int size)
+{
+   int pos = 0;
+   Eina_Bool alpha = EINA_FALSE;
+   Efl_Gfx_Gradient_Stop *curr, *next;
+   assert(stop_count > 0);
+
+   curr = gradient_stops;
+   if (curr->a != 255) alpha = EINA_TRUE;
+   uint current_color = ECTOR_ARGB_JOIN(curr->a, curr->r, curr->g, curr->b);
+   double incr = 1.0 / (double)size;
+   double fpos = 1.5 * incr;
+
+   color_table[pos++] = current_color;
+
+   while (fpos <= curr->offset)
+     {
+        color_table[pos] = color_table[pos - 1];
         pos++;
         fpos += incr;
-    }
+     }
 
-    for (int i = 0; i < stop_count - 1; ++i) {
+   for (int i = 0; i < stop_count - 1; ++i)
+     {
         curr = (gradient_stops + i);
         next = (gradient_stops + i + 1);
         double delta = 1/(next->offset - curr->offset);
+        if (next->a != 255) alpha = EINA_TRUE;
         uint next_color = ECTOR_ARGB_JOIN(next->a, next->r, next->g, next->b);
-        next_color = _ector_premultiply(next_color);
         BLEND_FUNC func = &_ease_linear;
-        while (fpos < next->offset && pos < size) {
-            double t = func((fpos - curr->offset) * delta);
-            int dist = (int)(256 * t);
-            int idist = 256 - dist;
-            colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
-            ++pos;
-            fpos += incr;
-        }
+        while (fpos < next->offset && pos < size)
+          {
+             double t = func((fpos - curr->offset) * delta);
+             int dist = (int)(256 * t);
+             int idist = 256 - dist;
+             color_table[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
+             ++pos;
+             fpos += incr;
+          }
         current_color = next_color;
-    }
+     }
 
-    uint last_color = _ector_premultiply(current_color);
-    for (;pos < size; ++pos)
-        colorTable[pos] = last_color;
+   for (;pos < size; ++pos)
+     color_table[pos] = current_color;
 
-    // Make sure the last color stop is represented at the end of the table
-    colorTable[size-1] = last_color;
+   // Make sure the last color stop is represented at the end of the table
+   color_table[size-1] = current_color;
+   return alpha;
 }
 
 
-void 
+void
 update_color_table(Ector_Renderer_Software_Gradient_Data *gdata)
 {
-    if(gdata->colorTable) return;
+   if (gdata->color_table) return;
 
-    gdata->colorTable = malloc(GRADIENT_STOPTABLE_SIZE * 4);
-    _generate_gradient_color_table(gdata->gd->colors, gdata->gd->colors_count, gdata->colorTable, GRADIENT_STOPTABLE_SIZE);
+   gdata->color_table = malloc(GRADIENT_STOPTABLE_SIZE * 4);
+   gdata->alpha = _generate_gradient_color_table(gdata->gd->colors, gdata->gd->colors_count, gdata->color_table, GRADIENT_STOPTABLE_SIZE);
 }
 
-void 
+void
 destroy_color_table(Ector_Renderer_Software_Gradient_Data *gdata)
 {
-    if (gdata->colorTable) {
-        free(gdata->colorTable);
-        gdata->colorTable = NULL;
-    }
+   if (gdata->color_table)
+     {
+        free(gdata->color_table);
+        gdata->color_table = NULL;
+     }
 }
 
+inline static void
+_linear_helper_generic(uint *buffer, int length, Ector_Renderer_Software_Gradient_Data *g_data,
+                       int t_fixed, int inc_fixed)
+{
+   for (int i = 0 ; i < length ; i++)
+     {
+        *buffer++ = _gradient_pixel_fixed(g_data, t_fixed);
+        t_fixed += inc_fixed;
+     }
+}
 
 void
 fetch_linear_gradient(uint *buffer, Span_Data *data, int y, int x, int length)
 {
-    Ector_Renderer_Software_Gradient_Data *g_data = data->gradient;
-    float t, inc;
-    float rx=0, ry=0;
-    if (g_data->linear.l == 0) {
+   Ector_Renderer_Software_Gradient_Data *g_data = data->gradient;
+   float t, inc;
+   float rx=0, ry=0;
+
+   if (g_data->linear.l == 0)
+     {
         t = inc = 0;
-    } else {
+     }
+   else
+     {
         rx = data->inv.xy * (y + (float)0.5) + data->inv.xz + data->inv.xx * (x + (float)0.5);
         ry = data->inv.yy * (y + (float)0.5) + data->inv.yz + data->inv.yx * (x + (float)0.5);
         t = g_data->linear.dx*rx + g_data->linear.dy*ry + g_data->linear.off;
@@ -137,100 +371,108 @@ fetch_linear_gradient(uint *buffer, Span_Data *data, int y, int x, int length)
 
         t *= (GRADIENT_STOPTABLE_SIZE - 1);
         inc *= (GRADIENT_STOPTABLE_SIZE - 1);
-    }
-
-    uint *end = buffer + length;
-    if (inc > (float)(-1e-5) && inc < (float)(1e-5)) {
-        _ector_memfill(buffer, _gradient_pixel_fixed(g_data, (int)(t * FIXPT_SIZE)), length);
-    } else {
-        if (t + inc*length < (float)(INT_MAX >> (FIXPT_BITS + 1)) &&
-            t+inc*length > (float)(INT_MIN >> (FIXPT_BITS + 1))) {
-            // we can use fixed point math
-            int t_fixed = (int)(t * FIXPT_SIZE);
-            int inc_fixed = (int)(inc * FIXPT_SIZE);
-            // #ifdef BUILD_SSE3
-            // if (evas_common_cpu_has_feature(CPU_FEATURE_SSE3)) {
-            //     _fetch_linear_sse3(buffer, length, g_data, t_fixed, inc_fixed);
-            // } else
-            // #endif
-            {
-                while (buffer < end) {
-                   *buffer++ = _gradient_pixel_fixed(g_data, t_fixed);
-                   t_fixed += inc_fixed;
+     }
+
+   uint *end = buffer + length;
+    if (inc > (float)(-1e-5) && inc < (float)(1e-5))
+      {
+         _ector_memfill(buffer, length, _gradient_pixel_fixed(g_data, (int)(t * FIXPT_SIZE)));
+      }
+    else
+      {
+         if (t + inc*length < (float)(INT_MAX >> (FIXPT_BITS + 1)) &&
+             t+inc*length > (float)(INT_MIN >> (FIXPT_BITS + 1)))
+           {
+              // we can use fixed point math
+              int t_fixed = (int)(t * FIXPT_SIZE);
+              int inc_fixed = (int)(inc * FIXPT_SIZE);
+              linear_helper(buffer, length, g_data, t_fixed, inc_fixed);
+           }
+         else
+           {
+              // we have to fall back to float math
+              while (buffer < end)
+                {
+                   *buffer++ = _gradient_pixel(g_data, t/GRADIENT_STOPTABLE_SIZE);
+                   t += inc;
                 }
-            }
-        } else {
-            // we have to fall back to float math
-            while (buffer < end) {
-                *buffer++ = _gradient_pixel(g_data, t/GRADIENT_STOPTABLE_SIZE);
-                t += inc;
-            }
-        }
-    }
+           }
+      }
 }
 
 
-static void
+
+inline static void
 _radial_helper_generic(uint *buffer, int length, Ector_Renderer_Software_Gradient_Data *g_data, float det,
-      float delta_det, float delta_delta_det, float b, float delta_b)
+                       float delta_det, float delta_delta_det, float b, float delta_b)
 {
-    for (int i = 0 ; i < length ; i++) {
+   for (int i = 0 ; i < length ; i++)
+     {
         *buffer++ = _gradient_pixel(g_data, sqrt(det) - b);
         det += delta_det;
         delta_det += delta_delta_det;
         b += delta_b;
-    }
+     }
 }
 
 void
 fetch_radial_gradient(uint *buffer, Span_Data *data, int y, int x, int length)
 {
-    Ector_Renderer_Software_Gradient_Data *g_data = data->gradient;
-    // avoid division by zero
-    if (abs(g_data->radial.a) <= 0.00001f) {
-        _ector_memfill(buffer, 0, length);
+   Ector_Renderer_Software_Gradient_Data *g_data = data->gradient;
+
+   // avoid division by zero
+   if (abs(g_data->radial.a) <= 0.00001f)
+     {
+        _ector_memfill(buffer, length, 0);
         return;
-    }
+     }
 
-    float rx = data->inv.xy * (y + (float)0.5) + data->inv.xz + data->inv.xx * (x + (float)0.5);
-    float ry = data->inv.yy * (y + (float)0.5) + data->inv.yz + data->inv.yx * (x + (float)0.5);
+   float rx = data->inv.xy * (y + (float)0.5) + data->inv.xz + data->inv.xx * (x + (float)0.5);
+   float ry = data->inv.yy * (y + (float)0.5) + data->inv.yz + data->inv.yx * (x + (float)0.5);
 
-    rx -= g_data->radial.fx;
-    ry -= g_data->radial.fy;
+   rx -= g_data->radial.fx;
+   ry -= g_data->radial.fy;
 
-    float inv_a = 1 / (float)(2 * g_data->radial.a);
+   float inv_a = 1 / (float)(2 * g_data->radial.a);
 
-    const float delta_rx = data->inv.xx;
-    const float delta_ry = data->inv.yx;
+   const float delta_rx = data->inv.xx;
+   const float delta_ry = data->inv.yx;
 
-    float b = 2*(g_data->radial.dr*g_data->radial.fradius + rx * g_data->radial.dx + ry * g_data->radial.dy);
-    float delta_b = 2*(delta_rx * g_data->radial.dx + delta_ry * g_data->radial.dy);
-    const float b_delta_b = 2 * b * delta_b;
-    const float delta_b_delta_b = 2 * delta_b * delta_b;
+   float b = 2*(g_data->radial.dr*g_data->radial.fradius + rx * g_data->radial.dx + ry * g_data->radial.dy);
+   float delta_b = 2*(delta_rx * g_data->radial.dx + delta_ry * g_data->radial.dy);
+   const float b_delta_b = 2 * b * delta_b;
+   const float delta_b_delta_b = 2 * delta_b * delta_b;
 
-    const float bb = b * b;
-    const float delta_bb = delta_b * delta_b;
-    b *= inv_a;
-    delta_b *= inv_a;
+   const float bb = b * b;
+   const float delta_bb = delta_b * delta_b;
+   b *= inv_a;
+   delta_b *= inv_a;
 
-    const float rxrxryry = rx * rx + ry * ry;
-    const float delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry;
-    const float rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry);
-    const float delta_rx_plus_ry = 2 * delta_rxrxryry;
+   const float rxrxryry = rx * rx + ry * ry;
+   const float delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry;
+   const float rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry);
+   const float delta_rx_plus_ry = 2 * delta_rxrxryry;
 
-    inv_a *= inv_a;
+   inv_a *= inv_a;
 
-    float det = (bb - 4 * g_data->radial.a * (g_data->radial.sqrfr - rxrxryry)) * inv_a;
-    float delta_det = (b_delta_b + delta_bb + 4 * g_data->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a;
-    const float delta_delta_det = (delta_b_delta_b + 4 * g_data->radial.a * delta_rx_plus_ry) * inv_a;
+   float det = (bb - 4 * g_data->radial.a * (g_data->radial.sqrfr - rxrxryry)) * inv_a;
+   float delta_det = (b_delta_b + delta_bb + 4 * g_data->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a;
+   const float delta_delta_det = (delta_b_delta_b + 4 * g_data->radial.a * delta_rx_plus_ry) * inv_a;
 
- // #ifdef BUILD_SSE3
- //    if (evas_common_cpu_has_feature(CPU_FEATURE_SSE3)) {
- //        _radial_helper_sse3(buffer, length, g_data, det, delta_det, delta_delta_det, b, delta_b);
- //    } else
- // #endif
-    { // generic fallback
-        _radial_helper_generic(buffer, length, g_data, det, delta_det, delta_delta_det, b, delta_b);
-    }
+   radial_helper(buffer, length, g_data, det, delta_det, delta_delta_det, b, delta_b);
+}
 
+
+void
+init_drawhelper_gradient()
+{
+   radial_helper = _radial_helper_generic;
+   linear_helper = _linear_helper_generic;
+   #ifdef BUILD_SSE3
+   if (eina_cpu_features_get() & EINA_CPU_SSE3)
+     {
+        radial_helper = _radial_helper_sse3;
+        linear_helper = _linear_helper_sse3;
+     }
+   #endif
 }
index ef979a0..9e30a31 100644 (file)
 #ifndef ECTOR_SOFTWARE_PRIVATE_H_
 # define ECTOR_SOFTWARE_PRIVATE_H_
 
-
 #include "sw_ft_raster.h"
 #include "sw_ft_stroker.h"
 
 #ifndef DATA32
 typedef unsigned int DATA32;
-#endif 
+#endif
+
 #ifndef uint
 typedef unsigned int uint;
 #endif
-       
 
 typedef struct _Ector_Software_Surface_Data Ector_Software_Surface_Data;
 
-#define CHECK_SOFTWARE(Parent) (!(Parent && Parent->software))
-
-
 // Gradient related structure
+typedef struct _Software_Gradient_Linear_Data
+{
+   float x1, y1, x2, y2;
+   float dx, dy, l, off;
+} Software_Gradient_Linear_Data;
 
- typedef struct _Software_Gradient_Linear_Data
- {
-     float x1, y1, x2, y2;
-     float dx, dy, l, off;
- }Software_Gradient_Linear_Data;
-
-
- typedef struct _Software_Gradient_Radial_Data
- {
-     float cx, cy, fx, fy, cradius, fradius;
-     float dx, dy, dr, sqrfr, a, inv2a;
-     Eina_Bool extended;
- }Software_Gradient_Radial_Data;
+typedef struct _Software_Gradient_Radial_Data
+{
+   float cx, cy, fx, fy, cradius, fradius;
+   float dx, dy, dr, sqrfr, a, inv2a;
+   Eina_Bool extended;
+} Software_Gradient_Radial_Data;
 
 typedef struct _Ector_Renderer_Software_Gradient_Data
 {
-    Ector_Software_Surface_Data *surface;
-       Ector_Renderer_Generic_Gradient_Data *gd;
-    union {
-        Ector_Renderer_Generic_Gradient_Linear_Data *gld;
-        Ector_Renderer_Generic_Gradient_Radial_Data *grd;
-    };
-    union {
-        Software_Gradient_Linear_Data linear;
-        Software_Gradient_Radial_Data radial;
-    };
-    uint* colorTable;
-}Ector_Renderer_Software_Gradient_Data;
-
+   Ector_Software_Surface_Data *surface;
+   Ector_Renderer_Generic_Gradient_Data *gd;
+   union {
+      Ector_Renderer_Generic_Gradient_Linear_Data *gld;
+      Ector_Renderer_Generic_Gradient_Radial_Data *grd;
+   };
+   union {
+      Software_Gradient_Linear_Data linear;
+      Software_Gradient_Radial_Data radial;
+   };
+   Eina_Bool alpha;
+   uint* color_table;
+} Ector_Renderer_Software_Gradient_Data;
 
 
 // Rasterizer related structure
-
 typedef struct _Raster_Buffer
 {
-    int            width;
-    int            height;
-    DATA32        *buffer;
-
-}Raster_Buffer;
+   int            width;
+   int            height;
+   DATA32        *buffer;
+} Raster_Buffer;
 
 typedef struct _Shape_Rle_Data
 {
-    unsigned short   alloc;
-    unsigned short   size;
-    SW_FT_Span      *spans;// array of Scanlines.
-}Shape_Rle_Data;
+   unsigned short   alloc;
+   unsigned short   size;
+   SW_FT_Span      *spans;// array of Scanlines.
+} Shape_Rle_Data;
 
 typedef struct _Clip_Data
 {
-    Eina_Array           *clips; //Eina_Rectangle
-    Shape_Rle_Data       *path;
-    unsigned int          enabled : 1;
-    unsigned int          hasRectClip : 1;
-    unsigned int          hasPathClip : 1;
-}Clip_Data;
+   Eina_Array           *clips; //Eina_Rectangle
+   Shape_Rle_Data       *path;
+   unsigned int          enabled : 1;
+   unsigned int          has_rect_clip : 1;
+   unsigned int          has_path_clip : 1;
+} Clip_Data;
 
 
 typedef enum _Span_Data_Type {
-    None,
-    Solid,
-    LinearGradient,
-    RadialGradient,
-    Image
-}Span_Data_Type;
+  None,
+  Solid,
+  LinearGradient,
+  RadialGradient,
+  Image
+} Span_Data_Type;
 
 typedef struct _Span_Data
 {
-    Raster_Buffer    raster_buffer;
-
-    SW_FT_SpanFunc   blend;
-    SW_FT_SpanFunc   unclipped_blend;
-    
-    int              offx, offy;
-    Clip_Data        clip;
-    Eina_Matrix3     inv;
-    Span_Data_Type   type;
-    Eina_Bool        fast_matrix ;
-    DATA32           mul_col;
-    Ector_Rop        op;
-    union {
-        DATA32 color;
-        Ector_Renderer_Software_Gradient_Data *gradient;
-        //ImageData    texture;
-    };
-}Span_Data;
+   Raster_Buffer    raster_buffer;
+
+   SW_FT_SpanFunc   blend;
+   SW_FT_SpanFunc   unclipped_blend;
+
+   int              offx, offy;
+   Clip_Data        clip;
+   Eina_Matrix3     inv;
+   Span_Data_Type   type;
+   Eina_Bool        fast_matrix ;
+   DATA32           mul_col;
+   Ector_Rop        op;
+   union {
+      DATA32 color;
+      Ector_Renderer_Software_Gradient_Data *gradient;
+      //ImageData    texture;
+   };
+} Span_Data;
 
 typedef struct _Software_Rasterizer
 {
-    SW_FT_Raster     raster;
-    SW_FT_Stroker    stroker;
+   SW_FT_Raster     raster;
+   SW_FT_Stroker    stroker;
 
-    Span_Data        fillData;
-    Eina_Matrix3    *transform;
-    Eina_Rectangle   systemClip;
-
-}Software_Rasterizer;
+   Span_Data        fill_data;
+   Eina_Matrix3    *transform;
+   Eina_Rectangle   system_clip;
 
+} Software_Rasterizer;
 
 struct _Ector_Software_Surface_Data
 {
    Software_Rasterizer *software;
+   int x;
+   int y;
 };
 
-
-
-
 void ector_software_rasterizer_init(Software_Rasterizer *rasterizer);
 void ector_software_rasterizer_done(Software_Rasterizer *rasterizer);
 
index 67207d5..7807c5f 100644 (file)
@@ -1,77 +1,73 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Ector.h>
 #include <software/Ector_Software.h>
+
 #include "ector_private.h"
 #include "ector_software_private.h"
-#include "ector_blend_private.h"
 
-static void _blend_color_argb(int count, const SW_FT_Span *spans, void *userData)
+#include "ector_drawhelper_private.h"
+
+static void
+_blend_color_argb(int count, const SW_FT_Span *spans, void *user_data)
 {
-    Span_Data *data = (Span_Data *)(userData);
-    
-    // multiply the color with mul_col if any
-    uint color = ECTOR_MUL4_SYM(data->color, data->mul_col);
-    
-    Eina_Bool solidSource = ((color >> 24) == 255);
-    
-    // move to the offset location
-     uint *buffer = data->raster_buffer.buffer + (data->raster_buffer.width * data->offy + data->offx);
+   RGBA_Comp_Func_Solid comp_func;
+   Span_Data *data = (Span_Data *)(user_data);
 
-    
-    if (solidSource) {
-        while (count--) {
-            uint *target = buffer + (data->raster_buffer.width * spans->y + spans->x);
-            if (spans->coverage == 255) {
-                _ector_memfill(target, color, spans->len);
-            } else {
-                uint c = ECTOR_MUL_256(color, spans->coverage);
-                int ialpha = 255 - spans->coverage;
-                for (int i = 0; i < spans->len; ++i)
-                    target[i] = c + ECTOR_MUL_256(target[i], ialpha);
-            }
-            ++spans;
-        }
-        return;
-    }
+   // multiply the color with mul_col if any
+   uint color = ECTOR_MUL4_SYM(data->color, data->mul_col);
+   comp_func = ector_comp_func_solid_span_get(data->op, color);
 
-    while (count--) {
+   // move to the offset location
+   uint *buffer = data->raster_buffer.buffer + (data->raster_buffer.width * data->offy + data->offx);
+
+   while (count--)
+     {
         uint *target = buffer + (data->raster_buffer.width * spans->y + spans->x);
-        uint c =  ECTOR_MUL_256(color, spans->coverage);
-        int ialpha = (~c) >> 24;
-        for (int i = 0; i < spans->len; ++i)
-            target[i] = c + ECTOR_MUL_256(target[i], ialpha);        
+        comp_func(target, spans->len, color, spans->coverage);
         ++spans;
-    }
+     }
 }
 
 int buffer_size = 2048;
 
 typedef void (*src_fetch) (unsigned int *buffer, Span_Data *data, int y, int x, int length);
+
 static void
-_blend_gradient(int count, const SW_FT_Span *spans, void *userData)
+_blend_gradient(int count, const SW_FT_Span *spans, void *user_data)
 {
-    Span_Data *data = (Span_Data *)(userData);
-    src_fetch fetchfunc = NULL;
-    if(data->type == LinearGradient) fetchfunc = &fetch_linear_gradient;
-    if(data->type == RadialGradient) fetchfunc = &fetch_radial_gradient;
+   RGBA_Comp_Func comp_func;
+   Span_Data *data = (Span_Data *)(user_data);
+   src_fetch fetchfunc = NULL;
+
+   //@TODO, Get the proper composition function using ,color, ECTOR_OP etc.
+   if (data->type == LinearGradient) fetchfunc = &fetch_linear_gradient;
+   if (data->type == RadialGradient) fetchfunc = &fetch_radial_gradient;
+
+   comp_func = ector_comp_func_span_get(data->op, data->mul_col, data->gradient->alpha);
+
+   unsigned int buffer[buffer_size];
 
-    unsigned int buffer[buffer_size];
-    // move to the offset location
-    unsigned int *destbuffer = data->raster_buffer.buffer + (data->raster_buffer.width * data->offy + data->offx);
+  // move to the offset location
+   unsigned int *destbuffer = data->raster_buffer.buffer + (data->raster_buffer.width * data->offy + data->offx);
 
-    while (count--) {
+   while (count--)
+     {
         unsigned int *target = destbuffer + (data->raster_buffer.width * spans->y + spans->x);
         int length = spans->len;
-        while (length) {
-            int l = MIN(length, buffer_size);
-            fetchfunc(buffer, data, spans->y, spans->x, l);
-            if (data->mul_col == 0xffffffff)
-                _ector_comp_func_source_over(target, buffer, l, spans->coverage); // TODO use proper composition func
-            else
-                _ector_comp_func_source_over_mul_c(target, buffer, data->mul_col, l, spans->coverage);
-            target += l;
-            length -= l;
-        }
-    ++spans;
-    }
+        while (length)
+          {
+             int l = MIN(length, buffer_size);
+             fetchfunc(buffer, data, spans->y, spans->x, l);
+             comp_func(target, buffer, l, data->mul_col, spans->coverage);
+             target += l;
+             length -= l;
+          }
+        ++spans;
+     }
 }
 
 
@@ -81,305 +77,419 @@ _blend_gradient(int count, const SW_FT_Span *spans, void *userData)
 */
 static const
 SW_FT_Span *_intersect_spans_rect(const Eina_Rectangle *clip, const SW_FT_Span *spans, const SW_FT_Span *end,
-                                       SW_FT_Span **outSpans, int available)
+                                  SW_FT_Span **out_spans, int available)
+{
+   SW_FT_Span *out = *out_spans;
+   const short minx = clip->x;
+   const short miny = clip->y;
+   const short maxx = minx + clip->w - 1;
+   const short maxy = miny + clip->h - 1;
+
+   while (available && spans < end )
+     {
+        if (spans->y > maxy)
+          {
+             spans = end;// update spans so that we can breakout
+             break;
+          }
+        if (spans->y < miny
+            || spans->x > maxx
+            || spans->x + spans->len <= minx)
+          {
+             ++spans;
+             continue;
+          }
+        if (spans->x < minx)
+          {
+             out->len = MIN(spans->len - (minx - spans->x), maxx - minx + 1);
+             out->x = minx;
+          }
+        else
+          {
+             out->x = spans->x;
+             out->len = MIN(spans->len, (maxx - spans->x + 1));
+          }
+        if (out->len != 0)
+          {
+             out->y = spans->y;
+             out->coverage = spans->coverage;
+             ++out;
+          }
+
+        ++spans;
+        --available;
+    }
+
+    *out_spans = out;
+
+    return spans;
+}
+
+static inline int
+_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
+
+static const
+SW_FT_Span *_intersect_spans_region(const Shape_Rle_Data *clip, int *currentClip,
+                                       const SW_FT_Span *spans, const SW_FT_Span *end,
+                                       SW_FT_Span **out_spans, int available)
 {
-    SW_FT_Span *out = *outSpans;
-    const short minx = clip->x;
-    const short miny = clip->y;
-    const short maxx = minx + clip->w - 1;
-    const short maxy = miny + clip->h - 1;
+    SW_FT_Span *out = *out_spans;
+
+    const SW_FT_Span *clipSpans = clip->spans + *currentClip;
+    const SW_FT_Span *clipEnd = clip->spans + clip->size;
 
     while (available && spans < end ) {
-        if (spans->y > maxy) {
-            spans = end;// update spans so that we can breakout
+        if (clipSpans >= clipEnd) {
+            spans = end;
             break;
         }
-        if (spans->y < miny
-            || spans->x > maxx
-            || spans->x + spans->len <= minx) {
+        if (clipSpans->y > spans->y) {
             ++spans;
             continue;
         }
-        if (spans->x < minx) {
-            out->len = MIN(spans->len - (minx - spans->x), maxx - minx + 1);
-            out->x = minx;
-        } else {
-            out->x = spans->x;
-            out->len = MIN(spans->len, (maxx - spans->x + 1));
+        if (spans->y != clipSpans->y) {
+            ++clipSpans;
+            continue;
         }
-        if (out->len != 0) {
+        //assert(spans->y == clipSpans->y);
+
+        int sx1 = spans->x;
+        int sx2 = sx1 + spans->len;
+        int cx1 = clipSpans->x;
+        int cx2 = cx1 + clipSpans->len;
+
+        if (cx1 < sx1 && cx2 < sx1) {
+            ++clipSpans;
+            continue;
+        } else if (sx1 < cx1 && sx2 < cx1) {
+            ++spans;
+            continue;
+        }
+        int x = MAX(sx1, cx1);
+        int len = MIN(sx2, cx2) - x;
+        if (len) {
+            out->x = MAX(sx1, cx1);
+            out->len = MIN(sx2, cx2) - out->x;
             out->y = spans->y;
-            out->coverage = spans->coverage;
+            out->coverage = _div_255(spans->coverage * clipSpans->coverage);
             ++out;
+            --available;
+        }
+        if (sx2 < cx2) {
+            ++spans;
+        } else {
+            ++clipSpans;
         }
-
-        ++spans;
-        --available;
     }
 
-    *outSpans = out;
-
+    *out_spans = out;
+    *currentClip = clipSpans - clip->spans;
     return spans;
 }
 
 static void
-_span_fill_clipRect(int spanCount, const SW_FT_Span *spans, void *userData)
+_span_fill_clipRect(int span_count, const SW_FT_Span *spans, void *user_data)
 {
     const int NSPANS = 256;
     int clip_count, i;
     SW_FT_Span cspans[NSPANS];
-    Span_Data *fillData = (Span_Data *) userData;
-    Clip_Data clip = fillData->clip;
+    Span_Data *fill_data = (Span_Data *) user_data;
+    Clip_Data clip = fill_data->clip;
+
     clip_count = eina_array_count(clip.clips);
-    for(i = 0; i < clip_count ; i ++)
+    for (i = 0; i < clip_count ; i ++)
       {
         Eina_Rectangle *rect = (Eina_Rectangle *)eina_array_data_get(clip.clips, i);
         Eina_Rectangle tmpRect;
+
         // invert transform the offset
-        tmpRect.x = rect->x - fillData->offx;
-        tmpRect.y = rect->y - fillData->offy;
+        tmpRect.x = rect->x - fill_data->offx;
+        tmpRect.y = rect->y - fill_data->offy;
         tmpRect.w = rect->w;
         tmpRect.h = rect->h;
-        //printf("Clip after Offset : %d , %d ,%d , %d\n",tmpRect.x, tmpRect.y, tmpRect.w, tmpRect.h);
-        //printf("Offset = %d , %d \n", fillData->offx, fillData->offy);
-        const SW_FT_Span *end = spans + spanCount;
-        while (spans < end) {
-            SW_FT_Span *clipped = cspans;
-            spans = _intersect_spans_rect(&tmpRect,spans, end, &clipped, NSPANS);
-            if (clipped - cspans)
-                fillData->unclipped_blend(clipped - cspans, cspans, fillData);
-        }
-    }
+        const SW_FT_Span *end = spans + span_count;
+
+        while (spans < end)
+          {
+             SW_FT_Span *clipped = cspans;
+             spans = _intersect_spans_rect(&tmpRect,spans, end, &clipped, NSPANS);
+             if (clipped - cspans)
+               fill_data->unclipped_blend(clipped - cspans, cspans, fill_data);
+          }
+      }
+}
+
+static void
+_span_fill_clipPath(int span_count, const SW_FT_Span *spans, void *user_data)
+{
+    const int NSPANS = 256;
+    int current_clip = 0;
+    SW_FT_Span cspans[NSPANS];
+    Span_Data *fill_data = (Span_Data *) user_data;
+    Clip_Data clip = fill_data->clip;
+
+    //TODO take clip path offset into account.
+    
+    const SW_FT_Span *end = spans + span_count;
+    while (spans < end)
+      {
+         SW_FT_Span *clipped = cspans;
+         spans = _intersect_spans_region(clip.path, &current_clip, spans, end, &clipped, NSPANS);
+         if (clipped - cspans)
+           fill_data->unclipped_blend(clipped - cspans, cspans, fill_data);
+      }
 }
 
 static void
 _adjust_span_fill_methods(Span_Data *spdata)
 {
-    switch(spdata->type) {
-    case None:
-        spdata->unclipped_blend = 0;
-        break;
-    case Solid:
-        spdata->unclipped_blend = &_blend_color_argb;
-        break;
-    case LinearGradient:
-    case RadialGradient:
-        spdata->unclipped_blend = &_blend_gradient;
-        break;
-    case Image:
-        spdata->unclipped_blend = 0;//&_blend_image;
-        break;
-    }
-    // setup clipping
-    if (!spdata->unclipped_blend) {
+   switch(spdata->type)
+     {
+      case None:
+         spdata->unclipped_blend = 0;
+         break;
+      case Solid:
+         spdata->unclipped_blend = &_blend_color_argb;
+         break;
+      case LinearGradient:
+      case RadialGradient:
+         spdata->unclipped_blend = &_blend_gradient;
+         break;
+      case Image:
+         spdata->unclipped_blend = 0;//&_blend_image;
+         break;
+     }
+
+   // setup clipping
+   if (!spdata->unclipped_blend)
+     {
         spdata->blend = 0;
-    } else if (!spdata->clip.enabled) {
+     }
+   else if (!spdata->clip.enabled)
+     {
         spdata->blend = spdata->unclipped_blend;
-    } else if (spdata->clip.hasRectClip) {
+     }
+   else if (spdata->clip.has_rect_clip)
+     {
         spdata->blend = &_span_fill_clipRect;
-    } else {
-        spdata->blend = &_span_fill_clipRect; //TODO change when do path clipping
-    }
+     }
+   else
+     {
+        spdata->blend = &_span_fill_clipPath;
+     }
 }
 
 
 
 void ector_software_rasterizer_init(Software_Rasterizer *rasterizer)
 {
-    // initialize the rasterizer and stroker
-    unsigned char* renderPool = (unsigned char*) malloc(1024 * 100);
-    sw_ft_grays_raster.raster_new(&rasterizer->raster);
-    sw_ft_grays_raster.raster_reset(rasterizer->raster, renderPool, 1024*100);
-
-    SW_FT_Stroker_New(&rasterizer->stroker);
-    SW_FT_Stroker_Set(rasterizer->stroker, 1<<6,SW_FT_STROKER_LINECAP_BUTT,SW_FT_STROKER_LINEJOIN_MITER,0);
-
-    //initialize the span data.
-    rasterizer->fillData.raster_buffer.buffer = NULL;
-    rasterizer->fillData.clip.enabled = EINA_FALSE;
-    rasterizer->fillData.unclipped_blend = 0;
-    rasterizer->fillData.blend = 0;
+   // initialize the rasterizer and stroker
+   unsigned char* renderPool = (unsigned char*) malloc(1024 * 100);
+   sw_ft_grays_raster.raster_new(&rasterizer->raster);
+   sw_ft_grays_raster.raster_reset(rasterizer->raster, renderPool, 1024*100);
+
+   SW_FT_Stroker_New(&rasterizer->stroker);
+   SW_FT_Stroker_Set(rasterizer->stroker, 1<<6,SW_FT_STROKER_LINECAP_BUTT,SW_FT_STROKER_LINEJOIN_MITER,0);
+
+   //initialize the span data.
+   rasterizer->fill_data.raster_buffer.buffer = NULL;
+   rasterizer->fill_data.clip.enabled = EINA_FALSE;
+   rasterizer->fill_data.unclipped_blend = 0;
+   rasterizer->fill_data.blend = 0;
+   init_draw_helper();
 }
 
 void ector_software_rasterizer_done(Software_Rasterizer *rasterizer)
 {
-    sw_ft_grays_raster.raster_done(rasterizer->raster);
-    SW_FT_Stroker_Done(rasterizer->stroker);
-    //TODO free the pool memory
+   sw_ft_grays_raster.raster_done(rasterizer->raster);
+   SW_FT_Stroker_Done(rasterizer->stroker);
+   //TODO free the pool memory
 }
 
 
 void ector_software_rasterizer_stroke_set(Software_Rasterizer *rasterizer, double width,
                                           Efl_Gfx_Cap cap_style, Efl_Gfx_Join join_style)
 {
-    SW_FT_Stroker_LineCap cap;
-    SW_FT_Stroker_LineJoin join;
-
-    switch (cap_style) {
-        case EFL_GFX_CAP_SQUARE:
-            cap = SW_FT_STROKER_LINECAP_SQUARE;
-            break;
-        case EFL_GFX_CAP_ROUND:
-            cap = SW_FT_STROKER_LINECAP_ROUND;
-            break;
-        default:
-            cap = SW_FT_STROKER_LINECAP_BUTT;
-            break;
-    }
-    switch (join_style) {
-        case EFL_GFX_JOIN_BEVEL:
-            join = SW_FT_STROKER_LINEJOIN_BEVEL;
-            break;
-        case EFL_GFX_JOIN_ROUND:
-            join = SW_FT_STROKER_LINEJOIN_ROUND;
-            break;
-        default:
-            join = SW_FT_STROKER_LINEJOIN_MITER;
-            break;
-    }
-    int stroke_width = (int)(width * 64);
-    SW_FT_Stroker_Set(rasterizer->stroker, stroke_width, cap, join, 0);
+   SW_FT_Stroker_LineCap cap;
+   SW_FT_Stroker_LineJoin join;
+
+   switch (cap_style)
+     {
+      case EFL_GFX_CAP_SQUARE:
+         cap = SW_FT_STROKER_LINECAP_SQUARE;
+         break;
+      case EFL_GFX_CAP_ROUND:
+         cap = SW_FT_STROKER_LINECAP_ROUND;
+         break;
+      default:
+         cap = SW_FT_STROKER_LINECAP_BUTT;
+         break;
+     }
+
+   switch (join_style)
+     {
+      case EFL_GFX_JOIN_BEVEL:
+         join = SW_FT_STROKER_LINEJOIN_BEVEL;
+         break;
+      case EFL_GFX_JOIN_ROUND:
+         join = SW_FT_STROKER_LINEJOIN_ROUND;
+         break;
+      default:
+         join = SW_FT_STROKER_LINEJOIN_MITER;
+         break;
+     }
+
+   int stroke_width = (int)(width * 64);
+   SW_FT_Stroker_Set(rasterizer->stroker, stroke_width, cap, join, 0);
 }
 
 static void
 _rle_generation_cb( int count, const SW_FT_Span*  spans,void *user)
 {
-    Shape_Rle_Data *rle = (Shape_Rle_Data *) user;
-    int newsize = rle->size + count;
-
-    // allocate enough memory for new spans
-    // alloc is required to prevent free and reallocation
-    // when the rle needs to be regenerated because of attribute change.
-    if(rle->alloc < newsize) {
+   Shape_Rle_Data *rle = (Shape_Rle_Data *) user;
+   int newsize = rle->size + count;
+
+   // allocate enough memory for new spans
+   // alloc is required to prevent free and reallocation
+   // when the rle needs to be regenerated because of attribute change.
+   if(rle->alloc < newsize)
+     {
         rle->spans = (SW_FT_Span *) realloc(rle->spans, newsize * sizeof(SW_FT_Span));
         rle->alloc = newsize;
-    }
+     }
 
-    // copy the new spans to the allocated memory
-    SW_FT_Span *lastspan = (rle->spans + rle->size);
-    memcpy(lastspan,spans, count * sizeof(SW_FT_Span));
+   // copy the new spans to the allocated memory
+   SW_FT_Span *lastspan = (rle->spans + rle->size);
+   memcpy(lastspan,spans, count * sizeof(SW_FT_Span));
 
-    // update the size
-    rle->size = newsize;
+   // update the size
+   rle->size = newsize;
 }
 
 Shape_Rle_Data *
 ector_software_rasterizer_generate_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline)
 {
-    Shape_Rle_Data *rle_data = (Shape_Rle_Data *) calloc(1, sizeof(Shape_Rle_Data));
-    SW_FT_Raster_Params params;
-    params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA ;
-    params.gray_spans = &_rle_generation_cb;
-    params.user = rle_data;
-    params.source = outline;
+   Shape_Rle_Data *rle_data = (Shape_Rle_Data *) calloc(1, sizeof(Shape_Rle_Data));
+   SW_FT_Raster_Params params;
+
+   params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA ;
+   params.gray_spans = &_rle_generation_cb;
+   params.user = rle_data;
+   params.source = outline;
 
-    sw_ft_grays_raster.raster_render(rasterizer->raster, &params);
+   sw_ft_grays_raster.raster_render(rasterizer->raster, &params);
 
-    return rle_data;
+   return rle_data;
 }
 
 Shape_Rle_Data *
 ector_software_rasterizer_generate_stroke_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline, Eina_Bool closePath)
 {
-    uint points,contors;
-    
-    SW_FT_Stroker_ParseOutline(rasterizer->stroker, outline, !closePath);
-    SW_FT_Stroker_GetCounts(rasterizer->stroker,&points, &contors);
+   uint points,contors;
 
-    SW_FT_Outline strokeOutline = {0};
-    strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector));
-    strokeOutline.tags = (char *) calloc(points, sizeof(char));
-    strokeOutline.contours = (short *) calloc(contors, sizeof(short));
+   SW_FT_Stroker_ParseOutline(rasterizer->stroker, outline, !closePath);
+   SW_FT_Stroker_GetCounts(rasterizer->stroker,&points, &contors);
 
-    SW_FT_Stroker_Export(rasterizer->stroker, &strokeOutline);
+   SW_FT_Outline strokeOutline = {0};
+   strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector));
+   strokeOutline.tags = (char *) calloc(points, sizeof(char));
+   strokeOutline.contours = (short *) calloc(contors, sizeof(short));
 
-    Shape_Rle_Data *rle_data = ector_software_rasterizer_generate_rle_data(rasterizer, &strokeOutline);
+   SW_FT_Stroker_Export(rasterizer->stroker, &strokeOutline);
 
-    // cleanup the outline data.
-    free(strokeOutline.points);
-    free(strokeOutline.tags);
-    free(strokeOutline.contours);
+   Shape_Rle_Data *rle_data = ector_software_rasterizer_generate_rle_data(rasterizer, &strokeOutline);
 
-    return rle_data;
+   // cleanup the outline data.
+   free(strokeOutline.points);
+   free(strokeOutline.tags);
+   free(strokeOutline.contours);
+
+   return rle_data;
 }
 
 void ector_software_rasterizer_destroy_rle_data(Shape_Rle_Data *rle)
 {
-    if (rle) {
+   if (rle)
+     {
         if (rle->spans)
-            free(rle->spans);
+          free(rle->spans);
         free(rle);
-    }
+     }
 }
 
 static
 void _setup_span_fill_matrix(Software_Rasterizer *rasterizer)
 {
-    if (rasterizer->transform)
-    {
-        eina_matrix3_inverse(rasterizer->transform, &rasterizer->fillData.inv);
-    } else {
-        eina_matrix3_identity(&rasterizer->fillData.inv);
-        eina_matrix3_identity(&rasterizer->fillData.inv);
-    }
+   if (rasterizer->transform)
+     {
+        eina_matrix3_inverse(rasterizer->transform, &rasterizer->fill_data.inv);
+     }
+   else
+     {
+        eina_matrix3_identity(&rasterizer->fill_data.inv);
+        eina_matrix3_identity(&rasterizer->fill_data.inv);
+     }
 }
 
 void ector_software_rasterizer_transform_set(Software_Rasterizer *rasterizer, Eina_Matrix3 *t)
 {
-    rasterizer->transform = t;
+   rasterizer->transform = t;
 }
 
 void ector_software_rasterizer_clip_rect_set(Software_Rasterizer *rasterizer, Eina_Array *clips)
 {
-    if (clips) {
-        rasterizer->fillData.clip.clips = clips;
-        rasterizer->fillData.clip.hasRectClip = EINA_TRUE;
-        rasterizer->fillData.clip.enabled = EINA_TRUE;
-    } else {
-        rasterizer->fillData.clip.clips = NULL;
-        rasterizer->fillData.clip.hasRectClip = EINA_FALSE;
-        rasterizer->fillData.clip.enabled = EINA_FALSE;
-    }
+   if (clips)
+     {
+        rasterizer->fill_data.clip.clips = clips;
+        rasterizer->fill_data.clip.has_rect_clip = EINA_TRUE;
+        rasterizer->fill_data.clip.enabled = EINA_TRUE;
+     }
+   else
+     {
+        rasterizer->fill_data.clip.clips = NULL;
+        rasterizer->fill_data.clip.has_rect_clip = EINA_FALSE;
+        rasterizer->fill_data.clip.enabled = EINA_FALSE;
+     }
 }
 
 void ector_software_rasterizer_clip_shape_set(Software_Rasterizer *rasterizer, Shape_Rle_Data *clip)
 {
-    rasterizer->fillData.clip.path = clip;
-    rasterizer->fillData.clip.hasPathClip = EINA_TRUE;
-    rasterizer->fillData.clip.enabled = EINA_TRUE;
+   rasterizer->fill_data.clip.path = clip;
+   rasterizer->fill_data.clip.has_path_clip = EINA_TRUE;
+   rasterizer->fill_data.clip.enabled = EINA_TRUE;
 }
 
 void ector_software_rasterizer_color_set(Software_Rasterizer *rasterizer, int r, int g, int b, int a)
 {
-    uint color = ECTOR_ARGB_JOIN(a, r, g, b);
-    rasterizer->fillData.color = _ector_premultiply(color);
-    rasterizer->fillData.type = Solid;
+   rasterizer->fill_data.color = ECTOR_ARGB_JOIN(a, r, g, b);
+   rasterizer->fill_data.type = Solid;
 }
 void ector_software_rasterizer_linear_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *linear)
 {
-    rasterizer->fillData.gradient = linear;
-    rasterizer->fillData.type = LinearGradient;
+   rasterizer->fill_data.gradient = linear;
+   rasterizer->fill_data.type = LinearGradient;
 }
 void ector_software_rasterizer_radial_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *radial)
 {
-    rasterizer->fillData.gradient = radial;
-    rasterizer->fillData.type = RadialGradient;   
+   rasterizer->fill_data.gradient = radial;
+   rasterizer->fill_data.type = RadialGradient;
 }
 
 
-void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer, 
+void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer,
                                              int x, int y, uint mul_col, Ector_Rop op, Shape_Rle_Data* rle)
 {
-    rasterizer->fillData.offx = x;
-    rasterizer->fillData.offy = y;
-    rasterizer->fillData.mul_col = mul_col;
-    rasterizer->fillData.op = op;
+   // check for NULL rle data
+   if (!rle) return;
 
-    _setup_span_fill_matrix(rasterizer);
-    _adjust_span_fill_methods(&rasterizer->fillData);
-
-    if(rasterizer->fillData.blend)
-        rasterizer->fillData.blend(rle->size, rle->spans, &rasterizer->fillData);    
-}
+   rasterizer->fill_data.offx = x;
+   rasterizer->fill_data.offy = y;
+   rasterizer->fill_data.mul_col = mul_col;
+   rasterizer->fill_data.op = op;
 
+   _setup_span_fill_matrix(rasterizer);
+   _adjust_span_fill_methods(&rasterizer->fill_data);
 
+   if(rasterizer->fill_data.blend)
+     rasterizer->fill_data.blend(rle->size, rle->spans, &rasterizer->fill_data);
+}
index 80b5e1d..02d93c3 100644 (file)
 
 static unsigned int _software_count = 0;
 
+typedef struct _Ector_Renderer_Software_Base_Data Ector_Renderer_Software_Base_Data;
+struct _Ector_Renderer_Software_Base_Data
+{
+};
 
 static Ector_Renderer *
 _ector_software_surface_ector_generic_surface_renderer_factory_new(Eo *obj,
-                                                                Ector_Software_Surface_Data *pd EINA_UNUSED,
-                                                                const Eo_Class *type)
+                                                                   Ector_Software_Surface_Data *pd EINA_UNUSED,
+                                                                   const Eo_Class *type)
 {
-   if (type == ECTOR_RENDERER_GENERIC_SHAPE_CLASS)
+   if (type == ECTOR_RENDERER_GENERIC_SHAPE_MIXIN)
      return eo_add(ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS, obj);
-   else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS)
+   else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN)
      return eo_add(ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS, obj);
-   else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_CLASS)
+   else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN)
      return eo_add(ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS, obj);
+   ERR("Couldn't find class for type: %s\n", eo_class_name_get(type));
    return NULL;
 }
 
 static void
 _ector_software_surface_context_set(Eo *obj EINA_UNUSED,
-                                 Ector_Software_Surface_Data *pd,
-                                 Software_Rasterizer *ctx)
+                                    Ector_Software_Surface_Data *pd,
+                                    Software_Rasterizer *ctx)
 {
    pd->software = ctx;
 }
 
 static Software_Rasterizer *
 _ector_software_surface_context_get(Eo *obj EINA_UNUSED,
-                                 Ector_Software_Surface_Data *pd)
+                                    Ector_Software_Surface_Data *pd)
 {
    return pd->software;
 }
 
-void _ector_software_surface_ector_generic_surface_surface_set(Eo *obj EINA_UNUSED, 
-                                                               Ector_Software_Surface_Data *pd, 
-                                                               void *pixels, unsigned int width, unsigned int height)
+void
+_ector_software_surface_surface_set(Eo *obj EINA_UNUSED,
+                                    Ector_Software_Surface_Data *pd,
+                                    void *pixels, unsigned int width, unsigned int height)
 {
-    pd->software->fillData.raster_buffer.buffer = pixels;
-    pd->software->fillData.raster_buffer.width = width;
-    pd->software->fillData.raster_buffer.height = height;
+   pd->software->fill_data.raster_buffer.buffer = pixels;
+   pd->software->fill_data.raster_buffer.width = width;
+   pd->software->fill_data.raster_buffer.height = height;
 }
 
-
-void _ector_software_surface_ector_generic_surface_surface_get(Eo *obj EINA_UNUSED, 
-                                                               Ector_Software_Surface_Data *pd, 
-                                                               void **pixels, unsigned int *width, unsigned int *height)
+void
+_ector_software_surface_surface_get(Eo *obj EINA_UNUSED,
+                                    Ector_Software_Surface_Data *pd,
+                                    void **pixels, unsigned int *width, unsigned int *height)
 {
-  *pixels = pd->software->fillData.raster_buffer.buffer;
-  *width = pd->software->fillData.raster_buffer.width;
-  *height = pd->software->fillData.raster_buffer.height;
+   *pixels = pd->software->fill_data.raster_buffer.buffer;
+   *width = pd->software->fill_data.raster_buffer.width;
+   *height = pd->software->fill_data.raster_buffer.height;
 }
 
-
-
 static void
 _ector_software_surface_eo_base_constructor(Eo *obj,
-                                         Ector_Software_Surface_Data *pd EINA_UNUSED)
+                                            Ector_Software_Surface_Data *pd EINA_UNUSED)
 {
   eo_do_super(obj, ECTOR_SOFTWARE_SURFACE_CLASS, eo_constructor());
-  if(_software_count == 0) {
-    pd->software = (Software_Rasterizer *) calloc(1, sizeof(Software_Rasterizer));
-    ector_software_rasterizer_init(pd->software);
-  }
+  if(_software_count == 0)
+    {
+       pd->software = (Software_Rasterizer *) calloc(1, sizeof(Software_Rasterizer));
+       ector_software_rasterizer_init(pd->software);
+    }
   _software_count++;
 }
 
@@ -85,6 +90,14 @@ _ector_software_surface_eo_base_destructor(Eo *obj EINA_UNUSED,
    eo_do_super(obj, ECTOR_SOFTWARE_SURFACE_CLASS, eo_destructor());
 }
 
+static void
+_ector_software_surface_ector_generic_surface_reference_point_set(Eo *obj EINA_UNUSED,
+                                                                  Ector_Software_Surface_Data *pd,
+                                                                  int x, int y)
+{
+   pd->x = x;
+   pd->y = y;
+}
 
 #include "ector_software_surface.eo.c"
 #include "ector_renderer_software_base.eo.c"
index b324f78..3ed863c 100644 (file)
@@ -12,12 +12,22 @@ class Ector.Software.Surface (Ector.Generic.Surface)
            Software_Rasterizer *ctx;
         }
       }
+      surface {
+         set {
+        }
+        get {
+        }
+        values {
+           void *pixels;
+           uint width;
+           uint height;
+        }
+      }
    }
 
    implements {
       Ector.Generic.Surface.renderer_factory_new;
-      Ector.Generic.Surface.surface.set;
-      Ector.Generic.Surface.surface.get;
+      Ector.Generic.Surface.reference_point.set;
       Eo.Base.destructor;
       Eo.Base.constructor;
    }
index 55cb3c9..cbdb89f 100644 (file)
@@ -34,32 +34,9 @@ extern "C"
 # endif
 #endif /* ! _WIN32 */
 
-#ifdef EFL_BETA_API_SUPPORT
-
-/* Interfaces */
-#include "interfaces/efl_control.eo.h"
-#include "interfaces/efl_file.eo.h"
-#include "interfaces/efl_image.eo.h"
-#include "interfaces/efl_player.eo.h"
-#include "interfaces/efl_text.eo.h"
-#include "interfaces/efl_text_properties.eo.h"
-
-#endif
 /**
  * These values determine how the points are interpreted in a stream of points.
  *
- * @see efl_gfx_path_dup()
- * @see efl_gfx_path_append_move_to()
- * @see efl_gfx_path_append_line_to()
- * @see efl_gfx_path_append_quadratic_to()
- * @see efl_gfx_path_append_cubic_to()
- * @see efl_gfx_path_append_scubic_to()
- * @see efl_gfx_path_append_arc_to()
- * @see efl_gfx_path_append_arc()
- * @see efl_gfx_path_append_rounded_rect()
- * @see efl_gfx_path_append_close()
- * @see efl_gfx_path_append_circle()
- *
  * @since 1.14
  */
 typedef enum _Efl_Gfx_Path_Command
@@ -147,11 +124,42 @@ typedef enum _Efl_Gfx_Gradient_Spread
   EFL_GFX_GRADIENT_SPREAD_LAST /**< End of enum value */
 } Efl_Gfx_Gradient_Spread;
 
-#include "interfaces/efl_gfx_utils.h"
+/**
+ * Type defining how an image content get filled.
+ * @since 1.14
+ */
+typedef enum _Efl_Gfx_Fill_Spread
+{
+  EFL_GFX_FILL_REFLECT = 0, /**< image fill tiling mode - tiling reflects */
+  EFL_GFX_FILL_REPEAT = 1,  /**< tiling repeats */
+  EFL_GFX_FILL_RESTRICT = 2, /**< tiling clamps - range offset ignored */
+  EFL_GFX_FILL_RESTRICT_REFLECT = 3, /**< tiling clamps and any range offset reflects */
+  EFL_GFX_FILL_RESTRICT_REPEAT = 4, /**< tiling clamps and any range offset repeats */
+  EFL_GFX_FILL_PAD = 5 /**< tiling extends with end values */
+} Efl_Gfx_Fill_Spread;
+
+#ifdef EFL_BETA_API_SUPPORT
+
+/* Interfaces */
+#include "interfaces/efl_control.eo.h"
+#include "interfaces/efl_file.eo.h"
+#include "interfaces/efl_image.eo.h"
+#include "interfaces/efl_player.eo.h"
+#include "interfaces/efl_text.eo.h"
+#include "interfaces/efl_text_properties.eo.h"
+
+EAPI extern const Eo_Event_Description _EFL_GFX_CHANGED;
+EAPI extern const Eo_Event_Description _EFL_GFX_PATH_CHANGED;
+
+#define EFL_GFX_CHANGED (&(_EFL_GFX_CHANGED))
+#define EFL_GFX_PATH_CHANGED (&(_EFL_GFX_PATH_CHANGED))
 
 #include "interfaces/efl_gfx_base.eo.h"
+#include "interfaces/efl_gfx_stack.eo.h"
+#include "interfaces/efl_gfx_fill.eo.h"
+#include "interfaces/efl_gfx_view.eo.h"
 #include "interfaces/efl_gfx_shape.eo.h"
-#include "interfaces/efl_gfx_gradient.eo.h"
+#include "interfaces/efl_gfx_gradient_base.eo.h"
 #include "interfaces/efl_gfx_gradient_linear.eo.h"
 #include "interfaces/efl_gfx_gradient_radial.eo.h"
 
index e5b719c..df9369c 100644 (file)
@@ -74,6 +74,51 @@ interface Efl.Gfx.Base {
             int a; /*@ The alpha component of the given color. */
          }
       }
+      color_part {
+         set {
+            /*@
+            Sets a specifc color of the given Efl.Gfx.Base object to the given
+            one.
+
+            @see evas_object_color_get() (for an example)
+            @note These color values are expected to be premultiplied by @p a.
+
+            */
+           return: bool;
+         }
+         get {
+            /*@
+            Retrieves a specific color of the given Evas object.
+
+            Retrieves a specific color's RGB component (and alpha channel)
+            values, <b>which range from 0 to 255</b>. For the alpha channel,
+            which defines the object's transparency level, 0 means totally
+            transparent, while 255 means opaque. These color values are
+            premultiplied by the alpha value.
+
+           The “main“ color being mapped to @c NULL.
+
+            Usually you’ll use this attribute for text and rectangle objects,
+            where the “main” color is their unique one. If set for objects
+            which themselves have colors, like the images one, those colors get
+            modulated by this one.
+
+            @note Use @c NULL pointers on the components you're not interested
+            in: they'll be ignored by the function.
+
+            */
+           return: bool;
+         }
+        keys {
+           const (char)* part; /*@ The part you are interested in. */
+        }
+         values {
+            int r; /*@ The red component of the given color. */
+            int g; /*@ The green component of the given color. */
+            int b; /*@ The blue component of the given color. */
+            int a; /*@ The alpha component of the given color. */
+         }
+      }
       visible {
          set {
             /*@ Makes the given Evas object visible or invisible. */
diff --git a/src/lib/efl/interfaces/efl_gfx_fill.eo b/src/lib/efl/interfaces/efl_gfx_fill.eo
new file mode 100644 (file)
index 0000000..1ce4dd8
--- /dev/null
@@ -0,0 +1,72 @@
+interface Efl.Gfx.Fill {
+   legacy_prefix: null;
+   properties {
+      fill_spread {
+         set {
+            /*@
+            Sets the tiling mode for the given evas image object's fill.
+            EFL_GFX_FILL_RESTRICT, or EFL_GFX_FILL_PAD. */
+         }
+         get {
+            /*@
+            Retrieves the spread (tiling mode) for the given image object's
+            fill.
+
+            @return  The current spread mode of the image object. */
+         }
+         values {
+            Efl_Gfx_Fill_Spread spread; /*@ One of EVAS_TEXTURE_REFLECT, EVAS_TEXTURE_REPEAT, */
+         }
+      }
+      fill {
+         set {
+            /*@
+            Set how to fill an image object's drawing rectangle given the
+            (real) image bound to it.
+
+            Note that if @p w or @p h are smaller than the dimensions of
+            @p obj, the displayed image will be @b tiled around the object's
+            area. To have only one copy of the bound image drawn, @p x and @p y
+            must be 0 and @p w and @p h need to be the exact width and height
+            of the image object itself, respectively.
+
+            See the following image to better understand the effects of this
+            call. On this diagram, both image object and original image source
+            have @c a x @c a dimensions and the image itself is a circle, with
+            empty space around it:
+
+            @image html image-fill.png
+            @image rtf image-fill.png
+            @image latex image-fill.eps
+
+            @warning The default values for the fill parameters are @p x = 0,
+            @p y = 0, @p w = 0 and @p h = 0. Thus, if you're not using the
+            evas_object_image_filled_add() helper and want your image
+            displayed, you'll have to set valid values with this function on
+            your object.
+
+            @note evas_object_image_filled_set() is a helper function which
+            will @b override the values set here automatically, for you, in a
+            given way. */
+         }
+         get {
+            /*@
+            Retrieve how an image object is to fill its drawing rectangle,
+            given the (real) image bound to it.
+
+            @note Use @c NULL pointers on the fill components you're not
+            interested in: they'll be ignored by the function.
+
+            See @ref evas_object_image_fill_set() for more details. */
+         }
+         values {
+            int x; /*@ The x coordinate (from the top left corner of the bound
+            image) to start drawing from. */
+            int y; /*@ The y coordinate (from the top left corner of the bound
+            image) to start drawing from. */
+            int w; /*@ The width the bound image will be displayed at. */
+            int h; /*@ The height the bound image will be displayed at. */
+         }
+      }
+   }
+}
diff --git a/src/lib/efl/interfaces/efl_gfx_gradient_base.eo b/src/lib/efl/interfaces/efl_gfx_gradient_base.eo
new file mode 100644 (file)
index 0000000..b50d7bc
--- /dev/null
@@ -0,0 +1,38 @@
+interface Efl.Gfx.Gradient.Base
+{
+   eo_prefix: efl_gfx_gradient;
+   legacy_prefix: null;
+   properties {
+      stop {
+         set {
+            /*@
+              Set the list of color stops for the gradient
+            */
+         }
+         get {
+            /*@
+              get the list of color stops.
+            */
+         }
+         values {
+            const(Efl_Gfx_Gradient_Stop) *colors; /*@ color stops list*/
+            uint length; /*@ length of the list */
+         }
+      }
+      spread {
+         set {
+            /*@
+              Specifies the spread method that should be used for this gradient.
+            */
+         }
+         get {
+            /*@
+              Returns the spread method use by this gradient. The default is EFL_GFX_GRADIENT_SPREAD_PAD.
+            */
+         }
+         values {
+            Efl_Gfx_Gradient_Spread s; /*@ spread type to be used */
+         }
+      }
+   }
+}
index 88c1d80..0d9299f 100644 (file)
@@ -1,4 +1,4 @@
-interface Efl.Gfx.Gradient_Linear (Efl.Gfx.Gradient)
+interface Efl.Gfx.Gradient.Linear (Efl.Gfx.Gradient.Base)
 {
    legacy_prefix: null;
    properties {
@@ -6,13 +6,11 @@ interface Efl.Gfx.Gradient_Linear (Efl.Gfx.Gradient)
          set {
             /*@
               Sets the start point of this linear gradient.
-              @since 1.14
             */
          }
          get {
             /*@
               Gets the start point of this linear gradient.
-              @since 1.14
             */
          }
          values {
@@ -24,13 +22,11 @@ interface Efl.Gfx.Gradient_Linear (Efl.Gfx.Gradient)
          set {
             /*@
               Sets the end point of this linear gradient.
-              @since 1.14
             */
          }
          get {
             /*@
               Gets the end point of this linear gradient.
-              @since 1.14
             */
          }
          values {
index 5a84c78..b9eeb72 100644 (file)
@@ -1,4 +1,4 @@
-interface Efl.Gfx.Gradient_Radial (Efl.Gfx.Gradient)
+interface Efl.Gfx.Gradient.Radial (Efl.Gfx.Gradient.Base)
 {
    legacy_prefix: null;
    properties {
diff --git a/src/lib/efl/interfaces/efl_gfx_shape.c b/src/lib/efl/interfaces/efl_gfx_shape.c
new file mode 100644 (file)
index 0000000..ef0c2a7
--- /dev/null
@@ -0,0 +1,1333 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <math.h>
+#include <float.h>
+#include <ctype.h>
+
+#include <Efl.h>
+
+typedef struct _Efl_Gfx_Shape_Data Efl_Gfx_Shape_Data;
+struct _Efl_Gfx_Shape_Data
+{
+   struct {
+      double x;
+      double y;
+   } current, current_ctrl;
+
+   Efl_Gfx_Path_Command *commands;
+   double *points;
+
+   unsigned int commands_count;
+   unsigned int points_count;
+};
+
+static inline unsigned int
+_efl_gfx_path_command_length(Efl_Gfx_Path_Command command)
+{
+   switch (command)
+     {
+      case EFL_GFX_PATH_COMMAND_TYPE_END: return 0;
+      case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO: return 2;
+      case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO: return 2;
+      case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO: return 6;
+      case EFL_GFX_PATH_COMMAND_TYPE_CLOSE: return 0;
+      case EFL_GFX_PATH_COMMAND_TYPE_LAST: return 0;
+     }
+   return 0;
+}
+
+static inline void
+_efl_gfx_path_length(const Efl_Gfx_Path_Command *commands,
+                     unsigned int *cmd_length,
+                     unsigned int *pts_length)
+{
+   if (commands)
+     while (commands[*cmd_length] != EFL_GFX_PATH_COMMAND_TYPE_END)
+       {
+          *pts_length += _efl_gfx_path_command_length(commands[*cmd_length]);
+          (*cmd_length)++;
+       }
+
+   // Accounting for END command and handle gracefully the NULL case at the same time
+   (*cmd_length)++;
+}
+
+static inline Eina_Bool
+efl_gfx_path_grow(Efl_Gfx_Path_Command command,
+                  Efl_Gfx_Shape_Data *pd,
+                  double **offset_point)
+{
+   Efl_Gfx_Path_Command *cmd_tmp;
+   double *pts_tmp;
+   unsigned int cmd_length = 0, pts_length = 0;
+
+   cmd_length = pd->commands_count ? pd->commands_count : 1;
+   pts_length = pd->points_count;
+
+   if (_efl_gfx_path_command_length(command))
+     {
+        pts_length += _efl_gfx_path_command_length(command);
+        pts_tmp = realloc(pd->points, pts_length * sizeof (double));
+        if (!pts_tmp) return EINA_FALSE;
+
+        pd->points = pts_tmp;
+        *offset_point = pd->points +
+          pts_length - _efl_gfx_path_command_length(command);
+     }
+
+   cmd_tmp = realloc(pd->commands,
+                     (cmd_length + 1) * sizeof (Efl_Gfx_Path_Command));
+   if (!cmd_tmp) return EINA_FALSE;
+   pd->commands = cmd_tmp;
+
+   pd->commands_count = cmd_length + 1;
+   pd->points_count = pts_length;
+
+   // Append the command
+   cmd_tmp[cmd_length - 1] = command;
+   // NULL terminate the stream
+   cmd_tmp[cmd_length] = EFL_GFX_PATH_COMMAND_TYPE_END;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_gfx_path_current_search(const Efl_Gfx_Path_Command *cmd,
+                             const double *points,
+                             double *current_x, double *current_y,
+                             double *current_ctrl_x, double *current_ctrl_y)
+{
+   unsigned int i;
+
+   if (current_x) *current_x = 0;
+   if (current_y) *current_y = 0;
+   if (current_ctrl_x) *current_ctrl_x = 0;
+   if (current_ctrl_y) *current_ctrl_y = 0;
+   if (!cmd || !points) return EINA_FALSE;
+
+   for (i = 0; cmd[i] != EFL_GFX_PATH_COMMAND_TYPE_END; i++)
+     {
+        switch (cmd[i])
+          {
+           case EFL_GFX_PATH_COMMAND_TYPE_END:
+              break;
+           case EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO:
+           case EFL_GFX_PATH_COMMAND_TYPE_LINE_TO:
+              if (current_x) *current_x = points[0];
+              if (current_y) *current_y = points[1];
+
+              points += 2;
+              break;
+           case EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO:
+              if (current_x) *current_x = points[0];
+              if (current_y) *current_y = points[1];
+              if (current_ctrl_x) *current_ctrl_x = points[4];
+              if (current_ctrl_y) *current_ctrl_y = points[5];
+
+              points += 6;
+              break;
+           case EFL_GFX_PATH_COMMAND_TYPE_CLOSE:
+              break;
+           case EFL_GFX_PATH_COMMAND_TYPE_LAST:
+           default:
+              return EINA_FALSE;
+          }
+     }
+
+   return EINA_TRUE;
+}
+
+void
+_efl_gfx_shape_path_set(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                        const Efl_Gfx_Path_Command *commands,
+                        const double *points)
+{
+   Efl_Gfx_Path_Command *cmds;
+   double *pts;
+   unsigned int cmds_length = 0, pts_length = 0;
+
+   if (!commands)
+     {
+        free(pd->commands); pd->commands = NULL;
+        free(pd->points); pd->points = NULL;
+        pd->current.x = pd->current.y = 0;
+        pd->current_ctrl.x = pd->current_ctrl.y = 0;
+        goto end;
+     }
+
+   _efl_gfx_path_length(commands, &cmds_length, &pts_length);
+
+   cmds = realloc(pd->commands,
+                  sizeof (Efl_Gfx_Path_Command) * cmds_length);
+   if (!cmds) return ;
+   pd->commands = cmds;
+
+   pts = realloc(pd->points,
+                 sizeof (double) * pts_length);
+   if (!pts) return ;
+   pd->points = pts;
+
+   pd->commands_count = cmds_length;
+   pd->points_count = pts_length;
+
+   memcpy(pd->commands, commands, sizeof (Efl_Gfx_Path_Command) * cmds_length);
+   memcpy(pd->points, points, sizeof (double) * pts_length);
+
+   _efl_gfx_path_current_search(pd->commands, pd->points,
+                                &pd->current.x, &pd->current.y,
+                                &pd->current_ctrl.x, &pd->current_ctrl.y);
+
+ end:
+   eo_do(obj,
+         eo_event_callback_call(EFL_GFX_PATH_CHANGED, NULL),
+         eo_event_callback_call(EFL_GFX_CHANGED, NULL));
+}
+
+void
+_efl_gfx_shape_path_get(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd,
+                        const Efl_Gfx_Path_Command **commands,
+                        const double **points)
+{
+   if (commands) *commands = pd->commands;
+   if (points) *points = pd->points;
+}
+
+void
+_efl_gfx_shape_path_length_get(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd,
+                               unsigned int *commands, unsigned int *points)
+{
+   if (commands) *commands = pd->commands_count;
+   if (points) *points = pd->points_count;
+}
+
+void
+_efl_gfx_shape_current_get(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd,
+                           double *x, double *y)
+{
+   if (x) *x = pd->current.x;
+   if (y) *y = pd->current.y;
+}
+
+void
+_efl_gfx_shape_current_ctrl_get(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd,
+                                double *x, double *y)
+{
+   if (x) *x = pd->current_ctrl.x;
+   if (y) *y = pd->current_ctrl.y;
+}
+
+static Eina_Bool
+_efl_gfx_shape_equal_commands_internal(Efl_Gfx_Shape_Data *a,
+                                       Efl_Gfx_Shape_Data *b)
+{
+   unsigned int i;
+
+   if (a->commands_count != b->commands_count) return EINA_FALSE;
+
+   for (i = 0; a->commands[i] == b->commands[i] &&
+          a->commands[i] != EFL_GFX_PATH_COMMAND_TYPE_END; i++)
+     ;
+
+   return (a->commands[i] == b->commands[i]);
+}
+
+static inline double
+interpolate(double from, double to, double pos_map)
+{
+   return (from * pos_map) + (to * (1.0 - pos_map));
+}
+
+static inline int
+interpolatei(int from, int to, double pos_map)
+{
+   return (from * pos_map) + (to * (1.0 - pos_map));
+}
+
+typedef struct _Efl_Gfx_Stroke Efl_Gfx_Stroke;
+struct _Efl_Gfx_Stroke
+{
+   double scale;
+   int r, g, b, a;
+   double w;
+   double centered;
+   const Efl_Gfx_Dash *dash;
+   unsigned int dash_length;
+   Efl_Gfx_Cap c;
+   Efl_Gfx_Join j;
+};
+
+static inline void
+stroke_get(const Eo *obj, Efl_Gfx_Stroke *stroke)
+{
+   eo_do(obj,
+         stroke->scale = efl_gfx_shape_stroke_scale_get(),
+         efl_gfx_shape_stroke_color_get(&stroke->r, &stroke->g, &stroke->b, &stroke->a),
+         stroke->w = efl_gfx_shape_stroke_width_get(),
+         stroke->centered = efl_gfx_shape_stroke_location_get(),
+         efl_gfx_shape_stroke_dash_get(&stroke->dash, &stroke->dash_length),
+         stroke->c = efl_gfx_shape_stroke_cap_get(),
+         stroke->j = efl_gfx_shape_stroke_join_get());
+}
+
+Eina_Bool
+_efl_gfx_shape_interpolate(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                           const Eo *from, const Eo *to, double pos_map)
+{
+   Efl_Gfx_Shape_Data *from_pd, *to_pd;
+   Efl_Gfx_Path_Command *cmds;
+   double *pts, *from_pts, *to_pts;
+   unsigned int i, j;
+   Efl_Gfx_Stroke stroke_from, stroke_to;
+   Efl_Gfx_Dash *dash;
+
+   from_pd = eo_data_scope_get(from, EFL_GFX_SHAPE_MIXIN);
+   to_pd = eo_data_scope_get(to, EFL_GFX_SHAPE_MIXIN);
+   if (!eo_isa(from, EFL_GFX_SHAPE_MIXIN) ||
+       !eo_isa(to, EFL_GFX_SHAPE_MIXIN)) return EINA_FALSE;
+   if (pd == from_pd || pd == to_pd) return EINA_FALSE;
+   if (!_efl_gfx_shape_equal_commands_internal(from_pd, to_pd))
+     return EINA_FALSE;
+
+   stroke_get(from, &stroke_from);
+   stroke_get(to, &stroke_to);
+
+   if (stroke_from.dash_length != stroke_to.dash_length) return EINA_FALSE;
+
+   cmds = realloc(pd->commands,
+                  sizeof (Efl_Gfx_Path_Command) * from_pd->commands_count);
+   if (!cmds && from_pd->commands_count) return EINA_FALSE;
+   pd->commands = cmds;
+
+   pts = realloc(pd->points,
+                 sizeof (double) * from_pd->points_count);
+   if (!pts && from_pd->points_count) return EINA_FALSE;
+   pd->points = pts;
+
+   memcpy(cmds, from_pd->commands,
+          sizeof (Efl_Gfx_Path_Command) * from_pd->commands_count);
+
+   to_pts = to_pd->points;
+   from_pts = from_pd->points;
+
+   for (i = 0; cmds[i] != EFL_GFX_PATH_COMMAND_TYPE_END; i++)
+     for (j = 0; j < _efl_gfx_path_command_length(cmds[i]); j++)
+       {
+          *pts = interpolate(*from_pts, *to_pts, pos_map);
+
+          pts++;
+          from_pts++;
+          to_pts++;
+       }
+
+   pd->points_count = from_pd->points_count;
+   pd->commands_count = from_pd->commands_count;
+
+   pd->current.x = interpolate(from_pd->current.x,
+                               to_pd->current.x,
+                               pos_map);
+   pd->current.y = interpolate(from_pd->current.y,
+                               to_pd->current.y,
+                               pos_map);
+   pd->current_ctrl.x = interpolate(from_pd->current_ctrl.x,
+                                    to_pd->current_ctrl.x,
+                                    pos_map);
+   pd->current_ctrl.y = interpolate(from_pd->current_ctrl.y,
+                                    to_pd->current_ctrl.y,
+                                    pos_map);
+
+   dash = malloc(sizeof (Efl_Gfx_Dash) * stroke_to.dash_length);
+   if (dash)
+     {
+        for (i = 0; i < stroke_to.dash_length; i++)
+          {
+             dash[i].length = interpolate(stroke_from.dash[i].length,
+                                          stroke_to.dash[i].length, pos_map);
+             dash[i].gap = interpolate(stroke_from.dash[i].gap,
+                                       stroke_to.dash[i].gap, pos_map);
+          }
+     }
+   else
+     {
+        stroke_to.dash_length = 0;
+     }
+
+   eo_do(obj,
+         efl_gfx_shape_stroke_scale_set(interpolate(stroke_to.scale, stroke_from.scale, pos_map)),
+         efl_gfx_shape_stroke_color_set(interpolatei(stroke_to.r, stroke_from.r, pos_map),
+                                        interpolatei(stroke_to.g, stroke_from.g, pos_map),
+                                        interpolatei(stroke_to.b, stroke_from.b, pos_map),
+                                        interpolatei(stroke_to.a, stroke_from.a, pos_map)),
+         efl_gfx_shape_stroke_width_set(interpolate(stroke_to.w, stroke_from.w, pos_map)),
+         efl_gfx_shape_stroke_location_set(interpolate(stroke_to.centered, stroke_from.centered, pos_map)),
+         efl_gfx_shape_stroke_dash_set(dash, stroke_to.dash_length),
+         efl_gfx_shape_stroke_cap_set(pos_map < 0.5 ? stroke_from.c : stroke_to.c),
+         efl_gfx_shape_stroke_join_set(pos_map < 0.5 ? stroke_from.j : stroke_to.j),
+
+         eo_event_callback_call(EFL_GFX_PATH_CHANGED, NULL),
+         eo_event_callback_call(EFL_GFX_CHANGED, NULL));
+
+   return EINA_TRUE;
+}
+
+Eina_Bool
+_efl_gfx_shape_equal_commands(Eo *obj EINA_UNUSED,
+                              Efl_Gfx_Shape_Data *pd,
+                              const Eo *with)
+{
+   Efl_Gfx_Shape_Data *with_pd;
+
+   with_pd = eo_data_scope_get(with, EFL_GFX_SHAPE_MIXIN);
+   if (!with_pd) return EINA_FALSE;
+
+   return _efl_gfx_shape_equal_commands_internal(with_pd, pd);
+}
+
+void
+_efl_gfx_shape_dup(Eo *obj, Efl_Gfx_Shape_Data *pd, Eo *dup_from)
+{
+   const Efl_Gfx_Dash *dash = NULL;
+   Efl_Gfx_Shape_Data *from;
+   unsigned int dash_length = 0;
+   Efl_Gfx_Cap cap;
+   Efl_Gfx_Join j;
+   int sr, sg, sb, sa;
+   double scale, location;
+   double sw;
+
+   if (obj == dup_from) return ;
+   from = eo_data_scope_get(dup_from, EFL_GFX_SHAPE_MIXIN);
+   if (!from) return ;
+
+   eo_do(dup_from,
+         scale = efl_gfx_shape_stroke_scale_get(),
+         efl_gfx_shape_stroke_color_get(&sr, &sg, &sb, &sa),
+         sw = efl_gfx_shape_stroke_width_get(),
+         location = efl_gfx_shape_stroke_location_get(),
+         efl_gfx_shape_stroke_dash_get(&dash, &dash_length),
+         cap = efl_gfx_shape_stroke_cap_get(),
+         j = efl_gfx_shape_stroke_join_get());
+   eo_do(obj,
+         efl_gfx_shape_stroke_scale_set(scale),
+         efl_gfx_shape_stroke_color_set(sr, sg, sb, sa),
+         efl_gfx_shape_stroke_width_set(sw),
+         efl_gfx_shape_stroke_location_set(location),
+         efl_gfx_shape_stroke_dash_set(dash, dash_length),
+         efl_gfx_shape_stroke_cap_set(cap),
+         efl_gfx_shape_stroke_join_set(j));
+
+   _efl_gfx_shape_path_set(obj, pd, from->commands, from->points);
+
+   eo_do(obj,
+         eo_event_callback_call(EFL_GFX_PATH_CHANGED, NULL),
+         eo_event_callback_call(EFL_GFX_CHANGED, NULL));
+}
+
+void
+_efl_gfx_shape_reset(Eo *obj, Efl_Gfx_Shape_Data *pd)
+{
+   free(pd->commands);
+   pd->commands = NULL;
+   pd->commands_count = 0;
+
+   free(pd->points);
+   pd->points = NULL;
+   pd->points_count = 0;
+
+   pd->current.x = 0;
+   pd->current.y = 0;
+   pd->current_ctrl.x = 0;
+   pd->current_ctrl.y = 0;
+
+   eo_do(obj,
+         eo_event_callback_call(EFL_GFX_PATH_CHANGED, NULL),
+         eo_event_callback_call(EFL_GFX_CHANGED, NULL));
+}
+
+void
+_efl_gfx_shape_append_move_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                              double x, double y)
+{
+   double *offset_point;
+
+   if (!efl_gfx_path_grow(EFL_GFX_PATH_COMMAND_TYPE_MOVE_TO,
+                          pd, &offset_point))
+     return ;
+
+   offset_point[0] = x;
+   offset_point[1] = y;
+
+   pd->current.x = x;
+   pd->current.y = y;
+
+   eo_do(obj,
+         eo_event_callback_call(EFL_GFX_PATH_CHANGED, NULL),
+         eo_event_callback_call(EFL_GFX_CHANGED, NULL));
+}
+
+void
+_efl_gfx_shape_append_line_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                              double x, double y)
+{
+   double *offset_point;
+
+   if (!efl_gfx_path_grow(EFL_GFX_PATH_COMMAND_TYPE_LINE_TO,
+                          pd, &offset_point))
+     return ;
+
+   offset_point[0] = x;
+   offset_point[1] = y;
+
+   pd->current.x = x;
+   pd->current.y = y;
+
+   eo_do(obj,
+         eo_event_callback_call(EFL_GFX_PATH_CHANGED, NULL),
+         eo_event_callback_call(EFL_GFX_CHANGED, NULL));
+}
+
+void
+_efl_gfx_shape_append_cubic_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                               double x, double y,
+                               double ctrl_x0, double ctrl_y0,
+                               double ctrl_x1, double ctrl_y1)
+{
+   double *offset_point;
+
+   if (!efl_gfx_path_grow(EFL_GFX_PATH_COMMAND_TYPE_CUBIC_TO,
+                          pd, &offset_point))
+     return ;
+
+   offset_point[0] = x;
+   offset_point[1] = y;
+   offset_point[2] = ctrl_x0;
+   offset_point[3] = ctrl_y0;
+   offset_point[4] = ctrl_x1;
+   offset_point[5] = ctrl_y1;
+
+   pd->current.x = x;
+   pd->current.y = y;
+   pd->current_ctrl.x = ctrl_x1;
+   pd->current_ctrl.y = ctrl_y1;
+
+   eo_do(obj,
+         eo_event_callback_call(EFL_GFX_PATH_CHANGED, NULL),
+         eo_event_callback_call(EFL_GFX_CHANGED, NULL));
+}
+
+void
+_efl_gfx_shape_append_scubic_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                                double x, double y,
+                                double ctrl_x, double ctrl_y)
+{
+   double ctrl_x0, ctrl_y0;
+   double current_x = 0, current_y = 0;
+   double current_ctrl_x = 0, current_ctrl_y = 0;
+
+   current_x = pd->current.x;
+   current_y = pd->current.x;
+   current_ctrl_x = pd->current_ctrl.x;
+   current_ctrl_y = pd->current_ctrl.y;
+
+   ctrl_x0 = 2 * current_x - current_ctrl_x;
+   ctrl_y0 = 2 * current_y - current_ctrl_y;
+
+   _efl_gfx_shape_append_cubic_to(obj, pd, x, y,
+                                  ctrl_x0, ctrl_y0, ctrl_x, ctrl_y);
+}
+
+void
+_efl_gfx_shape_append_quadratic_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                                   double x, double y,
+                                   double ctrl_x, double ctrl_y)
+{
+   double current_x = 0, current_y = 0;
+   double ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1;
+
+   current_x = pd->current.x;
+   current_y = pd->current.y;
+
+   // Convert quadratic bezier to cubic
+   ctrl_x0 = (current_x + 2 * ctrl_x) * (1.0 / 3.0);
+   ctrl_y0 = (current_y + 2 * ctrl_y) * (1.0 / 3.0);
+   ctrl_x1 = (x + 2 * ctrl_x) * (1.0 / 3.0);
+   ctrl_y1 = (y + 2 * ctrl_y) * (1.0 / 3.0);
+
+   _efl_gfx_shape_append_cubic_to(obj, pd, x, y,
+                                  ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1);
+}
+
+void
+_efl_gfx_shape_append_squadratic_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                                    double x, double y)
+{
+   double xc, yc; /* quadratic control point */
+   double ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1;
+   double current_x = 0, current_y = 0;
+   double current_ctrl_x = 0, current_ctrl_y = 0;
+
+   current_x = pd->current.x;
+   current_y = pd->current.x;
+   current_ctrl_x = pd->current_ctrl.x;
+   current_ctrl_y = pd->current_ctrl.y;
+
+   xc = 2 * current_x - current_ctrl_x;
+   yc = 2 * current_y - current_ctrl_y;
+   /* generate a quadratic bezier with control point = xc, yc */
+   ctrl_x0 = (current_x + 2 * xc) * (1.0 / 3.0);
+   ctrl_y0 = (current_y + 2 * yc) * (1.0 / 3.0);
+   ctrl_x1 = (x + 2 * xc) * (1.0 / 3.0);
+   ctrl_y1 = (y + 2 * yc) * (1.0 / 3.0);
+
+   _efl_gfx_shape_append_cubic_to(obj, pd, x, y,
+                                  ctrl_x0, ctrl_y0,
+                                  ctrl_x1, ctrl_y1);
+}
+
+/*
+ * code adapted from enesim which was adapted from moonlight sources
+ */
+void
+_efl_gfx_shape_append_arc_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                             double x, double y,
+                             double rx, double ry,
+                             double angle,
+                             Eina_Bool large_arc, Eina_Bool sweep)
+{
+   double cxp, cyp, cx, cy;
+   double sx, sy;
+   double cos_phi, sin_phi;
+   double dx2, dy2;
+   double x1p, y1p;
+   double x1p2, y1p2;
+   double rx2, ry2;
+   double lambda;
+   double c;
+   double at;
+   double theta1, delta_theta;
+   double nat;
+   double delta, bcp;
+   double cos_phi_rx, cos_phi_ry;
+   double sin_phi_rx, sin_phi_ry;
+   double cos_theta1, sin_theta1;
+   int segments, i;
+
+   // some helpful stuff is available here:
+   // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
+   sx = pd->current.x;
+   sy = pd->current.y;
+
+   // if start and end points are identical, then no arc is drawn
+   if ((fabs(x - sx) < (1 / 256.0)) && (fabs(y - sy) < (1 / 256.0)))
+     return;
+
+   // Correction of out-of-range radii, see F6.6.1 (step 2)
+   rx = fabs(rx);
+   ry = fabs(ry);
+   if ((rx < 0.5) || (ry < 0.5))
+     {
+        _efl_gfx_shape_append_line_to(obj, pd, x, y);
+        return;
+     }
+
+   angle = angle * M_PI / 180.0;
+   cos_phi = cos(angle);
+   sin_phi = sin(angle);
+   dx2 = (sx - x) / 2.0;
+   dy2 = (sy - y) / 2.0;
+   x1p = cos_phi * dx2 + sin_phi * dy2;
+   y1p = cos_phi * dy2 - sin_phi * dx2;
+   x1p2 = x1p * x1p;
+   y1p2 = y1p * y1p;
+   rx2 = rx * rx;
+   ry2 = ry * ry;
+   lambda = (x1p2 / rx2) + (y1p2 / ry2);
+
+   // Correction of out-of-range radii, see F6.6.2 (step 4)
+   if (lambda > 1.0)
+     {
+        // see F6.6.3
+        double lambda_root = sqrt(lambda);
+
+        rx *= lambda_root;
+        ry *= lambda_root;
+        // update rx2 and ry2
+        rx2 = rx * rx;
+        ry2 = ry * ry;
+     }
+
+   c = (rx2 * ry2) - (rx2 * y1p2) - (ry2 * x1p2);
+
+   // check if there is no possible solution
+   // (i.e. we can't do a square root of a negative value)
+   if (c < 0.0)
+     {
+        // scale uniformly until we have a single solution
+        // (see F6.2) i.e. when c == 0.0
+        double scale = sqrt(1.0 - c / (rx2 * ry2));
+        rx *= scale;
+        ry *= scale;
+        // update rx2 and ry2
+        rx2 = rx * rx;
+        ry2 = ry * ry;
+
+        // step 2 (F6.5.2) - simplified since c == 0.0
+        cxp = 0.0;
+        cyp = 0.0;
+        // step 3 (F6.5.3 first part) - simplified since cxp and cyp == 0.0
+        cx = 0.0;
+        cy = 0.0;
+     }
+   else
+     {
+        // complete c calculation
+        c = sqrt(c / ((rx2 * y1p2) + (ry2 * x1p2)));
+        // inverse sign if Fa == Fs
+        if (large_arc == sweep)
+          c = -c;
+
+        // step 2 (F6.5.2)
+        cxp = c * ( rx * y1p / ry);
+        cyp = c * (-ry * x1p / rx);
+
+        // step 3 (F6.5.3 first part)
+        cx = cos_phi * cxp - sin_phi * cyp;
+        cy = sin_phi * cxp + cos_phi * cyp;
+     }
+
+   // step 3 (F6.5.3 second part) we now have the center point of the ellipse
+   cx += (sx + x) / 2.0;
+   cy += (sy + y) / 2.0;
+
+   // step 4 (F6.5.4)
+   // we dont' use arccos (as per w3c doc),
+   // see http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
+   // note: atan2 (0.0, 1.0) == 0.0
+   at = atan2(((y1p - cyp) / ry), ((x1p - cxp) / rx));
+   theta1 = (at < 0.0) ? 2.0 * M_PI + at : at;
+
+   nat = atan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
+   delta_theta = (nat < at) ? 2.0 * M_PI - at + nat : nat - at;
+
+   if (sweep)
+     {
+        // ensure delta theta < 0 or else add 360 degrees
+        if (delta_theta < 0.0)
+          delta_theta += 2.0 * M_PI;
+     }
+   else
+     {
+        // ensure delta theta > 0 or else substract 360 degrees
+        if (delta_theta > 0.0)
+          delta_theta -= 2.0 * M_PI;
+     }
+
+   // add several cubic bezier to approximate the arc
+   // (smaller than 90 degrees)
+   // we add one extra segment because we want something
+   // smaller than 90deg (i.e. not 90 itself)
+   segments = (int) (fabs(delta_theta / M_PI_2)) + 1;
+   delta = delta_theta / segments;
+
+   // http://www.stillhq.com/ctpfaq/2001/comp.text.pdf-faq-2001-04.txt (section 2.13)
+   bcp = 4.0 / 3 * (1 - cos(delta / 2)) / sin(delta / 2);
+
+   cos_phi_rx = cos_phi * rx;
+   cos_phi_ry = cos_phi * ry;
+   sin_phi_rx = sin_phi * rx;
+   sin_phi_ry = sin_phi * ry;
+
+   cos_theta1 = cos(theta1);
+   sin_theta1 = sin(theta1);
+
+   for (i = 0; i < segments; ++i)
+     {
+        // end angle (for this segment) = current + delta
+        double c1x, c1y, ex, ey, c2x, c2y;
+        double theta2 = theta1 + delta;
+        double cos_theta2 = cos(theta2);
+        double sin_theta2 = sin(theta2);
+
+        // first control point (based on start point sx,sy)
+        c1x = sx - bcp * (cos_phi_rx * sin_theta1 + sin_phi_ry * cos_theta1);
+        c1y = sy + bcp * (cos_phi_ry * cos_theta1 - sin_phi_rx * sin_theta1);
+
+        // end point (for this segment)
+        ex = cx + (cos_phi_rx * cos_theta2 - sin_phi_ry * sin_theta2);
+        ey = cy + (sin_phi_rx * cos_theta2 + cos_phi_ry * sin_theta2);
+
+        // second control point (based on end point ex,ey)
+        c2x = ex + bcp * (cos_phi_rx * sin_theta2 + sin_phi_ry * cos_theta2);
+        c2y = ey + bcp * (sin_phi_rx * sin_theta2 - cos_phi_ry * cos_theta2);
+
+        _efl_gfx_shape_append_cubic_to(obj, pd, ex, ey, c1x, c1y, c2x, c2y);
+
+        // next start point is the current end point (same for angle)
+        sx = ex;
+        sy = ey;
+        theta1 = theta2;
+        // avoid recomputations
+        cos_theta1 = cos_theta2;
+        sin_theta1 = sin_theta2;
+     }
+}
+
+void
+_efl_gfx_shape_append_close(Eo *obj, Efl_Gfx_Shape_Data *pd)
+{
+   double *offset_point;
+
+   efl_gfx_path_grow(EFL_GFX_PATH_COMMAND_TYPE_CLOSE,
+                     pd, &offset_point);
+
+   eo_do(obj,
+         eo_event_callback_call(EFL_GFX_PATH_CHANGED, NULL),
+         eo_event_callback_call(EFL_GFX_CHANGED, NULL));
+}
+
+void
+_efl_gfx_shape_append_circle(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                             double x, double y, double radius)
+{
+   _efl_gfx_shape_append_move_to(obj, pd, x - radius, y);
+   _efl_gfx_shape_append_arc_to(obj, pd, x + radius, y, radius, radius, 0, EINA_FALSE, EINA_TRUE);
+   _efl_gfx_shape_append_arc_to(obj, pd, x, y + radius, radius, radius, 0, EINA_FALSE, EINA_TRUE);
+   _efl_gfx_shape_append_arc_to(obj, pd, x - radius, y, radius, radius, 0, EINA_FALSE, EINA_TRUE);
+   _efl_gfx_shape_append_arc_to(obj, pd, x, y - radius, radius, radius, 0, EINA_FALSE, EINA_TRUE);
+}
+
+void
+_efl_gfx_shape_append_rect(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                           double x, double y, double w, double h,
+                           double rx, double ry)
+{
+   _efl_gfx_shape_append_move_to(obj, pd, x, y + ry);
+   // Top left corner
+   _efl_gfx_shape_append_arc_to(obj, pd, x + rx, y, rx, ry, 0, EINA_FALSE, EINA_TRUE);
+   _efl_gfx_shape_append_line_to(obj, pd, x + w - rx, y);
+   // Top right corner
+   _efl_gfx_shape_append_arc_to(obj, pd, x + w, y + ry, rx, ry, 0, EINA_FALSE, EINA_TRUE);
+   _efl_gfx_shape_append_line_to(obj, pd, x + w, y + h - ry);
+   // Bottom right corner
+   _efl_gfx_shape_append_arc_to(obj, pd, x + w - rx, y + h, rx, ry, 0, EINA_FALSE, EINA_TRUE);
+   _efl_gfx_shape_append_line_to(obj, pd, x + rx, y + h);
+   // Bottom left corner
+   _efl_gfx_shape_append_arc_to(obj, pd, x, y + h - ry, rx, ry, 0, EINA_FALSE, EINA_TRUE);
+   _efl_gfx_shape_append_close(obj, pd);
+}
+
+static void
+_efl_gfx_path_append_horizontal_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                                   double d, double current_x EINA_UNUSED, double current_y)
+{
+   _efl_gfx_shape_append_line_to(obj, pd, d, current_y);
+}
+
+static void
+_efl_gfx_path_append_vertical_to(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                                 double d, double current_x, double current_y EINA_UNUSED)
+{
+   _efl_gfx_shape_append_line_to(obj, pd, current_x, d);
+}
+
+static char *
+_strcomma(const char *content)
+{
+   while (*content && isspace(*content)) content++;
+   if (*content != ',') return NULL;
+   return (char*) content + 1;
+}
+
+static inline Eina_Bool
+_next_isnumber(const char *content)
+{
+   char *tmp = NULL;
+
+   (void) strtod(content, &tmp);
+   return content != tmp;
+}
+
+static Eina_Bool
+_efl_gfx_path_parse_pair(const char *content, char **end, double *x, double *y)
+{
+   /* "x,y" */
+   char *end1 = NULL;
+   char *end2 = NULL;
+
+   *x = strtod(content, &end1);
+   end1 = _strcomma(end1);
+   if (!end1) return EINA_FALSE;
+   *y = strtod(end1, &end2);
+   if (end1 == end2) return EINA_FALSE;
+
+   *end = end2;
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_gfx_path_parse_pair_to(const char *content, char **end,
+                            Eo *obj, Efl_Gfx_Shape_Data *pd,
+                            double *current_x, double *current_y,
+                            void (*func)(Eo *obj, Efl_Gfx_Shape_Data *pd, double x, double y),
+                            Eina_Bool rel)
+{
+   double x, y;
+
+   *end = (char*) content;
+   do
+     {
+        Eina_Bool r;
+
+        r = _efl_gfx_path_parse_pair(content, end, &x, &y);
+        if (!r) return EINA_FALSE;
+
+        if (rel)
+          {
+             x += *current_x;
+             y += *current_y;
+          }
+
+        func(obj, pd, x, y);
+        content = *end;
+
+        *current_x = x;
+        *current_y = y;
+     }
+   while (_next_isnumber(content));
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_gfx_path_parse_double_to(const char *content, char **end,
+                              Eo *obj, Efl_Gfx_Shape_Data *pd,
+                              double *current, double current_x, double current_y,
+                              void (*func)(Eo *obj, Efl_Gfx_Shape_Data *pd, double d, double current_x, double current_y),
+                              Eina_Bool rel)
+{
+   double d;
+   Eina_Bool first = EINA_FALSE;
+
+   *end = (char*) content;
+   do
+     {
+        d = strtod(content, end);
+        if (content == *end)
+          return first;
+        first = EINA_TRUE;
+
+        if (rel)
+          {
+             d += *current;
+          }
+
+        func(obj, pd, d, current_x, current_y);
+        content = *end;
+
+        *current = d;
+     }
+   while (1); // This is an optimisation as we have only one parameter.
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_gfx_path_parse_six(const char *content, char **end,
+                        double *x, double *y,
+                        double *ctrl_x0, double *ctrl_y0,
+                        double *ctrl_x1, double *ctrl_y1)
+{
+   /* "x,y ctrl_x0,ctrl_y0 ctrl_x1,ctrl_y1" */
+   char *end1 = NULL;
+   char *end2 = NULL;
+
+   *ctrl_x0 = strtod(content, &end1);
+   end1 = _strcomma(end1);
+   if (!end1) return EINA_FALSE;
+   *ctrl_y0 = strtod(end1, &end2);
+   if (end1 == end2) return EINA_FALSE;
+
+   *ctrl_x1 = strtod(end2, &end2);
+   end2 = _strcomma(end2);
+   if (!end2) return EINA_FALSE;
+   *ctrl_y1 = strtod(end2, &end1);
+   if (end1 == end2) return EINA_FALSE;
+
+   *x = strtod(end1, &end2);
+   end2 = _strcomma(end2);
+   if (!end2) return EINA_FALSE;
+   *y = strtod(end2, &end1);
+   if (end1 == end2) return EINA_FALSE;
+
+   *end = end1;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_gfx_path_parse_six_to(const char *content, char **end,
+                           Eo *obj, Efl_Gfx_Shape_Data *pd,
+                           double *current_x, double *current_y,
+                           void (*func)(Eo *obj, Efl_Gfx_Shape_Data *pd, double x, double y, double ctrl_x0, double ctrl_y0, double ctrl_x1, double ctrl_y1),
+                           Eina_Bool rel)
+{
+   double x, y, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1;
+
+   *end = (char*) content;
+   do
+     {
+        Eina_Bool r;
+
+        r = _efl_gfx_path_parse_six(content, end,
+                                    &x, &y,
+                                    &ctrl_x0, &ctrl_y0,
+                                    &ctrl_x1, &ctrl_y1);
+        if (!r) return EINA_FALSE;
+
+        if (rel)
+          {
+             x += *current_x;
+             y += *current_y;
+          }
+
+        func(obj, pd, x, y, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1);
+        content = *end;
+
+        *current_x = x;
+        *current_y = y;
+     }
+   while (_next_isnumber(content));
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_gfx_path_parse_quad(const char *content, char **end,
+                         double *x, double *y,
+                         double *ctrl_x0, double *ctrl_y0)
+{
+   /* "x,y ctrl_x0,ctrl_y0" */
+   char *end1 = NULL;
+   char *end2 = NULL;
+
+   *ctrl_x0 = strtod(content, &end1);
+   end1 = _strcomma(end1);
+   if (!end1) return EINA_FALSE;
+   *ctrl_y0 = strtod(end1, &end2);
+   if (end1 == end2) return EINA_FALSE;
+
+   *x = strtod(end2, &end1);
+   end1 = _strcomma(end2);
+   if (!end1) return EINA_FALSE;
+   *y = strtod(end1, &end2);
+   if (end1 == end2) return EINA_FALSE;
+
+   *end = end2;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_gfx_path_parse_quad_to(const char *content, char **end,
+                            Eo *obj, Efl_Gfx_Shape_Data *pd,
+                            double *current_x, double *current_y,
+                            void (*func)(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                                         double x, double y, double ctrl_x0, double ctrl_y0),
+                            Eina_Bool rel)
+{
+   double x, y, ctrl_x0, ctrl_y0;
+
+   *end = (char*) content;
+   do
+     {
+        Eina_Bool r;
+
+        r = _efl_gfx_path_parse_quad(content, end,
+                                     &x, &y,
+                                     &ctrl_x0, &ctrl_y0);
+        if (!r) return EINA_FALSE;
+
+        if (rel)
+          {
+             x += *current_x;
+             y += *current_y;
+          }
+
+        func(obj, pd, x, y, ctrl_x0, ctrl_y0);
+        content = *end;
+
+        *current_x = x;
+        *current_y = y;
+     }
+   while (_next_isnumber(content));
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_gfx_path_parse_arc(const char *content, char **end,
+                        double *x, double *y,
+                        double *rx, double *ry,
+                        double *radius,
+                        Eina_Bool *large_arc, Eina_Bool *sweep)
+{
+   /* "rx,ry r large-arc-flag,sweep-flag x,y" */
+   char *end1 = NULL;
+   char *end2 = NULL;
+
+   *rx = strtod(content, &end1);
+   end1 = _strcomma(end1);
+   if (!end1) return EINA_FALSE;
+   *ry = strtod(end1, &end2);
+   if (end1 == end2) return EINA_FALSE;
+
+   *radius = strtod(end2, &end1);
+   if (end1 == end2) return EINA_FALSE;
+
+   *large_arc = strtol(end1, &end2, 10) ? EINA_TRUE : EINA_FALSE;
+   end1 = _strcomma(end2);
+   if (!end1) return EINA_FALSE;
+   *sweep = strtol(end1, &end2, 10) ? EINA_TRUE : EINA_FALSE;
+   if (end1 == end2) return EINA_FALSE;
+
+   *x = strtod(end2, &end1);
+   end1 = _strcomma(end2);
+   if (!end1) return EINA_FALSE;
+   *y = strtod(end1, &end2);
+   if (end1 == end2) return EINA_FALSE;
+
+   *end = end2;
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_gfx_path_parse_arc_to(const char *content, char **end,
+                           Eo *obj, Efl_Gfx_Shape_Data *pd,
+                           double *current_x, double *current_y,
+                           void (*func)(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                                        double x, double y, double rx, double ry, double angle,
+                                        Eina_Bool large_arc, Eina_Bool sweep),
+                           Eina_Bool rel)
+{
+   double x, y, rx, ry, angle;
+   Eina_Bool large_arc, sweep; // FIXME: handle those flag
+
+   *end = (char*) content;
+   do
+     {
+        Eina_Bool r;
+
+        r = _efl_gfx_path_parse_arc(content, end,
+                                    &x, &y,
+                                    &rx, &ry,
+                                    &angle,
+                                    &large_arc, &sweep);
+        if (!r) return EINA_FALSE;
+
+        if (rel)
+          {
+             x += *current_x;
+             y += *current_y;
+          }
+
+        func(obj, pd, x, y, rx, ry, angle, large_arc, sweep);
+        content = *end;
+
+        *current_x = x;
+        *current_y = y;
+     }
+   while (_next_isnumber(content));
+
+   return EINA_TRUE;
+}
+
+void
+_efl_gfx_shape_append_svg_path(Eo *obj, Efl_Gfx_Shape_Data *pd,
+                               const char *svg_path_data)
+{
+   double current_x = 0, current_y = 0;
+   char *content = (char*) svg_path_data;
+
+   if (!content) return ;
+
+   while (content[0] != '\0')
+     {
+        while (isspace(content[0])) content++;
+
+        switch (content[0])
+          {
+           case 'M':
+              if (!_efl_gfx_path_parse_pair_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_move_to,
+                                               EINA_FALSE))
+                return ;
+              break;
+           case 'm':
+              if (!_efl_gfx_path_parse_pair_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_move_to,
+                                               EINA_TRUE))
+                return ;
+              break;
+           case 'z':
+              _efl_gfx_shape_append_close(obj, pd);
+              content++;
+              break;
+           case 'L':
+              if (!_efl_gfx_path_parse_pair_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_line_to,
+                                               EINA_FALSE))
+                return ;
+              break;
+           case 'l':
+              if (!_efl_gfx_path_parse_pair_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_line_to,
+                                               EINA_TRUE))
+                return ;
+              break;
+           case 'H':
+              if (!_efl_gfx_path_parse_double_to(&content[1],
+                                                 &content,
+                                                 obj, pd,
+                                                 &current_x, current_x, current_y,
+                                                 _efl_gfx_path_append_horizontal_to,
+                                                 EINA_FALSE))
+                return ;
+              break;
+           case 'h':
+              if (!_efl_gfx_path_parse_double_to(&content[1],
+                                                 &content,
+                                                 obj, pd,
+                                                 &current_x, current_x, current_y,
+                                                 _efl_gfx_path_append_horizontal_to,
+                                                 EINA_TRUE))
+                return ;
+              break;
+           case 'V':
+              if (!_efl_gfx_path_parse_double_to(&content[1],
+                                                 &content,
+                                                 obj, pd,
+                                                 &current_y, current_x, current_y,
+                                                 _efl_gfx_path_append_vertical_to,
+                                                 EINA_FALSE))
+                return ;
+              break;
+           case 'v':
+              if (!_efl_gfx_path_parse_double_to(&content[1],
+                                                 &content,
+                                                 obj, pd,
+                                                 &current_y, current_x, current_y,
+                                                 _efl_gfx_path_append_vertical_to,
+                                                 EINA_TRUE))
+                return ;
+              break;
+           case 'C':
+              if (!_efl_gfx_path_parse_six_to(&content[1],
+                                              &content,
+                                              obj, pd,
+                                              &current_x, &current_y,
+                                              _efl_gfx_shape_append_cubic_to,
+                                              EINA_FALSE))
+                return ;
+              break;
+           case 'c':
+              if (!_efl_gfx_path_parse_six_to(&content[1],
+                                              &content,
+                                              obj, pd,
+                                              &current_x, &current_y,
+                                              _efl_gfx_shape_append_cubic_to,
+                                              EINA_TRUE))
+                return ;
+              break;
+           case 'S':
+              if (!_efl_gfx_path_parse_quad_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_scubic_to,
+                                               EINA_FALSE))
+                return ;
+              break;
+           case 's':
+              if (!_efl_gfx_path_parse_quad_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_scubic_to,
+                                               EINA_TRUE))
+                return ;
+              break;
+           case 'Q':
+              if (!_efl_gfx_path_parse_quad_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_quadratic_to,
+                                               EINA_FALSE))
+                return ;
+              break;
+           case 'q':
+              if (!_efl_gfx_path_parse_quad_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_quadratic_to,
+                                               EINA_TRUE))
+                return ;
+              break;
+           case 'T':
+              if (!_efl_gfx_path_parse_pair_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_squadratic_to,
+                                               EINA_FALSE))
+                return ;
+              break;
+           case 't':
+              if (!_efl_gfx_path_parse_pair_to(&content[1],
+                                               &content,
+                                               obj, pd,
+                                               &current_x, &current_y,
+                                               _efl_gfx_shape_append_squadratic_to,
+                                               EINA_TRUE))
+                return ;
+              break;
+           case 'A':
+              if (!_efl_gfx_path_parse_arc_to(&content[1],
+                                              &content,
+                                              obj, pd,
+                                              &current_x, &current_y,
+                                              _efl_gfx_shape_append_arc_to,
+                                              EINA_FALSE))
+                return ;
+              break;
+           case 'a':
+              if (!_efl_gfx_path_parse_arc_to(&content[1],
+                                              &content,
+                                              obj, pd,
+                                              &current_x, &current_y,
+                                              _efl_gfx_shape_append_arc_to,
+                                              EINA_TRUE))
+                return ;
+              break;
+           default:
+              return ;
+          }
+     }
+}
+
+#include "interfaces/efl_gfx_shape.eo.c"
index d04d9c5..8547dc5 100644 (file)
@@ -1,4 +1,4 @@
-interface Efl.Gfx.Shape
+mixin Efl.Gfx.Shape
 {
    legacy_prefix: null;
    properties {
@@ -153,5 +153,147 @@ interface Efl.Gfx.Shape
             const(double) *points; /*@ point list */
          }
       }
+      path_length {
+        get {
+        }
+        values {
+           uint commands;
+           uint points;
+        }
+      }
+      current {
+         get {
+        }
+        values {
+           double x;
+           double y;
+        }
+      }
+      current_ctrl {
+         get {
+        }
+        values {
+           double x;
+           double y;
+        }
+      }
+   }
+   methods {
+      dup {
+         params {
+            @in Eo *dup_from;
+        }
+      }
+      reset {
+      }
+      append_move_to {
+         params {
+           @in double x;
+           @in double y;
+        }
+      }
+      append_line_to {
+         params {
+           @in double x;
+           @in double y;
+        }
+      }
+      append_quadratic_to {
+         params {
+           @in double x;
+           @in double y;
+           @in double ctrl_x;
+           @in double ctrl_y;
+        }
+      }
+      append_squadratic_to {
+         params {
+           @in double x;
+           @in double y;
+        }
+      }
+      append_cubic_to {
+         params {
+           @in double x;
+           @in double y;
+           @in double ctrl_x0;
+           @in double ctrl_y0;
+           @in double ctrl_x1;
+           @in double ctrl_y1;
+        }
+      }
+      append_scubic_to {
+         params {
+           @in double x;
+           @in double y;
+           @in double ctrl_x;
+           @in double ctrl_y;
+        }
+      }
+      append_arc_to {
+         params {
+           @in double x;
+           @in double y;
+           @in double rx;
+           @in double ry;
+           @in double angle;
+           @in bool large_arc;
+           @in bool sweep;
+        }
+      }
+      append_close {
+      }
+      append_circle {
+         params {
+           @in double x;
+           @in double y;
+           @in double radius;
+        }
+      }
+      append_rect {
+         params {
+           @in double x;
+           @in double y;
+           @in double w;
+           @in double h;
+           @in double rx;
+           @in double ry;
+        }
+      }
+      append_svg_path {
+         params {
+           @in const(char)* svg_path_data;
+        }
+      }
+      interpolate {
+         return: bool;
+        params {
+           @in const(Eo)* from;
+           @in const(Eo)* to;
+           @in double pos_map;
+        }
+      }
+      equal_commands {
+         return: bool;
+        params {
+           @in const(Eo)* with;
+        }
+      }
+   }
+   implements {
+      @virtual .stroke_scale.get;
+      @virtual .stroke_scale.set;
+      @virtual .stroke_color.get;
+      @virtual .stroke_color.set;
+      @virtual .stroke_width.get;
+      @virtual .stroke_width.set;
+      @virtual .stroke_location.get;
+      @virtual .stroke_location.set;
+      @virtual .stroke_dash.get;
+      @virtual .stroke_dash.set;
+      @virtual .stroke_cap.get;
+      @virtual .stroke_cap.set;
+      @virtual .stroke_join.get;
+      @virtual .stroke_join.set;
    }
 }
diff --git a/src/lib/efl/interfaces/efl_gfx_stack.eo b/src/lib/efl/interfaces/efl_gfx_stack.eo
new file mode 100644 (file)
index 0000000..a104d0d
--- /dev/null
@@ -0,0 +1,154 @@
+interface Efl.Gfx.Stack {
+   legacy_prefix: null;
+   properties {
+      layer {
+         set {
+            /*@
+            Sets the layer of its canvas that the given object will be part of.
+
+            If you don't use this function, you'll be dealing with an @b unique
+            layer of objects, the default one. Additional layers are handy when
+            you don't want a set of objects to interfere with another set with
+            regard to @b stacking. Two layers are completely disjoint in that
+            matter.
+
+            This is a low-level function, which you'd be using when something
+            should be always on top, for example.
+
+            @warning Be careful, it doesn't make sense to change the layer of
+            smart objects' children. Smart objects have a layer of their own,
+            which should contain all their children objects.
+
+            @see evas_object_layer_get() */
+         }
+         get {
+            /*@
+            Retrieves the layer of its canvas that the given object is part of.
+
+            @return  Number of its layer
+
+            @see evas_object_layer_set() */
+         }
+         values {
+            short l; /*@ The number of the layer to place the object on.
+            Must be between #EVAS_LAYER_MIN and #EVAS_LAYER_MAX. */
+         }
+      }
+      below {
+         get {
+            /*@
+            Get the Evas object stacked right below @p obj
+
+            @return the #Efl_Gfx_Stack directly below @p obj, if any, or @c NULL,
+            if none
+
+            This function will traverse layers in its search, if there are
+            objects on layers below the one @p obj is placed at.
+
+            @see evas_object_layer_get()
+            @see evas_object_layer_set()
+            @see evas_object_below_get() */
+            return: Efl_Gfx_Stack * @warn_unused;
+         }
+      }
+      above {
+         get {
+            /*@
+            Get the Evas object stacked right above @p obj
+
+            @return the #Efl_Gfx_Stack directly above @p obj, if any, or @c NULL,
+            if none
+
+            This function will traverse layers in its search, if there are
+            objects on layers above the one @p obj is placed at.
+
+            @see evas_object_layer_get()
+            @see evas_object_layer_set()
+            @see evas_object_below_get() */
+            return: Efl_Gfx_Stack * @warn_unused;
+         }
+      }
+   }
+   methods {
+      stack_below {
+         /*@
+         Stack @p obj immediately below @p below
+
+         Objects, in a given canvas, are stacked in the order they get added
+         to it.  This means that, if they overlap, the highest ones will
+         cover the lowest ones, in that order. This function is a way to
+         change the stacking order for the objects.
+
+         This function is intended to be used with <b>objects belonging to
+         the same layer</b> in a given canvas, otherwise it will fail (and
+         accomplish nothing).
+
+         If you have smart objects on your canvas and @p obj is a member of
+         one of them, then @p below must also be a member of the same
+         smart object.
+
+         Similarly, if @p obj is not a member of a smart object, @p below
+         must not be either.
+
+         @see evas_object_layer_get()
+         @see evas_object_layer_set()
+         @see evas_object_stack_below() */
+
+         params {
+            @in Efl_Gfx_Stack *below @nonull; /*@ the object below which to stack */
+         }
+      }
+      raise {
+         /*@
+         Raise @p obj to the top of its layer.
+
+         @p obj will, then, be the highest one in the layer it belongs
+         to. Object on other layers won't get touched.
+
+         @see evas_object_stack_above()
+         @see evas_object_stack_below()
+         @see evas_object_lower() */
+
+      }
+      stack_above {
+         /*@
+         Stack @p obj immediately above @p above
+
+         Objects, in a given canvas, are stacked in the order they get added
+         to it.  This means that, if they overlap, the highest ones will
+         cover the lowest ones, in that order. This function is a way to
+         change the stacking order for the objects.
+
+         This function is intended to be used with <b>objects belonging to
+         the same layer</b> in a given canvas, otherwise it will fail (and
+         accomplish nothing).
+
+         If you have smart objects on your canvas and @p obj is a member of
+         one of them, then @p above must also be a member of the same
+         smart object.
+
+         Similarly, if @p obj is not a member of a smart object, @p above
+         must not be either.
+
+         @see evas_object_layer_get()
+         @see evas_object_layer_set()
+         @see evas_object_stack_below() */
+
+         params {
+            @in Efl_Gfx_Stack *above @nonull; /*@ the object above which to stack */
+         }
+      }
+      lower {
+         /*@
+         Lower @p obj to the bottom of its layer.
+
+         @p obj will, then, be the lowest one in the layer it belongs
+         to. Objects on other layers won't get touched.
+
+         @see evas_object_stack_above()
+         @see evas_object_stack_below()
+         @see evas_object_raise() */
+
+      }
+   }
+}
diff --git a/src/lib/efl/interfaces/efl_gfx_view.eo b/src/lib/efl/interfaces/efl_gfx_view.eo
new file mode 100644 (file)
index 0000000..9d609d5
--- /dev/null
@@ -0,0 +1,27 @@
+interface Efl.Gfx.View {
+   legacy_prefix: null;
+   properties {
+      size {
+         set {
+            /*@
+            Sets the size of the given image object.
+
+            This function will scale down or crop the image so that it is
+            treated as if it were at the given size. If the size given is
+            smaller than the image, it will be cropped. If the size given is
+            larger, then the image will be treated as if it were in the upper
+            left hand corner of a larger image that is otherwise transparent. */
+         }
+         get {
+            /*@
+            Retrieves the size of the given image object.
+
+            See @ref evas_object_image_size_set() for more details. */
+         }
+         values {
+            int w; /*@ The new width of the image. */
+            int h; /*@ The new height of the image. */
+         }
+      }
+   }
+}
index 3aecd65..6ae1cb3 100644 (file)
 #include "interfaces/efl_text_properties.eo.c"
 
 #include "interfaces/efl_gfx_base.eo.c"
-#include "interfaces/efl_gfx_shape.eo.c"
-#include "interfaces/efl_gfx_gradient.eo.c"
+#include "interfaces/efl_gfx_stack.eo.c"
+#include "interfaces/efl_gfx_fill.eo.c"
+#include "interfaces/efl_gfx_view.eo.c"
+
+#include "interfaces/efl_gfx_gradient_base.eo.c"
 #include "interfaces/efl_gfx_gradient_linear.eo.c"
 #include "interfaces/efl_gfx_gradient_radial.eo.c"
+
+EAPI const Eo_Event_Description _EFL_GFX_CHANGED =
+  EO_EVENT_DESCRIPTION("Graphics changed", "The visual representation of the object changed");
+
+EAPI const Eo_Event_Description _EFL_GFX_PATH_CHANGED =
+  EO_EVENT_DESCRIPTION("Graphics path changed", "The path of a shape object changed");
index 35a155b..8275130 100644 (file)
@@ -313,6 +313,11 @@ typedef Eo                 Evas_Object;
 /* This define is used in H files generated by Eolian */
 #define _EVAS_OBJECT_EO_CLASS_TYPE
 
+/**
+ * Type of abstract VG node
+ */
+typedef Eo      Efl_VG;
+
 typedef void                        Evas_Performance; /**< An Evas Performance handle */
 typedef struct _Evas_Modifier       Evas_Modifier; /**< An opaque type containing information on which modifier keys are registered in an Evas canvas */
 typedef struct _Evas_Lock           Evas_Lock; /**< An opaque type containing information on which lock keys are registered in an Evas canvas */
@@ -433,15 +438,13 @@ typedef enum _Evas_Alloc_Error
    EVAS_ALLOC_ERROR_RECOVERED = 2 /**< Allocation succeeded, but extra memory had to be found by freeing up speculative resources */
 } Evas_Alloc_Error; /**< Possible allocation errors returned by evas_alloc_error() */
 
-typedef enum _Evas_Fill_Spread
-{
-   EVAS_TEXTURE_REFLECT = 0, /**< image fill tiling mode - tiling reflects */
-   EVAS_TEXTURE_REPEAT = 1, /**< tiling repeats */
-   EVAS_TEXTURE_RESTRICT = 2, /**< tiling clamps - range offset ignored */
-   EVAS_TEXTURE_RESTRICT_REFLECT = 3, /**< tiling clamps and any range offset reflects */
-   EVAS_TEXTURE_RESTRICT_REPEAT = 4, /**< tiling clamps and any range offset repeats */
-   EVAS_TEXTURE_PAD = 5 /**< tiling extends with end values */
-} Evas_Fill_Spread; /**< Fill types used for evas_object_image_fill_spread_set() */
+typedef Efl_Gfx_Fill_Spread Evas_Fill_Spread;
+#define EVAS_TEXTURE_REFLECT EFL_GFX_FILL_REFLECT
+#define EVAS_TEXTURE_REPEAT EFL_GFX_FILL_REPEAT
+#define EVAS_TEXTURE_RESTRICT EFL_GFX_FILL_RESTRICT
+#define EVAS_TEXTURE_RESTRICT_REFLECT EFL_GFX_FILL_RESTRICT_REFLECT
+#define EVAS_TEXTURE_RESTRICT_REPEAT EFL_GFX_FILL_RESTRICT_REPEAT
+#define EVAS_TEXTURE_PAD EFL_GFX_FILL_PAD
 
 typedef enum _Evas_Pixel_Import_Pixel_Format
 {
index 9f877d4..380585f 100644 (file)
@@ -826,10 +826,10 @@ typedef Eo      Evas_VG_Node;
  * @}
  */
 
-#include "canvas/evas_vg_node.eo.h"
-#include "canvas/evas_vg_container.eo.h"
-#include "canvas/evas_vg_shape.eo.h"
-#include "canvas/evas_vg_gradient.eo.h"
-#include "canvas/evas_vg_gradient_linear.eo.h"
-#include "canvas/evas_vg_gradient_radial.eo.h"
-#include "canvas/evas_vg_image.eo.h"
+#include "canvas/efl_vg_base.eo.h"
+#include "canvas/efl_vg_container.eo.h"
+#include "canvas/efl_vg_shape.eo.h"
+#include "canvas/efl_vg_gradient.eo.h"
+#include "canvas/efl_vg_gradient_linear.eo.h"
+#include "canvas/efl_vg_gradient_radial.eo.h"
+#include "canvas/efl_vg_image.eo.h"
index 87e78d0..19bc9d3 100644 (file)
@@ -1555,14 +1555,81 @@ EAPI Evas_Object *evas_object_rectangle_add(Evas *e) EINA_WARN_UNUSED_RESULT EIN
  */
 EAPI Evas_Object *evas_object_vg_add(Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
 
-#include "canvas/evas_vg_node.eo.legacy.h"
 #include "canvas/evas_vg.eo.legacy.h"
-#include "canvas/evas_vg_shape.eo.legacy.h"
-#include "canvas/evas_vg_gradient.eo.legacy.h"
-#include "canvas/evas_vg_gradient_linear.eo.legacy.h"
-#include "canvas/evas_vg_gradient_radial.eo.legacy.h"
-#include "canvas/evas_vg_image.eo.legacy.h"
-#include "canvas/evas_vg_root_node.eo.legacy.h"
+
+EAPI Eina_Bool evas_vg_node_visible_get(Eo *obj);
+EAPI void evas_vg_node_visible_set(Eo *obj, Eina_Bool v);
+EAPI void evas_vg_node_color_get(Eo *obj, int *r, int *g, int *b, int *a);
+EAPI void evas_vg_node_color_set(Eo *obj, int r, int g, int b, int a);
+EAPI void evas_vg_node_geometry_get(Eo *obj, int *x, int *y, int *w, int *h);
+EAPI void evas_vg_node_geometry_set(Eo *obj, int x, int y, int w, int h);
+EAPI void evas_vg_node_stack_below(Eo *obj, Eo *below);
+EAPI void evas_vg_node_stack_above(Eo *obj, Eo *above);
+EAPI void evas_vg_node_raise(Eo *obj);
+EAPI void evas_vg_node_lower(Eo *obj);
+
+#include "canvas/efl_vg_base.eo.legacy.h"
+
+EAPI double evas_vg_shape_stroke_scale_get(Eo *obj);
+EAPI void evas_vg_shape_stroke_scale_set(Eo *obj, double s);
+EAPI void evas_vg_shape_stroke_color_get(Eo *obj, int *r, int *g, int *b, int *a);
+EAPI void evas_vg_shape_stroke_color_set(Eo *obj, int r, int g, int b, int a);
+EAPI double evas_vg_shape_stroke_width_get(Eo *obj);
+EAPI void evas_vg_shape_stroke_width_set(Eo *obj, double w);
+EAPI double evas_vg_shape_stroke_location_get(Eo *obj);
+EAPI void evas_vg_shape_stroke_location_set(Eo *obj, double centered);
+EAPI void evas_vg_shape_stroke_dash_get(Eo *obj, const Efl_Gfx_Dash **dash, unsigned int *length);
+EAPI void evas_vg_shape_stroke_dash_set(Eo *obj, const Efl_Gfx_Dash *dash, unsigned int length);
+EAPI Efl_Gfx_Cap evas_vg_shape_stroke_cap_get(Eo *obj);
+EAPI void evas_vg_shape_stroke_cap_set(Eo *obj, Efl_Gfx_Cap c);
+EAPI Efl_Gfx_Join evas_vg_shape_stroke_join_get(Eo *obj);
+EAPI void evas_vg_shape_stroke_join_set(Eo *obj, Efl_Gfx_Join j);
+EAPI void evas_vg_shape_shape_path_set(Eo *obj, const Efl_Gfx_Path_Command *op, const double *points);
+EAPI void evas_vg_shape_shape_path_get(Eo *obj, const Efl_Gfx_Path_Command **op, const double **points);
+EAPI void evas_vg_shape_shape_path_length_get(Eo *obj, unsigned int *commands, unsigned int *points);
+EAPI void evas_vg_shape_shape_current_get(Eo *obj, double *x, double *y);
+EAPI void evas_vg_shape_shape_current_ctrl_get(Eo *obj, double *x, double *y);
+EAPI void evas_vg_shape_shape_dup(Eo *obj, Eo *dup_from);
+EAPI void evas_vg_shape_shape_reset(Eo *obj);
+EAPI void evas_vg_shape_shape_append_move_to(Eo *obj, double x, double y);
+EAPI void evas_vg_shape_shape_append_line_to(Eo *obj, double x, double y);
+EAPI void evas_vg_shape_shape_append_quadratic_to(Eo *obj, double x, double y, double ctrl_x, double ctrl_y);
+EAPI void evas_vg_shape_shape_append_squadratic_to(Eo *obj, double x, double y);
+EAPI void evas_vg_shape_shape_append_cubic_to(Eo *obj, double x, double y, double ctrl_x0, double ctrl_y0, double ctrl_x1, double ctrl_y1);
+EAPI void evas_vg_shape_shape_append_scubic_to(Eo *obj, double x, double y, double ctrl_x, double ctrl_y);
+EAPI void evas_vg_shape_shape_append_arc_to(Eo *obj, double x, double y, double rx, double ry, double angle, Eina_Bool large_arc, Eina_Bool sweep);
+EAPI void evas_vg_shape_shape_append_close(Eo *obj);
+EAPI void evas_vg_shape_shape_append_circle(Eo *obj, double x, double y, double radius);
+EAPI void evas_vg_shape_shape_append_rect(Eo *obj, double x, double y, double w, double h, double rx, double ry);
+EAPI void evas_vg_shape_shape_append_svg_path(Eo *obj, const char *svg_path_data);
+EAPI Eina_Bool evas_vg_shape_shape_interpolate(Eo *obj, const Eo *from, const Eo *to, double pos_map);
+EAPI Eina_Bool evas_vg_shape_shape_equal_commands(Eo *obj, const Eo *with);
+
+#include "canvas/efl_vg_shape.eo.legacy.h"
+
+EAPI void evas_vg_gradient_stop_set(Eo *obj, const Efl_Gfx_Gradient_Stop *colors, unsigned int length);
+EAPI void evas_vg_gradient_stop_get(Eo *obj, const Efl_Gfx_Gradient_Stop **colors, unsigned int *length);
+EAPI void evas_vg_gradient_spread_set(Eo *obj, Efl_Gfx_Gradient_Spread s);
+EAPI Efl_Gfx_Gradient_Spread evas_vg_gradient_spread_get(Eo *obj);
+
+#include "canvas/efl_vg_gradient.eo.legacy.h"
+
+EAPI void evas_vg_gradient_linear_start_set(Eo *obj, double x, double y);
+EAPI void evas_vg_gradient_linear_start_get(Eo *obj, double *x, double *y);
+EAPI void evas_vg_gradient_linear_end_set(Eo *obj, double x, double y);
+EAPI void evas_vg_gradient_linear_end_get(Eo *obj, double *x, double *y);
+
+#include "canvas/efl_vg_gradient_linear.eo.legacy.h"
+
+EAPI void evas_vg_gradient_radial_center_set(Eo *obj, double x, double y);
+EAPI void evas_vg_gradient_radial_center_get(Eo *obj, double *x, double *y);
+EAPI void evas_vg_gradient_radial_radius_set(Eo *obj, double r);
+EAPI double evas_vg_gradient_radial_radius_get(Eo *obj);
+EAPI void evas_vg_gradient_radial_focal_set(Eo *obj, double x, double y);
+EAPI void evas_vg_gradient_radial_focal_get(Eo *obj, double *x, double *y);
+
+#include "canvas/efl_vg_gradient_radial.eo.legacy.h"
+>>>>>>> f359123... ector : integration of ector library in efl1.30.0 branch for tizen2.4
 
 /**
  * @}
diff --git a/src/lib/evas/canvas/efl_vg_base.eo b/src/lib/evas/canvas/efl_vg_base.eo
new file mode 100644 (file)
index 0000000..2b8d9e7
--- /dev/null
@@ -0,0 +1,106 @@
+abstract Efl.VG.Base (Eo.Base, Efl.Gfx.Base, Efl.Gfx.Stack)
+{
+   eo_prefix: efl_vg;
+   legacy_prefix: evas_vg_node;
+   properties {
+      transformation {
+         set {
+            /*@
+             Sets the transformation matrix to be used for this node object.
+             @since 1.14
+            */
+         }
+         get {
+            /*@
+             Gets the transformation matrix used for this node object.
+             @since 1.14
+            */
+         }
+         values {
+            const(Eina_Matrix3) *m; /*@ transformation matrix */
+         }
+      }
+      origin {
+         set {
+            /*@
+             Sets the origin position of this node object. This origin position
+             affects to node transformation
+             @since 1.14
+            */
+         }
+         get {
+            /*@
+             Gets the origin position of this node object.
+             @since 1.14
+            */
+         }
+         values {
+            double x; /* @origin x position */
+            double y; /* @origin y position */
+         }
+      }
+      mask {
+         set {
+        }
+        get {
+        }
+        values {
+           Efl_VG *m;
+        }
+      }
+/*      quality {
+         set {
+        }
+        get {
+        }
+        values {
+           Evas_VG_Quality q;
+        }
+      } */
+   }
+   methods {
+      bound_get {
+         /*@
+          Give the bounding box in screen coordinate as being drawn.
+          It will start as the control box until it is refined once the shape
+          is computed.
+          @since 1.14
+         */
+         return: bool @warn_unused;
+         params {
+            @out Eina_Rectangle r; /*@ bounding box to be returned */
+         }
+      }
+      original_bound_get {
+         /*@
+          Give the bounding box in screen coordinate as defined in
+          the file or at the insertion of the object (before any scaling).
+          @since 1.14
+         */
+         return: bool @warn_unused;
+         params {
+            @out Eina_Rectangle r; /*@ original bounding box to be returned */
+         }
+      }
+   }
+   implements {
+      Eo.Base.parent.set;
+      Eo.Base.constructor;
+      Efl.Gfx.Base.visible.set;
+      Efl.Gfx.Base.visible.get;
+      Efl.Gfx.Base.color.set;
+      Efl.Gfx.Base.color.get;
+      Efl.Gfx.Base.color_part.set;
+      Efl.Gfx.Base.color_part.get;
+      Efl.Gfx.Base.size.get;
+      Efl.Gfx.Base.position.set;
+      Efl.Gfx.Base.position.get;
+      Efl.Gfx.Stack.below.get;
+      Efl.Gfx.Stack.above.get;
+      Efl.Gfx.Stack.stack_below;
+      Efl.Gfx.Stack.stack_above;
+      Efl.Gfx.Stack.raise;
+      Efl.Gfx.Stack.lower;
+      @virtual .bound_get;
+   }
+}
\ No newline at end of file
diff --git a/src/lib/evas/canvas/efl_vg_container.eo b/src/lib/evas/canvas/efl_vg_container.eo
new file mode 100644 (file)
index 0000000..4d8a085
--- /dev/null
@@ -0,0 +1,9 @@
+class Efl.VG.Container (Efl.VG.Base)
+{
+   legacy_prefix: evas_vg_container;
+   implements {
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+      Efl.VG.Base.bound_get;
+   }
+}
diff --git a/src/lib/evas/canvas/efl_vg_gradient.eo b/src/lib/evas/canvas/efl_vg_gradient.eo
new file mode 100644 (file)
index 0000000..de78039
--- /dev/null
@@ -0,0 +1,10 @@
+abstract Efl.VG.Gradient (Efl.VG.Base, Efl.Gfx.Gradient.Base)
+{
+   legacy_prefix: evas_vg_gradient;
+   implements {
+      Efl.Gfx.Gradient.Base.stop.set;
+      Efl.Gfx.Gradient.Base.stop.get;
+      Efl.Gfx.Gradient.Base.spread.set;
+      Efl.Gfx.Gradient.Base.spread.get;
+   }
+}
diff --git a/src/lib/evas/canvas/efl_vg_gradient_linear.eo b/src/lib/evas/canvas/efl_vg_gradient_linear.eo
new file mode 100644 (file)
index 0000000..bc9c664
--- /dev/null
@@ -0,0 +1,12 @@
+class Efl.VG.Gradient_Linear (Efl.VG.Gradient, Efl.Gfx.Gradient.Linear)
+{
+   legacy_prefix: evas_vg_gradient_linear;
+   implements {
+      Efl.Gfx.Gradient.Linear.start.set;
+      Efl.Gfx.Gradient.Linear.start.get;
+      Efl.Gfx.Gradient.Linear.end.set;
+      Efl.Gfx.Gradient.Linear.end.get;
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+   }
+}
diff --git a/src/lib/evas/canvas/efl_vg_gradient_radial.eo b/src/lib/evas/canvas/efl_vg_gradient_radial.eo
new file mode 100644 (file)
index 0000000..0d60589
--- /dev/null
@@ -0,0 +1,14 @@
+class Efl.VG.Gradient_Radial (Efl.VG.Gradient, Efl.Gfx.Gradient.Radial)
+{
+   legacy_prefix: evas_vg_gradient_radial;
+   implements {
+      Efl.Gfx.Gradient.Radial.center.set;
+      Efl.Gfx.Gradient.Radial.center.get;
+      Efl.Gfx.Gradient.Radial.radius.set;
+      Efl.Gfx.Gradient.Radial.radius.get;
+      Efl.Gfx.Gradient.Radial.focal.set;
+      Efl.Gfx.Gradient.Radial.focal.get;     
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+   }
+}
diff --git a/src/lib/evas/canvas/efl_vg_image.eo b/src/lib/evas/canvas/efl_vg_image.eo
new file mode 100644 (file)
index 0000000..62d7451
--- /dev/null
@@ -0,0 +1,35 @@
+class Efl.VG.Image (Efl.VG.Base, Efl.File)
+{
+   legacy_prefix: evas_vg_image;
+   properties {
+      position {
+         set {
+        }
+        get {
+        }
+        values {
+           int x;
+           int y;
+        }
+      }
+      size {
+         set {
+        }
+        get {
+        }
+        values {
+           uint w;
+           uint h;
+        }
+      }
+      // FIXME: add aspect ratio following SVG specification
+   }
+   implements {
+      Efl.File.file.set;
+      Efl.File.file.get;
+      Efl.File.mmap.set;
+      Efl.File.mmap.get;
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+   }
+}
\ No newline at end of file
diff --git a/src/lib/evas/canvas/efl_vg_root_node.eo b/src/lib/evas/canvas/efl_vg_root_node.eo
new file mode 100644 (file)
index 0000000..685bf7e
--- /dev/null
@@ -0,0 +1,8 @@
+class Efl.VG.Root_Node (Efl.VG.Container)
+{
+   legacy_prefix: evas_vg_root_node;
+   implements {
+      Eo.Base.parent.set;
+      Eo.Base.constructor;
+   }
+}
diff --git a/src/lib/evas/canvas/efl_vg_shape.eo b/src/lib/evas/canvas/efl_vg_shape.eo
new file mode 100644 (file)
index 0000000..ab6468c
--- /dev/null
@@ -0,0 +1,47 @@
+class Efl.VG.Shape (Efl.VG.Base, Efl.Gfx.Shape)
+{
+   legacy_prefix: evas_vg_shape;
+   properties {
+      fill {
+         set {
+        }
+        get {
+        }
+        values {
+           Efl_VG *f;
+        }
+      }
+      stroke_fill {
+         set {
+        }
+        get {
+        }
+        values {
+           Efl_VG *f;
+        }
+      }
+      stroke_marker {
+         set {
+        }
+        get {
+        }
+        values {
+           Efl_VG *m;
+        }
+      }
+   }
+   implements {
+      Efl.Gfx.Shape.stroke_scale;
+      Efl.Gfx.Shape.stroke_color;
+      Efl.Gfx.Shape.stroke_width;
+      Efl.Gfx.Shape.stroke_location;
+      Efl.Gfx.Shape.stroke_dash;
+      Efl.Gfx.Shape.stroke_cap;
+      Efl.Gfx.Shape.stroke_join;
+      Efl.Gfx.Base.color_part.set;
+      Efl.Gfx.Base.color_part.get;
+      Efl.VG.Base.bound_get;
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+   }
+}
index daaebf8..afbe045 100644 (file)
@@ -2,7 +2,7 @@
 #include "evas_private.h"
 
 #include "evas_vg_private.h"
-#include "evas_vg_root_node.eo.h"
+#include "efl_vg_root_node.eo.h"
 
 #define MY_CLASS EVAS_VG_CLASS
 
@@ -16,8 +16,8 @@ typedef struct _Evas_VG_Data      Evas_VG_Data;
 
 struct _Evas_VG_Data
 {
-   void         *engine_data;
-   Evas_VG_Node *root;
+   void   *engine_data;
+   Efl_VG *root;
 
    /* Opening an SVG file (could actually be inside an eet section */
    Eina_File    *f;
@@ -25,8 +25,7 @@ struct _Evas_VG_Data
 
    Eina_Rectangle fill;
 
-   int width, height;
-   void          *backing_store;
+   unsigned int width, height;
 };
 
 static void evas_object_vg_render(Evas_Object *eo_obj,
@@ -90,7 +89,7 @@ evas_object_vg_add(Evas *e)
    return eo_obj;
 }
 
-Evas_VG_Node *
+Efl_VG *
 _evas_vg_root_node_get(Eo *obj EINA_UNUSED, Evas_VG_Data *pd)
 {
    return pd->root;
@@ -99,11 +98,6 @@ _evas_vg_root_node_get(Eo *obj EINA_UNUSED, Evas_VG_Data *pd)
 void
 _evas_vg_eo_base_destructor(Eo *eo_obj, Evas_VG_Data *pd)
 {
-   if (pd->backing_store) {
-      Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
-      obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
-                                                  pd->backing_store);
-   }
    eo_unref(pd->root);
    eo_do_super(eo_obj, MY_CLASS, eo_destructor());
 }
@@ -122,7 +116,7 @@ _evas_vg_eo_base_constructor(Eo *eo_obj, Evas_VG_Data *pd)
    obj->type = o_type;
 
    /* root node */
-   pd->root = eo_add(EVAS_VG_ROOT_NODE_CLASS, eo_obj);
+   pd->root = eo_add(EFL_VG_ROOT_NODE_CLASS, eo_obj);
    eo_ref(pd->root);
 
    eo_do(eo_obj, parent = eo_parent_get());
@@ -131,28 +125,28 @@ _evas_vg_eo_base_constructor(Eo *eo_obj, Evas_VG_Data *pd)
 
 static void
 _evas_vg_render(Evas_Object_Protected_Data *obj,
-                void *output, void *context, void *surface, Evas_VG_Node *node,
-                Eina_Array *clips, int x, int y, Eina_Bool do_async)
+                void *output, void *context, void *surface, Efl_VG *n,
+                Eina_Array *clips, Eina_Bool do_async)
 {
-    // FIXME if the class is not container ,
-    // some times its returning garbage container data.
-    if (eo_isa(node, EVAS_VG_CONTAINER_CLASS))
+   Efl_VG_Container_Data *vd = eo_data_scope_get(n, EFL_VG_CONTAINER_CLASS);
+
+   if (eo_isa(n, EFL_VG_CONTAINER_CLASS))
      {
-        Evas_VG_Container_Data *cd = eo_data_scope_get(node,
-                                                       EVAS_VG_CONTAINER_CLASS);
-        Evas_VG_Node *child;
+        Efl_VG *child;
         Eina_List *l;
 
-        EINA_LIST_FOREACH(cd->children, l, child)
-           _evas_vg_render(obj, output, context, surface, child, clips, x, y,
-                           do_async);
+        EINA_LIST_FOREACH(vd->children, l, child)
+          _evas_vg_render(obj,
+                          output, context, surface, child,
+                          clips, do_async);
      }
    else
      {
-        Evas_VG_Node_Data *nd = eo_data_scope_get(node, EVAS_VG_NODE_CLASS);
-        obj->layer->evas->engine.func->ector_draw(output, context, surface,
-                                                  nd->renderer, clips, x, y,
-                                                  do_async);
+        Efl_VG_Base_Data *nd;
+
+        nd = eo_data_scope_get(n, EFL_VG_BASE_CLASS);
+
+        obj->layer->evas->engine.func->ector_renderer_draw(output, context, surface, nd->renderer, clips, do_async);
      }
 }
 
@@ -165,11 +159,6 @@ evas_object_vg_render(Evas_Object *eo_obj EINA_UNUSED,
 {
    Evas_VG_Data *vd = type_private_data;
 
-   vd->backing_store = obj->layer->evas->engine.func->ector_begin(obj->layer->evas->engine.data.output,
-                                                                  vd->backing_store, 
-                                                                  obj->cur->geometry.w,
-                                                                  obj->cur->geometry.h);
-
    // FIXME: Set context (that should affect Ector_Surface) and
    // then call Ector_Renderer render from bottom to top. Get the
    // Ector_Surface that match the output from Evas engine API.
@@ -190,23 +179,12 @@ evas_object_vg_render(Evas_Object *eo_obj EINA_UNUSED,
                                                            context);
    obj->layer->evas->engine.func->context_render_op_set(output, context,
                                                         obj->cur->render_op);
-   if (!vd->backing_store) {
+   obj->layer->evas->engine.func->ector_begin(output, context, surface,
+                                              obj->cur->geometry.x + x, obj->cur->geometry.y + y,
+                                              do_async);
    _evas_vg_render(obj, output, context, surface, vd->root, NULL,
-                   obj->cur->geometry.x + x, obj->cur->geometry.y + y,
                    do_async);
- } else {
-
-   _evas_vg_render(obj, output, context, vd->backing_store, vd->root, NULL,
-                   0 , 0,
-                   do_async);
-   obj->layer->evas->engine.func->image_dirty_region(obj->layer->evas->engine.data.output, vd->backing_store, 
-                                                      0, 0, 0, 0);
-   obj->layer->evas->engine.func->image_draw(output, context, surface,
-                                             vd->backing_store, 0, 0,
-                                             obj->cur->geometry.w, obj->cur->geometry.h, obj->cur->geometry.x + x, 
-                                             obj->cur->geometry.y + y, obj->cur->geometry.w, obj->cur->geometry.h, 
-                                             EINA_TRUE, do_async);
- }
+   obj->layer->evas->engine.func->ector_end(output, context, surface, do_async);
 }
 
 static void
@@ -215,14 +193,15 @@ evas_object_vg_render_pre(Evas_Object *eo_obj,
                           void *type_private_data)
 {
    Evas_VG_Data *vd = type_private_data;
+   Efl_VG_Base_Data *rnd;
    Evas_Public_Data *e = obj->layer->evas;
    int is_v, was_v;
-   Ector_Surface *surface;
-   Eina_Bool change = EINA_FALSE;
+   Ector_Surface *s;
 
    /* dont pre-render the obj twice! */
    if (obj->pre_render_done) return;
    obj->pre_render_done = EINA_TRUE;
+
    /* 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. */
@@ -244,47 +223,44 @@ evas_object_vg_render_pre(Evas_Object *eo_obj,
    if (!(is_v | was_v)) goto done;
 
    // FIXME: handle damage only on changed renderer.
-   surface = e->engine.func->ector_get(e->engine.data.output);
-   if (surface)
-     change = _evas_vg_render_pre(vd->root, surface, NULL);
-
-   if (change)
+   s = e->engine.func->ector_get(e->engine.data.output);
+   if (vd->root && s)
+     _evas_vg_render_pre(vd->root, s, NULL);
+
+   // FIXME: for now the walking Evas_VG_Node tree doesn't trigger any damage
+   // So just forcing it here if necessary
+   rnd = eo_data_scope_get(vd->root, EFL_VG_BASE_CLASS);
+   if (rnd->changed)
      {
-        evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
-                                            eo_obj, obj);
+        rnd->changed = EINA_FALSE;
+        evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
         goto done;
      }
 
    if (is_v != was_v)
      {
-        evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes,
-                                              eo_obj, is_v, was_v);
+        evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, eo_obj, is_v, was_v);
         goto done;
      }
-
    if (obj->changed_map || obj->changed_src_visible)
      {
-        evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
-                                            eo_obj, obj);
+        evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
         goto done;
      }
    /* it's not visible - we accounted for it appearing or not so just abort */
    if (!is_v) goto done;
    /* clipper changed this is in addition to anything else for obj */
-   evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes,
-                                         eo_obj);
+   evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes, eo_obj);
    /* if we restacked (layer or just within a layer) and don't clip anyone */
    if ((obj->restack) && (!obj->clip.clipees))
      {
-        evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
-                                            eo_obj, obj);
+        evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
         goto done;
      }
    /* if it changed render op */
    if (obj->cur->render_op != obj->prev->render_op)
      {
-        evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
-                                            eo_obj, obj);
+        evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
         goto done;
      }
    /* if it changed color */
@@ -293,8 +269,7 @@ evas_object_vg_render_pre(Evas_Object *eo_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,
-                                            eo_obj, obj);
+        evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, eo_obj, obj);
         goto done;
      }
    /* if it changed geometry - and obviously not visibility or color */
@@ -343,9 +318,8 @@ evas_object_vg_render_pre(Evas_Object *eo_obj,
          y + obj->layer->evas->framespace.y,
          w, h);
      }
-done:
-   evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes,
-                                         eo_obj, is_v, was_v);
+   done:
+   evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, eo_obj, is_v, was_v);
 }
 
 static void
@@ -468,24 +442,24 @@ _evas_vg_efl_file_file_get(Eo *obj, Evas_VG_Data *pd EINA_UNUSED,
 }
 
 void
-_evas_vg_size_get(Eo *obj EINA_UNUSED, Evas_VG_Data *pd,
-                  unsigned int *w, unsigned int *h)
+_evas_vg_efl_gfx_view_size_get(Eo *obj EINA_UNUSED, Evas_VG_Data *pd,
+                               int *w, int *h)
 {
    if (w) *w = pd->width;
    if (h) *h = pd->height;
 }
 
 void
-_evas_vg_size_set(Eo *obj EINA_UNUSED, Evas_VG_Data *pd,
-                  unsigned int w, unsigned int h)
+_evas_vg_efl_gfx_view_size_set(Eo *obj EINA_UNUSED, Evas_VG_Data *pd,
+                               int w, int h)
 {
    pd->width = w;
    pd->height = h;
 }
 
 void
-_evas_vg_fill_set(Eo *obj EINA_UNUSED, Evas_VG_Data *pd,
-                  Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+_evas_vg_efl_gfx_fill_fill_set(Eo *obj EINA_UNUSED, Evas_VG_Data *pd,
+                               int x, int y, int w, int h)
 {
    pd->fill.x = x;
    pd->fill.y = y;
@@ -494,8 +468,8 @@ _evas_vg_fill_set(Eo *obj EINA_UNUSED, Evas_VG_Data *pd,
 }
 
 void
-_evas_vg_fill_get(Eo *obj EINA_UNUSED, Evas_VG_Data *pd,
-                  Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+_evas_vg_efl_gfx_fill_fill_get(Eo *obj EINA_UNUSED, Evas_VG_Data *pd,
+                               int *x, int *y, int *w, int *h)
 {
    if (x) *x = pd->fill.x;
    if (y) *y = pd->fill.y;
index da307a2..8247f46 100644 (file)
@@ -1,4 +1,4 @@
-class Evas.VG (Evas.Object, Efl.File)
+class Evas.VG (Evas.Object, Efl.File, Efl.Gfx.Fill, Efl.Gfx.View)
 {
    legacy_prefix: evas_object_vg;
    eo_prefix: evas_obj_vg;
@@ -15,76 +15,7 @@ class Evas.VG (Evas.Object, Efl.File)
             */
          }
          values {
-            Evas_VG_Node *container; /*@ Root node of the VG canvas */
-         }
-      }
-      size {
-         get {
-            /*@
-             Get the size as defined in the original data before any scaling
-             (as in the file or when the object were added).
-             @since 1.14
-             */
-         }
-         set {
-            /*@
-             Set the size defined in the original data before any scaling
-             (as in the file or when the object were added).
-             @since 1.14
-             */         
-         }
-         values {
-            uint w; /*@ width of the vg object */
-            uint h; /*@ height of the vg object */
-         }
-      }
-      fill {
-         set {
-            /*@
-             Set how to fill an image object's drawing rectangle given the
-             (real) image bound to it. Note that if @p w or @p h are smaller
-             than the dimensions of @p obj, the displayed image will be
-             @b tiled around the object's area. To have only one copy of the
-             bound image drawn, @p x and @p y must be 0 and @p w and @p h
-             need to be the exact width and height of the image object
-             itself, respectively. See the following image to better
-             understand the effects of this call. On this diagram, both
-             image object and original image source have @c a x @c a
-             dimensions and the image itself is a circle, with empty space
-             around it:
-
-             @image html image-fill.png
-             @image rtf image-fill.png
-             @image latex image-fill.eps
-             @warning The default values for the fill parameters are
-                      @p x = 0, @p y = 0, @p w = 0 and @p h = 0. Thus,
-                      if you're not using the evas_object_image_filled_add()
-                      helper and want your image displayed, you'll have to
-                      set valid values with this function on your object.
-             @note evas_object_image_filled_set() is a helper function which
-                   will @b override the values set here automatically, for
-                   you, in a given way.
-             @sine 1.14 */
-         }
-         get {
-            /*@
-             Retrieve how an image object is to fill its drawing rectangle,
-             given the (real) image bound to it.
-
-             @note Use @c NULL pointers on the fill components you're not
-                   interested in: they'll be ignored by the function.
-                   See @ref evas_object_image_fill_set() for more details.
-             @since 1.14 */
-         }
-         values {
-            Evas_Coord x; /*@ The x coordinate (from the top left corner of
-                            the bound image) to start drawing from. */
-            Evas_Coord y; /*@ The y coordinate (from the top left corner of
-                            the bound image) to start drawing from. */
-            Evas_Coord w; /*@ The width the bound image will be displayed
-                            at. */
-            Evas_Coord h; /*@ The height the bound image will be displayed
-                            at. */
+            Efl_VG *container; /*@ Root node of the VG canvas */
          }
       }
    }
@@ -95,5 +26,9 @@ class Evas.VG (Evas.Object, Efl.File)
       Efl.File.file.get;
       Efl.File.mmap.set;
       Efl.File.mmap.get;
+      Efl.Gfx.Fill.fill.set;
+      Efl.Gfx.Fill.fill.get;
+      Efl.Gfx.View.size.set;
+      Efl.Gfx.View.size.get;
    }
 }
index 10f630e..fdf8124 100644 (file)
@@ -3,51 +3,52 @@
 
 #include "evas_vg_private.h"
 
-#define MY_CLASS EVAS_VG_CONTAINER_CLASS
+#define MY_CLASS EFL_VG_CONTAINER_CLASS
 
-static Eina_Bool
-_evas_vg_container_render_pre(Eo *obj EINA_UNUSED,
-                              Eina_Matrix3 *parent,
-                              Ector_Surface *s,
-                              void *data,
-                              Evas_VG_Node_Data *nd)
+static void
+_efl_vg_container_render_pre(Eo *obj EINA_UNUSED,
+                             Eina_Matrix3 *parent,
+                             Ector_Surface *s,
+                             void *data,
+                             Efl_VG_Base_Data *nd)
 {
-   Evas_VG_Container_Data *pd = data;
+   Efl_VG_Container_Data *pd = data;
    Eina_List *l;
    Eo *child;
-   Eina_Bool change = EINA_FALSE;
-   EVAS_VG_COMPUTE_MATRIX(current, parent, nd);
 
-   EINA_LIST_FOREACH(pd->children, l, child)
-     change |= _evas_vg_render_pre(child, s, current);
+   if (!nd->changed) return ;
+   nd->changed = EINA_FALSE;
 
-   return change;
+   EFL_VG_COMPUTE_MATRIX(current, parent, nd);
+
+   EINA_LIST_FOREACH(pd->children, l, child)
+     _evas_vg_render_pre(child, s, current);
 }
 
 static void
-_evas_vg_container_eo_base_constructor(Eo *obj,
-                                       Evas_VG_Container_Data *pd)
+_efl_vg_container_eo_base_constructor(Eo *obj,
+                                      Efl_VG_Container_Data *pd)
 {
-   Evas_VG_Node_Data *nd;
+   Efl_VG_Base_Data *nd;
 
    eo_do_super(obj, MY_CLASS, eo_constructor());
 
-   nd = eo_data_scope_get(obj, EVAS_VG_NODE_CLASS);
-   nd->render_pre = &_evas_vg_container_render_pre;
+   nd = eo_data_scope_get(obj, EFL_VG_BASE_CLASS);
+   nd->render_pre = _efl_vg_container_render_pre;
    nd->data = pd;
 }
 
 static void
-_evas_vg_container_eo_base_destructor(Eo *obj,
-                                      Evas_VG_Container_Data *pd EINA_UNUSED)
+_efl_vg_container_eo_base_destructor(Eo *obj,
+                                     Efl_VG_Container_Data *pd EINA_UNUSED)
 {
    eo_do_super(obj, MY_CLASS, eo_destructor());
 }
 
 static Eina_Bool
-_evas_vg_container_evas_vg_node_bound_get(Eo *obj EINA_UNUSED,
-                                          Evas_VG_Container_Data *pd,
-                                          Eina_Rectangle *r)
+_efl_vg_container_efl_vg_base_bound_get(Eo *obj EINA_UNUSED,
+                                        Efl_VG_Container_Data *pd,
+                                        Eina_Rectangle *r)
 {
    Eina_Rectangle s;
    Eina_Bool first = EINA_TRUE;
@@ -62,12 +63,12 @@ _evas_vg_container_evas_vg_node_bound_get(Eo *obj EINA_UNUSED,
      {
         if (first)
           {
-             eo_do(child, evas_vg_node_bound_get(r));
+             eo_do(child, efl_vg_bound_get(r));
              first = EINA_FALSE;
           }
         else
           {
-             eo_do(child, evas_vg_node_bound_get(&s));
+             eo_do(child, efl_vg_bound_get(&s));
              eina_rectangle_union(r, &s);
           }
      }
@@ -76,4 +77,4 @@ _evas_vg_container_evas_vg_node_bound_get(Eo *obj EINA_UNUSED,
 }
 
 
-#include "evas_vg_container.eo.c"
+#include "efl_vg_container.eo.c"
index e448005..321e9bf 100644 (file)
@@ -5,13 +5,11 @@
 
 #include <strings.h>
 
-#define MY_CLASS EVAS_VG_GRADIENT_CLASS
-
 static void
-_evas_vg_gradient_efl_gfx_gradient_stop_set(Eo *obj,
-                                            Evas_VG_Gradient_Data *pd,
-                                            const Efl_Gfx_Gradient_Stop *colors,
-                                            unsigned int length)
+_efl_vg_gradient_efl_gfx_gradient_base_stop_set(Eo *obj EINA_UNUSED,
+                                                Efl_VG_Gradient_Data *pd,
+                                                const Efl_Gfx_Gradient_Stop *colors,
+                                                unsigned int length)
 {
    pd->colors = realloc(pd->colors, length * sizeof(Efl_Gfx_Gradient_Stop));
    if (!pd->colors)
@@ -23,33 +21,59 @@ _evas_vg_gradient_efl_gfx_gradient_stop_set(Eo *obj,
    memcpy(pd->colors, colors, length * sizeof(Efl_Gfx_Gradient_Stop));
    pd->colors_count = length;
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
 static void
-_evas_vg_gradient_efl_gfx_gradient_stop_get(Eo *obj EINA_UNUSED,
-                                            Evas_VG_Gradient_Data *pd,
-                                            const Efl_Gfx_Gradient_Stop **colors,
-                                            unsigned int *length)
+_efl_vg_gradient_efl_gfx_gradient_base_stop_get(Eo *obj EINA_UNUSED,
+                                                Efl_VG_Gradient_Data *pd,
+                                                const Efl_Gfx_Gradient_Stop **colors,
+                                                unsigned int *length)
 {
    if (colors) *colors = pd->colors;
    if (length) *length = pd->colors_count;
 }
 
 static void
-_evas_vg_gradient_efl_gfx_gradient_spread_set(Eo *obj,
-                                              Evas_VG_Gradient_Data *pd,
-                                              Efl_Gfx_Gradient_Spread s)
+_efl_vg_gradient_efl_gfx_gradient_base_spread_set(Eo *obj EINA_UNUSED,
+                                                  Efl_VG_Gradient_Data *pd,
+                                                  Efl_Gfx_Gradient_Spread s)
 {
    pd->s = s;
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+
+   _efl_vg_base_changed(obj);
 }
 
 static Efl_Gfx_Gradient_Spread
-_evas_vg_gradient_efl_gfx_gradient_spread_get(Eo *obj EINA_UNUSED,
-                                              Evas_VG_Gradient_Data *pd)
+_efl_vg_gradient_efl_gfx_gradient_base_spread_get(Eo *obj EINA_UNUSED,
+                                                  Efl_VG_Gradient_Data *pd)
 {
    return pd->s;
 }
 
-#include "evas_vg_gradient.eo.c"
+EAPI void
+evas_vg_gradient_stop_set(Eo *obj, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
+{
+   eo_do(obj, efl_gfx_gradient_stop_set(colors, length));
+}
+
+EAPI void
+evas_vg_gradient_stop_get(Eo *obj, const Efl_Gfx_Gradient_Stop **colors, unsigned int *length)
+{
+   eo_do(obj, efl_gfx_gradient_stop_get(colors, length));
+}
+
+EAPI void
+evas_vg_gradient_spread_set(Eo *obj, Efl_Gfx_Gradient_Spread s)
+{
+   eo_do(obj, efl_gfx_gradient_spread_set(s));
+}
+
+EAPI Efl_Gfx_Gradient_Spread
+evas_vg_gradient_spread_get(Eo *obj)
+{
+
+   return eo_do(obj, efl_gfx_gradient_spread_get());
+}
+
+#include "efl_vg_gradient.eo.c"
index 2dea1a5..814bd47 100644 (file)
@@ -5,10 +5,10 @@
 
 #include <strings.h>
 
-#define MY_CLASS EVAS_VG_GRADIENT_LINEAR_CLASS
+#define MY_CLASS EFL_VG_GRADIENT_LINEAR_CLASS
 
-typedef struct _Evas_VG_Gradient_Linear_Data Evas_VG_Gradient_Linear_Data;
-struct _Evas_VG_Gradient_Linear_Data
+typedef struct _Efl_VG_Gradient_Linear_Data Efl_VG_Gradient_Linear_Data;
+struct _Efl_VG_Gradient_Linear_Data
 {
    struct {
       double x, y;
@@ -16,59 +16,64 @@ struct _Evas_VG_Gradient_Linear_Data
 };
 
 static void
-_evas_vg_gradient_linear_efl_gfx_gradient_linear_start_set(Eo *obj,
-                                                           Evas_VG_Gradient_Linear_Data *pd,
-                                                           double x, double y)
+_efl_vg_gradient_linear_efl_gfx_gradient_linear_start_set(Eo *obj EINA_UNUSED,
+                                                          Efl_VG_Gradient_Linear_Data *pd,
+                                                          double x, double y)
 {
    pd->start.x = x;
    pd->start.y = y;
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
 static void
-_evas_vg_gradient_linear_efl_gfx_gradient_linear_start_get(Eo *obj EINA_UNUSED,
-                                                           Evas_VG_Gradient_Linear_Data *pd,
-                                                           double *x, double *y)
+_efl_vg_gradient_linear_efl_gfx_gradient_linear_start_get(Eo *obj EINA_UNUSED,
+                                                          Efl_VG_Gradient_Linear_Data *pd,
+                                                          double *x, double *y)
 {
    if (x) *x = pd->start.x;
    if (y) *y = pd->start.y;
 }
 
 static void
-_evas_vg_gradient_linear_efl_gfx_gradient_linear_end_set(Eo *obj,
-                                                         Evas_VG_Gradient_Linear_Data *pd,
-                                                         double x, double y)
+_efl_vg_gradient_linear_efl_gfx_gradient_linear_end_set(Eo *obj EINA_UNUSED,
+                                                        Efl_VG_Gradient_Linear_Data *pd,
+                                                        double x, double y)
 {
    pd->end.x = x;
    pd->end.y = y;
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
 static void
-_evas_vg_gradient_linear_efl_gfx_gradient_linear_end_get(Eo *obj EINA_UNUSED,
-                                                         Evas_VG_Gradient_Linear_Data *pd,
-                                                         double *x, double *y)
+_efl_vg_gradient_linear_efl_gfx_gradient_linear_end_get(Eo *obj EINA_UNUSED,
+                                                        Efl_VG_Gradient_Linear_Data *pd,
+                                                        double *x, double *y)
 {
    if (x) *x = pd->end.x;
    if (y) *y = pd->end.y;
 }
 
-static Eina_Bool
-_evas_vg_gradient_linear_render_pre(Eo *obj,
-                                    Eina_Matrix3 *parent,
-                                    Ector_Surface *s,
-                                    void *data,
-                                    Evas_VG_Node_Data *nd)
+static void
+_efl_vg_gradient_linear_render_pre(Eo *obj,
+                                   Eina_Matrix3 *parent,
+                                   Ector_Surface *s,
+                                   void *data,
+                                   Efl_VG_Base_Data *nd)
 {
-   Evas_VG_Gradient_Linear_Data *pd = data;
-   Evas_VG_Gradient_Data *gd = eo_data_scope_get(obj, EVAS_VG_GRADIENT_CLASS);
-   EVAS_VG_COMPUTE_MATRIX(current, parent, nd);
+   Efl_VG_Gradient_Linear_Data *pd = data;
+   Efl_VG_Gradient_Data *gd;
+
+   if (!nd->changed) return ;
+   nd->changed = EINA_FALSE;
+
+   gd = eo_data_scope_get(obj, EFL_VG_GRADIENT_CLASS);
+   EFL_VG_COMPUTE_MATRIX(current, parent, nd);
 
    if (!nd->renderer)
      {
-        eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_CLASS));
+        eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN));
      }
 
    eo_do(nd->renderer,
@@ -81,27 +86,49 @@ _evas_vg_gradient_linear_render_pre(Eo *obj,
          efl_gfx_gradient_linear_start_set(pd->start.x, pd->start.y),
          efl_gfx_gradient_linear_end_set(pd->end.x, pd->end.y),
          ector_renderer_prepare());
-
-   return EINA_TRUE;
 }
 
 static void
-_evas_vg_gradient_linear_eo_base_constructor(Eo *obj,
-                                             Evas_VG_Gradient_Linear_Data *pd)
+_efl_vg_gradient_linear_eo_base_constructor(Eo *obj,
+                                            Efl_VG_Gradient_Linear_Data *pd)
 {
-   Evas_VG_Node_Data *nd;
+   Efl_VG_Base_Data *nd;
 
    eo_do_super(obj, MY_CLASS, eo_constructor());
 
-   nd = eo_data_scope_get(obj, EVAS_VG_NODE_CLASS);
-   nd->render_pre = &_evas_vg_gradient_linear_render_pre;
+   nd = eo_data_scope_get(obj, EFL_VG_BASE_CLASS);
+   nd->render_pre = _efl_vg_gradient_linear_render_pre;
    nd->data = pd;
 }
 
 void
-_evas_vg_gradient_linear_eo_base_destructor(Eo *obj, Evas_VG_Gradient_Linear_Data *pd EINA_UNUSED)
+_efl_vg_gradient_linear_eo_base_destructor(Eo *obj, Efl_VG_Gradient_Linear_Data *pd EINA_UNUSED)
 {
    eo_do_super(obj, MY_CLASS, eo_destructor());
 }
 
-#include "evas_vg_gradient_linear.eo.c"
+EAPI void
+evas_vg_gradient_linear_start_set(Eo *obj, double x, double y)
+{
+   eo_do(obj, efl_gfx_gradient_linear_start_set(x, y));
+}
+
+EAPI void
+evas_vg_gradient_linear_start_get(Eo *obj, double *x, double *y)
+{
+   eo_do(obj, efl_gfx_gradient_linear_start_get(x, y));
+}
+
+EAPI void
+evas_vg_gradient_linear_end_set(Eo *obj, double x, double y)
+{
+   eo_do(obj, efl_gfx_gradient_linear_end_set(x, y));
+}
+
+EAPI void
+evas_vg_gradient_linear_end_get(Eo *obj, double *x, double *y)
+{
+   eo_do(obj, efl_gfx_gradient_linear_end_get(x, y));
+}
+
+#include "efl_vg_gradient_linear.eo.c"
index b2ef343..a61f990 100644 (file)
@@ -3,10 +3,10 @@
 
 #include "evas_vg_private.h"
 
-#define MY_CLASS EVAS_VG_GRADIENT_RADIAL_CLASS
+#define MY_CLASS EFL_VG_GRADIENT_RADIAL_CLASS
 
-typedef struct _Evas_VG_Gradient_Radial_Data Evas_VG_Gradient_Radial_Data;
-struct _Evas_VG_Gradient_Radial_Data
+typedef struct _Efl_VG_Gradient_Radial_Data Efl_VG_Gradient_Radial_Data;
+struct _Efl_VG_Gradient_Radial_Data
 {
    struct {
       double x, y;
@@ -15,75 +15,81 @@ struct _Evas_VG_Gradient_Radial_Data
 };
 
 static void
-_evas_vg_gradient_radial_efl_gfx_gradient_radial_center_set(Eo *obj,
-                                                            Evas_VG_Gradient_Radial_Data *pd,
-                                                            double x, double y)
+_efl_vg_gradient_radial_efl_gfx_gradient_radial_center_set(Eo *obj EINA_UNUSED,
+                                                           Efl_VG_Gradient_Radial_Data *pd,
+                                                           double x, double y)
 {
    pd->center.x = x;
    pd->center.y = y;
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
 static void
-_evas_vg_gradient_radial_efl_gfx_gradient_radial_center_get(Eo *obj EINA_UNUSED,
-                                                            Evas_VG_Gradient_Radial_Data *pd,
-                                                            double *x, double *y)
+_efl_vg_gradient_radial_efl_gfx_gradient_radial_center_get(Eo *obj EINA_UNUSED,
+                                                           Efl_VG_Gradient_Radial_Data *pd,
+                                                           double *x, double *y)
 {
    if (x) *x = pd->center.x;
    if (y) *y = pd->center.y;
 }
 
 static void
-_evas_vg_gradient_radial_efl_gfx_gradient_radial_radius_set(Eo *obj,
-                                                            Evas_VG_Gradient_Radial_Data *pd,
-                                                            double r)
+_efl_vg_gradient_radial_efl_gfx_gradient_radial_radius_set(Eo *obj EINA_UNUSED,
+                                                           Efl_VG_Gradient_Radial_Data *pd,
+                                                           double r)
 {
    pd->radius = r;
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+
+   _efl_vg_base_changed(obj);
 }
 
 static double
-_evas_vg_gradient_radial_efl_gfx_gradient_radial_radius_get(Eo *obj EINA_UNUSED,
-                                                            Evas_VG_Gradient_Radial_Data *pd)
+_efl_vg_gradient_radial_efl_gfx_gradient_radial_radius_get(Eo *obj EINA_UNUSED,
+                                                           Efl_VG_Gradient_Radial_Data *pd)
 {
    return pd->radius;
 }
 
 static void
-_evas_vg_gradient_radial_efl_gfx_gradient_radial_focal_set(Eo *obj,
-                                                           Evas_VG_Gradient_Radial_Data *pd,
-                                                           double x, double y)
+_efl_vg_gradient_radial_efl_gfx_gradient_radial_focal_set(Eo *obj EINA_UNUSED,
+                                                          Efl_VG_Gradient_Radial_Data *pd,
+                                                          double x, double y)
 {
    pd->focal.x = x;
    pd->focal.y = y;
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
 static void
-_evas_vg_gradient_radial_efl_gfx_gradient_radial_focal_get(Eo *obj EINA_UNUSED,
-                                                           Evas_VG_Gradient_Radial_Data *pd,
-                                                           double *x, double *y)
+_efl_vg_gradient_radial_efl_gfx_gradient_radial_focal_get(Eo *obj EINA_UNUSED,
+                                                          Efl_VG_Gradient_Radial_Data *pd,
+                                                          double *x, double *y)
 {
    if (x) *x = pd->focal.x;
    if (y) *y = pd->focal.y;
 }
 
-static Eina_Bool
-_evas_vg_gradient_radial_render_pre(Eo *obj,
+static void
+_efl_vg_gradient_radial_render_pre(Eo *obj,
                                     Eina_Matrix3 *parent,
                                     Ector_Surface *s,
                                     void *data,
-                                    Evas_VG_Node_Data *nd)
+                                    Efl_VG_Base_Data *nd)
 {
-   Evas_VG_Gradient_Radial_Data *pd = data;
-   Evas_VG_Gradient_Data *gd = eo_data_scope_get(obj, EVAS_VG_GRADIENT_CLASS);
-   EVAS_VG_COMPUTE_MATRIX(current, parent, nd);
+   Efl_VG_Gradient_Radial_Data *pd = data;
+   Efl_VG_Gradient_Data *gd;
+
+   if (!nd->changed) return ;
+   nd->changed = EINA_FALSE;
+
+   gd = eo_data_scope_get(obj, EFL_VG_GRADIENT_CLASS);
+   EFL_VG_COMPUTE_MATRIX(current, parent, nd);
 
    if (!nd->renderer)
      {
-        eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_CLASS));
+        eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN));
      }
 
    eo_do(nd->renderer,
@@ -97,27 +103,61 @@ _evas_vg_gradient_radial_render_pre(Eo *obj,
          efl_gfx_gradient_radial_focal_set(pd->focal.x, pd->focal.y),
          efl_gfx_gradient_radial_radius_set(pd->radius),
          ector_renderer_prepare());
-
-   return EINA_TRUE;
 }
 
 static void
-_evas_vg_gradient_radial_eo_base_constructor(Eo *obj, Evas_VG_Gradient_Radial_Data *pd)
+_efl_vg_gradient_radial_eo_base_constructor(Eo *obj, Efl_VG_Gradient_Radial_Data *pd)
 {
-   Evas_VG_Node_Data *nd;
+   Efl_VG_Base_Data *nd;
 
    eo_do_super(obj, MY_CLASS, eo_constructor());
 
-   nd = eo_data_scope_get(obj, EVAS_VG_NODE_CLASS);
-   nd->render_pre = &_evas_vg_gradient_radial_render_pre;
+   nd = eo_data_scope_get(obj, EFL_VG_BASE_CLASS);
+   nd->render_pre = _efl_vg_gradient_radial_render_pre;
    nd->data = pd;
 }
 
 static void
-_evas_vg_gradient_radial_eo_base_destructor(Eo *obj,
-                                            Evas_VG_Gradient_Radial_Data *pd EINA_UNUSED)
+_efl_vg_gradient_radial_eo_base_destructor(Eo *obj,
+                                           Efl_VG_Gradient_Radial_Data *pd EINA_UNUSED)
 {
    eo_do_super(obj, MY_CLASS, eo_destructor());
 }
 
-#include "evas_vg_gradient_radial.eo.c"
+EAPI void
+evas_vg_gradient_radial_center_set(Eo *obj, double x, double y)
+{
+   eo_do(obj, efl_gfx_gradient_radial_center_set(x, y));
+}
+
+EAPI void
+evas_vg_gradient_radial_center_get(Eo *obj, double *x, double *y)
+{
+   eo_do(obj, efl_gfx_gradient_radial_center_get(x, y));
+}
+
+EAPI void
+evas_vg_gradient_radial_radius_set(Eo *obj, double r)
+{
+   eo_do(obj, efl_gfx_gradient_radial_radius_set(r));
+}
+
+EAPI double
+evas_vg_gradient_radial_radius_get(Eo *obj)
+{
+   return eo_do(obj, efl_gfx_gradient_radial_radius_get());
+}
+
+EAPI void
+evas_vg_gradient_radial_focal_set(Eo *obj, double x, double y)
+{
+   eo_do(obj, efl_gfx_gradient_radial_focal_set(x, y));
+}
+
+EAPI void
+evas_vg_gradient_radial_focal_get(Eo *obj, double *x, double *y)
+{
+   eo_do(obj, efl_gfx_gradient_radial_focal_get(x, y));
+}
+
+#include "efl_vg_gradient_radial.eo.c"
index f9dceb7..1bb0b1b 100644 (file)
@@ -3,8 +3,10 @@
 
 #include <strings.h>
 
-typedef struct _Evas_VG_Image_Data Evas_VG_Image_Data;
-struct _Evas_VG_Image_Data
+#include "evas_vg_private.h"
+
+typedef struct _Efl_VG_Image_Data Efl_VG_Image_Data;
+struct _Efl_VG_Image_Data
 {
    // FIXME: only manipulate Eina_File internally.
    Eina_File *f;
@@ -15,31 +17,33 @@ struct _Evas_VG_Image_Data
 };
 
 static void
-_evas_vg_image_position_set(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
-                            int x, int y)
+_efl_vg_image_position_set(Eo *obj, Efl_VG_Image_Data *pd, int x, int y)
 {
    pd->x = x;
    pd->y = y;
+
+   _efl_vg_base_changed(obj);
 }
 
 static void
-_evas_vg_image_position_get(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
-                            int *x, int *y)
+_efl_vg_image_position_get(Eo *obj, Efl_VG_Image_Data *pd, int *x, int *y)
 {
    if (x) *x = pd->x;
    if (y) *y = pd->y;
 }
 
 static void
-_evas_vg_image_size_set(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
+_efl_vg_image_size_set(Eo *obj, Efl_VG_Image_Data *pd,
                         unsigned int w, unsigned int h)
 {
    pd->w = w;
    pd->h = h;
+
+   _efl_vg_base_changed(obj);
 }
 
 static void
-_evas_vg_image_size_get(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
+_efl_vg_image_size_get(Eo *obj, Efl_VG_Image_Data *pd,
                         unsigned int *w, unsigned int *h)
 {
    if (w) *w = pd->w;
@@ -47,7 +51,7 @@ _evas_vg_image_size_get(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
 }
 
 static Eina_Bool
-_evas_vg_image_efl_file_mmap_set(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
+_efl_vg_image_efl_file_mmap_set(Eo *obj EINA_UNUSED, Efl_VG_Image_Data *pd,
                                  const Eina_File *f, const char *key)
 {
    Eina_File *tmp = pd->f;
@@ -56,11 +60,13 @@ _evas_vg_image_efl_file_mmap_set(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
    eina_file_close(tmp);
    eina_stringshare_replace(&pd->key, key);
 
+   _efl_vg_base_changed(obj);
+
    return EINA_TRUE;
 }
 
 static void
-_evas_vg_image_efl_file_mmap_get(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
+_efl_vg_image_efl_file_mmap_get(Eo *obj EINA_UNUSED, Efl_VG_Image_Data *pd,
                                  const Eina_File **f, const char **key)
 {
    if (f) *f = pd->f;
@@ -68,21 +74,21 @@ _evas_vg_image_efl_file_mmap_get(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
 }
 
 static Eina_Bool
-_evas_vg_image_efl_file_file_set(Eo *obj, Evas_VG_Image_Data *pd,
+_efl_vg_image_efl_file_file_set(Eo *obj, Efl_VG_Image_Data *pd,
                                  const char *file, const char *key)
 {
    Eina_File *tmp;
    Eina_Bool r;
 
    tmp = eina_file_open(file, EINA_FALSE);
-   r = _evas_vg_image_efl_file_mmap_set(obj, pd, tmp, key);
+   r = _efl_vg_image_efl_file_mmap_set(obj, pd, tmp, key);
    eina_file_close(tmp);
 
    return r;
 }
 
 static void
-_evas_vg_image_efl_file_file_get(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
+_efl_vg_image_efl_file_file_get(Eo *obj EINA_UNUSED, Efl_VG_Image_Data *pd,
                                  const char **file, const char **key)
 {
    if (file) *file = eina_file_filename_get(pd->f);
@@ -90,15 +96,15 @@ _evas_vg_image_efl_file_file_get(Eo *obj EINA_UNUSED, Evas_VG_Image_Data *pd,
 }
 
 static void
-_evas_vg_image_eo_base_constructor(Eo *obj, Evas_VG_Image_Data *pd EINA_UNUSED)
+_efl_vg_image_eo_base_constructor(Eo *obj, Efl_VG_Image_Data *pd)
 {
    eo_error_set(obj);
 }
 
 static void
-_evas_vg_image_eo_base_destructor(Eo *obj, Evas_VG_Image_Data *pd EINA_UNUSED)
+_efl_vg_image_eo_base_destructor(Eo *obj, Efl_VG_Image_Data *pd)
 {
    eo_error_set(obj);
 }
 
-#include "evas_vg_image.eo.c"
+#include "efl_vg_image.eo.c"
index 3eb62fa..bf726d5 100644 (file)
@@ -45,11 +45,11 @@ _attrs_id_parser(void *data, const char *key, const char *value)
 static Eina_Bool
 _attrs_size_parser(void *data, const char *key, const char *value)
 {
-   unsigned int width, height;
+   int width, height;
    Evas_Object *vg = data;
    Eina_Bool get_w = EINA_FALSE, get_h = EINA_FALSE;
 
-   eo_do(vg, evas_obj_vg_size_get(&width, &height));
+   eo_do(vg, efl_gfx_view_size_get(&width, &height));
    if (!strcmp(key, "width"))
      get_w = EINA_TRUE;
    else if (!strcmp(key, "height"))
@@ -66,7 +66,7 @@ _attrs_size_parser(void *data, const char *key, const char *value)
              if (get_w) width = r;
              else if (get_h) height = r;
           }
-        eo_do(vg, evas_obj_vg_size_set(width, height));
+        eo_do(vg, efl_gfx_view_size_set(width, height));
      }
 
    return EINA_TRUE;
@@ -116,7 +116,7 @@ _tag_linearGradient_handler(Evas_SVG_Loader *loader,
                                     _attrs_id_parser, &id);
 
    if (!id) return EINA_FALSE;
-   node = eo_add(EVAS_VG_GRADIENT_LINEAR_CLASS, NULL);
+   node = eo_add(EFL_VG_GRADIENT_LINEAR_CLASS, NULL);
    if (!node) return EINA_FALSE;
 
    eina_hash_direct_add(loader->definition, id, node);
@@ -446,7 +446,7 @@ _tag_stop_handler(Evas_SVG_Loader *loader,
    if (((int)eina_array_count(loader->stack) - 1) < 0) return EINA_FALSE;
 
    node = eina_array_data_get(loader->stack, eina_array_count(loader->stack) - 1);
-   if (!eo_isa(node, EFL_GFX_GRADIENT_INTERFACE))
+   if (!eo_isa(node, EFL_GFX_GRADIENT_BASE_INTERFACE))
      return EINA_FALSE;
 
    eina_simple_xml_attributes_parse(attrs, attrs_length,
@@ -481,7 +481,7 @@ _tag_g_handler(Evas_SVG_Loader *loader,
 
    parent = eina_array_data_get(loader->stack, eina_array_count(loader->stack) - 1);
 
-   node = eo_add(EVAS_VG_CONTAINER_CLASS, parent);
+   node = eo_add(EFL_VG_CONTAINER_CLASS, parent);
    eina_array_push(loader->stack, node);
 
    return EINA_TRUE;
index 6b16256..ee95037 100644 (file)
@@ -6,17 +6,26 @@
 #include <string.h>
 #include <math.h>
 
-#define MY_CLASS EVAS_VG_NODE_CLASS
+#define MY_CLASS EFL_VG_BASE_CLASS
 
-// FIXME:
-// - share private structure with evas_object_vg
-// - mark parent canvas evas_object dirty after any change on the object
-// - add a virtual render function as part of the private data field
+static Eina_Bool
+_efl_vg_base_property_changed(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info)
+{
+   Efl_VG_Base_Data *pd = data;
+   Eo *parent;
+
+   if (pd->changed) return EINA_TRUE;
+   pd->changed = EINA_TRUE;
+
+   eo_do(obj, parent = eo_parent_get());
+   eo_do(parent, eo_event_callback_call(desc, event_info));
+   return EINA_TRUE;
+}
 
 void
-_evas_vg_node_transformation_set(Eo *obj EINA_UNUSED,
-                                 Evas_VG_Node_Data *pd,
-                                 const Eina_Matrix3 *m)
+_efl_vg_base_transformation_set(Eo *obj,
+                                Efl_VG_Base_Data *pd,
+                                const Eina_Matrix3 *m)
 {
    if (!pd->m)
      {
@@ -24,80 +33,121 @@ _evas_vg_node_transformation_set(Eo *obj EINA_UNUSED,
         if (!pd->m) return ;
      }
    memcpy(pd->m, m, sizeof (Eina_Matrix3));
+
+   _efl_vg_base_changed(obj);
 }
 
 const Eina_Matrix3 *
-_evas_vg_node_transformation_get(Eo *obj EINA_UNUSED, Evas_VG_Node_Data *pd)
+_efl_vg_base_transformation_get(Eo *obj EINA_UNUSED, Efl_VG_Base_Data *pd)
 {
    return pd->m;
 }
 
 void
-_evas_vg_node_origin_set(Eo *obj EINA_UNUSED,
-                         Evas_VG_Node_Data *pd,
-                         double x, double y)
+_efl_vg_base_origin_set(Eo *obj,
+                        Efl_VG_Base_Data *pd,
+                        double x, double y)
 {
    pd->x = x;
    pd->y = y;
+
+   _efl_vg_base_changed(obj);
 }
 
 void
-_evas_vg_node_origin_get(Eo *obj EINA_UNUSED,
-                         Evas_VG_Node_Data *pd,
-                         double *x, double *y)
+_efl_vg_base_origin_get(Eo *obj EINA_UNUSED,
+                        Efl_VG_Base_Data *pd,
+                        double *x, double *y)
 {
    if (x) *x = pd->x;
    if (y) *y = pd->y;
 }
 
 void
-_evas_vg_node_efl_gfx_base_position_set(Eo *obj EINA_UNUSED,
-                                        Evas_VG_Node_Data *pd,
-                                        int x, int y)
+_efl_vg_base_efl_gfx_base_position_set(Eo *obj EINA_UNUSED,
+                                       Efl_VG_Base_Data *pd,
+                                       int x, int y)
 {
    pd->x = lrint(x);
    pd->y = lrint(y);
+
+   _efl_vg_base_changed(obj);
 }
 
 void
-_evas_vg_node_efl_gfx_base_position_get(Eo *obj EINA_UNUSED,
-                                        Evas_VG_Node_Data *pd,
-                                        int *x, int *y)
+_efl_vg_base_efl_gfx_base_position_get(Eo *obj EINA_UNUSED,
+                                       Efl_VG_Base_Data *pd,
+                                       int *x, int *y)
 {
    if (x) *x = pd->x;
    if (y) *y = pd->y;
 }
 
 void
-_evas_vg_node_efl_gfx_base_visible_set(Eo *obj EINA_UNUSED,
-                                       Evas_VG_Node_Data *pd, Eina_Bool v)
+_efl_vg_base_efl_gfx_base_visible_set(Eo *obj EINA_UNUSED,
+                                      Efl_VG_Base_Data *pd, Eina_Bool v)
 {
    pd->visibility = v;
+
+   _efl_vg_base_changed(obj);
 }
 
 
 Eina_Bool
-_evas_vg_node_efl_gfx_base_visible_get(Eo *obj EINA_UNUSED,
-                                       Evas_VG_Node_Data *pd)
+_efl_vg_base_efl_gfx_base_visible_get(Eo *obj EINA_UNUSED,
+                                      Efl_VG_Base_Data *pd)
 {
    return pd->visibility;
 }
 
 void
-_evas_vg_node_efl_gfx_base_color_set(Eo *obj EINA_UNUSED,
-                                     Evas_VG_Node_Data *pd,
-                                     int r, int g, int b, int a)
+_efl_vg_base_efl_gfx_base_color_set(Eo *obj EINA_UNUSED,
+                                    Efl_VG_Base_Data *pd,
+                                    int r, int g, int b, int a)
 {
+   if (r > 255) r = 255; if (r < 0) r = 0;
+   if (g > 255) g = 255; if (g < 0) g = 0;
+   if (b > 255) b = 255; if (b < 0) b = 0;
+   if (a > 255) a = 255; if (a < 0) a = 0;
+   if (r > a)
+     {
+        r = a;
+        ERR("Evas only handles pre multiplied colors!");
+     }
+   if (g > a)
+     {
+        g = a;
+        ERR("Evas only handles pre multiplied colors!");
+     }
+   if (b > a)
+     {
+        b = a;
+        ERR("Evas only handles pre multiplied colors!");
+     }
+
    pd->r = r;
    pd->g = g;
    pd->b = b;
    pd->a = a;
+
+   _efl_vg_base_changed(obj);
+}
+
+Eina_Bool
+_efl_vg_base_efl_gfx_base_color_part_set(Eo *obj, Efl_VG_Base_Data *pd,
+                                         const char *part,
+                                         int r, int g, int b, int a)
+{
+   if (part) return EINA_FALSE;
+
+   _efl_vg_base_efl_gfx_base_color_set(obj, pd, r, g, b, a);
+   return EINA_TRUE;
 }
 
 void
-_evas_vg_node_efl_gfx_base_color_get(Eo *obj EINA_UNUSED,
-                                     Evas_VG_Node_Data *pd,
-                                     int *r, int *g, int *b, int *a)
+_efl_vg_base_efl_gfx_base_color_get(Eo *obj EINA_UNUSED,
+                                    Efl_VG_Base_Data *pd,
+                                    int *r, int *g, int *b, int *a)
 {
    if (r) *r = pd->r;
    if (g) *g = pd->g;
@@ -105,103 +155,121 @@ _evas_vg_node_efl_gfx_base_color_get(Eo *obj EINA_UNUSED,
    if (a) *a = pd->a;
 }
 
+Eina_Bool
+_efl_vg_base_efl_gfx_base_color_part_get(Eo *obj, Efl_VG_Base_Data *pd,
+                                         const char *part,
+                                         int *r, int *g, int *b, int *a)
+{
+   if (part) return EINA_FALSE;
+
+   _efl_vg_base_efl_gfx_base_color_get(obj, pd, r, g, b, a);
+   return EINA_TRUE;
+}
+
 void
-_evas_vg_node_mask_set(Eo *obj EINA_UNUSED,
-                       Evas_VG_Node_Data *pd,
-                       Evas_VG_Node *r)
+_efl_vg_base_mask_set(Eo *obj EINA_UNUSED,
+                       Efl_VG_Base_Data *pd,
+                       Efl_VG_Base *r)
 {
-   Evas_VG_Node *tmp = pd->mask;
+   Efl_VG_Base *tmp = pd->mask;
 
    pd->mask = eo_ref(r);
    eo_unref(tmp);
+
+   _efl_vg_base_changed(obj);
 }
 
-Evas_VG_Node*
-_evas_vg_node_mask_get(Eo *obj EINA_UNUSED, Evas_VG_Node_Data *pd)
+Efl_VG_Base*
+_efl_vg_base_mask_get(Eo *obj EINA_UNUSED, Efl_VG_Base_Data *pd)
 {
    return pd->mask;
 }
 
 void
-_evas_vg_node_efl_gfx_base_size_get(Eo *obj,
-                                    Evas_VG_Node_Data *pd EINA_UNUSED,
-                                    int *w, int *h)
+_efl_vg_base_efl_gfx_base_size_get(Eo *obj,
+                                   Efl_VG_Base_Data *pd EINA_UNUSED,
+                                   int *w, int *h)
 {
    Eina_Rectangle bound = { 0, 0, 0, 0 };
 
-   eo_do(obj, evas_vg_node_bound_get(&bound));
+   eo_do(obj, efl_vg_bound_get(&bound));
    if (w) *w = bound.w;
    if (h) *h = bound.h;
 }
 
 // Parent should be a container otherwise dismissing the stacking operation
 static Eina_Bool
-_evas_vg_node_parent_checked_get(Eo *obj,
-                                 Eo **parent, Evas_VG_Container_Data **cd)
+_efl_vg_base_parent_checked_get(Eo *obj,
+                                Eo **parent,
+                                Efl_VG_Container_Data **cd)
 {
+   *cd = NULL;
    eo_do(obj, *parent = eo_parent_get());
-   if (eo_isa(*parent, EVAS_VG_CONTAINER_CLASS))
+
+   if (eo_isa(*parent, EFL_VG_CONTAINER_CLASS))
      {
-        *cd = eo_data_scope_get(*parent, EVAS_VG_CONTAINER_CLASS);
+        *cd = eo_data_scope_get(*parent, EFL_VG_CONTAINER_CLASS);
         if (!*cd)
           {
-             ERR("Can't get EVAS_VG_CONTAINER_CLASS data.");
+             ERR("Can't get EFL_VG_CONTAINER_CLASS data.");
              goto on_error;
           }
      }
+   else if (*parent != NULL)
+     {
+        ERR("Parent of unauthorized class.");
+        goto on_error;
+     }
+
    return EINA_TRUE;
 
  on_error:
+   *parent = NULL;
    *cd = NULL;
    return EINA_FALSE;
 }
 
 void
-_evas_vg_node_eo_base_constructor(Eo *obj,
-                                  Evas_VG_Node_Data *pd EINA_UNUSED)
+_efl_vg_base_eo_base_constructor(Eo *obj,
+                                 Efl_VG_Base_Data *pd)
 {
-   Evas_VG_Container_Data *cd = NULL;
+   Efl_VG_Container_Data *cd = NULL;
    Eo *parent;
-   Evas_VG_Node_Data *parent_nd = NULL;
 
    eo_do_super(obj, MY_CLASS, eo_constructor());
 
-   if (!_evas_vg_node_parent_checked_get(obj, &parent, &cd))
+   if (!_efl_vg_base_parent_checked_get(obj, &parent, &cd))
      eo_error_set(obj);
 
-   //Link the vector object
-   if (parent)
-     {
-        parent_nd = eo_data_scope_get(parent, EVAS_VG_NODE_CLASS);
-        pd->eo_vg = parent_nd->eo_vg;
-     }
+   eo_do(obj, eo_event_callback_add(EFL_GFX_CHANGED, _efl_vg_base_property_changed, pd));
+   pd->changed = EINA_TRUE;
 }
 
 void
-_evas_vg_node_eo_base_parent_set(Eo *obj,
-                                 Evas_VG_Node_Data *pd EINA_UNUSED,
-                                 Eo *parent)
+_efl_vg_base_eo_base_parent_set(Eo *obj,
+                                Efl_VG_Base_Data *pd EINA_UNUSED,
+                                Eo *parent)
 {
-   Evas_VG_Container_Data *cd = NULL;
-   Evas_VG_Container_Data *old_cd = NULL;
+   Efl_VG_Container_Data *cd = NULL;
+   Efl_VG_Container_Data *old_cd = NULL;
    Eo *old_parent;
 
-   if (eo_isa(parent, EVAS_VG_CONTAINER_CLASS))
+   if (eo_isa(parent, EFL_VG_CONTAINER_CLASS))
      {
-        cd = eo_data_scope_get(parent, EVAS_VG_CONTAINER_CLASS);
+        cd = eo_data_scope_get(parent, EFL_VG_CONTAINER_CLASS);
         if (!cd)
           {
-             ERR("Can't get EVAS_VG_CONTAINER_CLASS data from %p.", parent);
+             ERR("Can't get EFL_VG_CONTAINER_CLASS data from %p.", parent);
              goto on_error;
           }
      }
-   else if (parent != NULL && !eo_isa(parent, EVAS_VG_CLASS))
+   else if (parent != NULL)
      {
         ERR("%p not even an EVAS_VG_CLASS.", parent);
         goto on_error;
      }
 
-   if (!_evas_vg_node_parent_checked_get(obj, &old_parent, &old_cd))
+   if (!_efl_vg_base_parent_checked_get(obj, &old_parent, &old_cd))
      goto on_error;
 
    // FIXME: this may become slow with to much object
@@ -212,6 +280,10 @@ _evas_vg_node_eo_base_parent_set(Eo *obj,
    if (cd)
      cd->children = eina_list_append(cd->children, obj);
 
+   _efl_vg_base_changed(old_parent);
+   _efl_vg_base_changed(obj);
+   _efl_vg_base_changed(parent);
+
    return ;
 
  on_error:
@@ -220,15 +292,15 @@ _evas_vg_node_eo_base_parent_set(Eo *obj,
 }
 
 void
-_evas_vg_node_raise(Eo *obj, Evas_VG_Node_Data *pd EINA_UNUSED)
+_efl_vg_base_efl_gfx_stack_raise(Eo *obj, Efl_VG_Base_Data *pd EINA_UNUSED)
 {
-   Evas_VG_Container_Data *cd;
+   Efl_VG_Container_Data *cd;
    Eina_List *lookup, *next;
    Eo *parent;
 
    eo_do(obj, parent = eo_parent_get());
-   cd = eo_data_scope_get(parent, EVAS_VG_CONTAINER_CLASS);
-   if (!cd) goto on_error;
+   if (!eo_isa(parent, EFL_VG_CONTAINER_CLASS)) goto on_error;
+   cd = eo_data_scope_get(parent, EFL_VG_CONTAINER_CLASS);
 
    // FIXME: this could become slow with to much object
    lookup = eina_list_data_find_list(cd->children, obj);
@@ -240,6 +312,7 @@ _evas_vg_node_raise(Eo *obj, Evas_VG_Node_Data *pd EINA_UNUSED)
    cd->children = eina_list_remove_list(cd->children, lookup);
    cd->children = eina_list_append_relative_list(cd->children, obj, next);
 
+   _efl_vg_base_changed(parent);
    return ;
 
  on_error:
@@ -247,17 +320,17 @@ _evas_vg_node_raise(Eo *obj, Evas_VG_Node_Data *pd EINA_UNUSED)
 }
 
 void
-_evas_vg_node_stack_above(Eo *obj,
-                          Evas_VG_Node_Data *pd EINA_UNUSED,
-                          Evas_VG_Node *above)
+_efl_vg_base_efl_gfx_stack_stack_above(Eo *obj,
+                                       Efl_VG_Base_Data *pd EINA_UNUSED,
+                                       Efl_Gfx_Stack *above)
 {
-   Evas_VG_Container_Data *cd;
+   Efl_VG_Container_Data *cd;
    Eina_List *lookup, *ref;
    Eo *parent;
 
    eo_do(obj, parent = eo_parent_get());
-   cd = eo_data_scope_get(parent, EVAS_VG_CONTAINER_CLASS);
-   if (!cd) goto on_error;
+   if (!eo_isa(parent, EFL_VG_CONTAINER_CLASS)) goto on_error;
+   cd = eo_data_scope_get(parent, EFL_VG_CONTAINER_CLASS);
 
    // FIXME: this could become slow with to much object
    lookup = eina_list_data_find_list(cd->children, obj);
@@ -269,6 +342,7 @@ _evas_vg_node_stack_above(Eo *obj,
    cd->children = eina_list_remove_list(cd->children, lookup);
    cd->children = eina_list_append_relative_list(cd->children, obj, ref);
 
+   _efl_vg_base_changed(parent);
    return ;
 
  on_error:
@@ -276,17 +350,17 @@ _evas_vg_node_stack_above(Eo *obj,
 }
 
 void
-_evas_vg_node_stack_below(Eo *obj,
-                          Evas_VG_Node_Data *pd EINA_UNUSED,
-                          Evas_Object *below)
+_efl_vg_base_efl_gfx_stack_stack_below(Eo *obj,
+                                       Efl_VG_Base_Data *pd EINA_UNUSED,
+                                       Efl_Gfx_Stack *below)
 {
-   Evas_VG_Container_Data *cd;
+   Efl_VG_Container_Data *cd;
    Eina_List *lookup, *ref;
    Eo *parent;
 
    eo_do(obj, parent = eo_parent_get());
-   cd = eo_data_scope_get(parent, EVAS_VG_CONTAINER_CLASS);
-   if (!cd) goto on_error;
+   if (!eo_isa(parent, EFL_VG_CONTAINER_CLASS)) goto on_error;
+   cd = eo_data_scope_get(parent, EFL_VG_CONTAINER_CLASS);
 
    // FIXME: this could become slow with to much object
    lookup = eina_list_data_find_list(cd->children, obj);
@@ -298,6 +372,7 @@ _evas_vg_node_stack_below(Eo *obj,
    cd->children = eina_list_remove_list(cd->children, lookup);
    cd->children = eina_list_prepend_relative_list(cd->children, obj, ref);
 
+   _efl_vg_base_changed(parent);
    return ;
 
  on_error:
@@ -305,15 +380,15 @@ _evas_vg_node_stack_below(Eo *obj,
 }
 
 void
-_evas_vg_node_lower(Eo *obj, Evas_VG_Node_Data *pd EINA_UNUSED)
+_efl_vg_base_efl_gfx_stack_lower(Eo *obj, Efl_VG_Base_Data *pd EINA_UNUSED)
 {
-   Evas_VG_Container_Data *cd;
+   Efl_VG_Container_Data *cd;
    Eina_List *lookup, *prev;
    Eo *parent;
 
    eo_do(obj, parent = eo_parent_get());
-   cd = eo_data_scope_get(parent, EVAS_VG_CONTAINER_CLASS);
-   if (!cd) goto on_error;
+   if (!eo_isa(parent, EFL_VG_CONTAINER_CLASS)) goto on_error;
+   cd = eo_data_scope_get(parent, EFL_VG_CONTAINER_CLASS);
 
    // FIXME: this could become slow with to much object
    lookup = eina_list_data_find_list(cd->children, obj);
@@ -325,28 +400,97 @@ _evas_vg_node_lower(Eo *obj, Evas_VG_Node_Data *pd EINA_UNUSED)
    cd->children = eina_list_remove_list(cd->children, lookup);
    cd->children = eina_list_prepend_relative_list(cd->children, obj, prev);
 
+   _efl_vg_base_changed(parent);
    return ;
 
  on_error:
    eo_error_set(obj);
 }
 
+Efl_Gfx_Stack *
+_efl_vg_base_efl_gfx_stack_below_get(Eo *obj, Efl_VG_Base_Data *pd)
+{
+   // FIXME: need to implement bound_get
+   return NULL;
+}
+
+Efl_Gfx_Stack *
+_efl_vg_base_efl_gfx_stack_above_get(Eo *obj, Efl_VG_Base_Data *pd)
+{
+   // FIXME: need to implement bound_get
+   return NULL;
+}
+
 Eina_Bool
-_evas_vg_node_original_bound_get(Eo *obj EINA_UNUSED,
-                                 Evas_VG_Node_Data *pd EINA_UNUSED,
-                                 Eina_Rectangle *r EINA_UNUSED)
+_efl_vg_base_original_bound_get(Eo *obj,
+                                Efl_VG_Base_Data *pd,
+                                Eina_Rectangle *r)
 {
    return EINA_FALSE;
 }
 
+EAPI Eina_Bool
+evas_vg_node_visible_get(Eo *obj)
+{
+   return eo_do(obj, efl_gfx_visible_get());
+}
 
-void
-_evas_vg_node_changed(Eo *obj EINA_UNUSED, Evas_VG_Node_Data *pd)
+EAPI void
+evas_vg_node_visible_set(Eo *obj, Eina_Bool v)
+{
+   eo_do(obj, efl_gfx_visible_set(v));
+}
+
+EAPI void
+evas_vg_node_color_get(Eo *obj, int *r, int *g, int *b, int *a)
+{
+   eo_do(obj, efl_gfx_color_get(r, g, b, a));
+}
+
+EAPI void
+evas_vg_node_color_set(Eo *obj, int r, int g, int b, int a)
+{
+   eo_do(obj, efl_gfx_color_set(r, g, b, a));
+}
+
+EAPI void
+evas_vg_node_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
+{
+   eo_do(obj,
+         efl_gfx_position_get(x, y),
+         efl_gfx_size_get(w, h));
+}
+
+EAPI void
+evas_vg_node_geometry_set(Eo *obj, int x, int y, int w, int h)
+{
+   eo_do(obj,
+         efl_gfx_position_set(x, y),
+         efl_gfx_size_set(w, h));
+}
+
+EAPI void
+evas_vg_node_stack_below(Eo *obj, Eo *below)
+{
+   eo_do(obj, efl_gfx_stack_below(below));
+}
+
+EAPI void
+evas_vg_node_stack_above(Eo *obj, Eo *above)
+{
+   eo_do(obj, efl_gfx_stack_above(above));
+}
+
+EAPI void
+evas_vg_node_raise(Eo *obj)
+{
+   eo_do(obj, efl_gfx_stack_raise());
+}
+
+EAPI void
+evas_vg_node_lower(Eo *obj)
 {
-   if (!pd->eo_vg) return;
-   Evas_Object_Protected_Data *obj_vg = eo_data_scope_get(pd->eo_vg,
-                                                          EVAS_OBJECT_CLASS);
-   evas_object_change(pd->eo_vg, obj_vg);
+   eo_do(obj, efl_gfx_stack_lower());
 }
 
-#include "evas_vg_node.eo.c"
+#include "efl_vg_base.eo.c"
index 26e22f5..8f5bf4f 100644 (file)
@@ -3,18 +3,17 @@
 
 #include <Ector.h>
 
-typedef struct _Evas_VG_Node_Data Evas_VG_Node_Data;
-typedef struct _Evas_VG_Container_Data Evas_VG_Container_Data;
-typedef struct _Evas_VG_Gradient_Data Evas_VG_Gradient_Data;
+typedef struct _Efl_VG_Base_Data Efl_VG_Base_Data;
+typedef struct _Efl_VG_Container_Data Efl_VG_Container_Data;
+typedef struct _Efl_VG_Gradient_Data Efl_VG_Gradient_Data;
 
-struct _Evas_VG_Node_Data
+struct _Efl_VG_Base_Data
 {
    Eina_Matrix3 *m;
-   Evas_VG_Node *mask;
+   Efl_VG *mask;
    Ector_Renderer *renderer;
-   Evas_VG *eo_vg;
 
-   Eina_Bool (*render_pre)(Eo *obj, Eina_Matrix3 *parent, Ector_Surface *s, void *data, Evas_VG_Node_Data *nd);
+   void (*render_pre)(Eo *obj, Eina_Matrix3 *parent, Ector_Surface *s, void *data, Efl_VG_Base_Data *nd);
    void *data;
 
    double x, y;
@@ -24,12 +23,12 @@ struct _Evas_VG_Node_Data
    Eina_Bool changed : 1;
 };
 
-struct _Evas_VG_Container_Data
+struct _Efl_VG_Container_Data
 {
    Eina_List *children;
 };
 
-struct _Evas_VG_Gradient_Data
+struct _Efl_VG_Gradient_Data
 {
    // FIXME: Later on we should deduplicate it somehow (Using Ector ?).
    Efl_Gfx_Gradient_Stop *colors;
@@ -38,23 +37,30 @@ struct _Evas_VG_Gradient_Data
    Efl_Gfx_Gradient_Spread s;
 };
 
-static inline Eina_Bool
-_evas_vg_render_pre(Evas_VG_Node *node, Ector_Surface *s, Eina_Matrix3 *m)
+static inline Efl_VG_Base_Data *
+_evas_vg_render_pre(Efl_VG *child, Ector_Surface *s, Eina_Matrix3 *m)
 {
-   Evas_VG_Node_Data *nd;
-
-   if (!node) return EINA_FALSE;
+   Efl_VG_Base_Data *child_nd = NULL;
 
    // FIXME: Prevent infinite loop
-   nd = eo_data_scope_get(node, EVAS_VG_NODE_CLASS);
-   if (nd->render_pre) return nd->render_pre(node, m, s, nd->data, nd);
-   else return EINA_FALSE;
+   if (child)
+     child_nd = eo_data_scope_get(child, EFL_VG_BASE_CLASS);
+   if (child_nd)
+     child_nd->render_pre(child, m, s, child_nd->data, child_nd);
+
+   return child_nd;
 }
 
-#define EVAS_VG_COMPUTE_MATRIX(Current, Parent, Nd)              \
-  Eina_Matrix3 *Current = Nd->m;                                 \
-  Eina_Matrix3 _matrix_tmp;                                      \
-                                                                 \
+static inline void
+_efl_vg_base_changed(Eo *obj)
+{
+   eo_do(obj, eo_event_callback_call(EFL_GFX_CHANGED, NULL));
+}
+
+#define EFL_VG_COMPUTE_MATRIX(Current, Parent, Nd)                      \
+  Eina_Matrix3 *Current = Nd->m;                                        \
+  Eina_Matrix3 _matrix_tmp, translate;                                  \
+                                                                        \
   if (Parent)                                                           \
     {                                                                   \
        if (Current)                                                     \
@@ -64,8 +70,13 @@ _evas_vg_render_pre(Evas_VG_Node *node, Ector_Surface *s, Eina_Matrix3 *m)
          }                                                              \
        else                                                             \
          {                                                              \
-            Current = Parent;                                           \
+            eina_matrix3_translate(&translate, -(Nd->x), -(Nd->y));     \
+            eina_matrix3_compose(Parent, &translate, &_matrix_tmp);     \
+            eina_matrix3_translate(&translate, (Nd->x), (Nd->y));       \
+            eina_matrix3_compose(&_matrix_tmp, &translate, &_matrix_tmp); \
+            Current = &_matrix_tmp;                                     \
          }                                                              \
     }
 
+
 #endif
index b47091d..8362dfd 100644 (file)
@@ -1,82 +1,92 @@
 #include "evas_common_private.h"
 #include "evas_private.h"
+
 #include "evas_vg_private.h"
-#include "evas_vg_root_node.eo.h"
+#include "efl_vg_root_node.eo.h"
 
 #include <string.h>
 
-#define MY_CLASS EVAS_VG_ROOT_NODE_CLASS
+#define MY_CLASS EFL_VG_ROOT_NODE_CLASS
 
-typedef struct _Evas_VG_Root_Node_Data Evas_VG_Root_Node_Data;
-struct _Evas_VG_Root_Node_Data
+typedef struct _Efl_VG_Root_Node_Data Efl_VG_Root_Node_Data;
+struct _Efl_VG_Root_Node_Data
 {
+   Evas_Object *parent;
+   Evas_Object_Protected_Data *data;
 };
 
 static void
-evas_vg_root_node_vg_set(Evas_VG_Root_Node *root, Evas_VG *vg)
-{
-   Evas_Object_Protected_Data *obj_vg;
-   Evas_VG_Node_Data *nd;
-
-   nd = eo_data_scope_get(root, EVAS_VG_NODE_CLASS);
-   nd->eo_vg = vg;
-   if (!vg) return;
-   obj_vg = eo_data_scope_get(vg, EVAS_OBJECT_CLASS);
-   evas_object_change(vg, obj_vg);
-}
-
-static Eina_Bool
 _evas_vg_root_node_render_pre(Eo *obj EINA_UNUSED,
                               Eina_Matrix3 *parent,
                               Ector_Surface *s,
-                              void *data EINA_UNUSED,
-                              Evas_VG_Node_Data *nd)
+                              void *data,
+                              Efl_VG_Base_Data *nd)
 {
-   Evas_VG_Container_Data *cd = eo_data_scope_get(obj, EVAS_VG_CONTAINER_CLASS);
+   Efl_VG_Container_Data *pd = data;
    Eina_List *l;
    Eo *child;
-   Eina_Bool change = EINA_FALSE;
-   EVAS_VG_COMPUTE_MATRIX(current, parent, nd);
 
-   EINA_LIST_FOREACH(cd->children, l, child)
-     change |= _evas_vg_render_pre(child, s, current);
+   EFL_VG_COMPUTE_MATRIX(current, parent, nd);
 
-   return change;
+   EINA_LIST_FOREACH(pd->children, l, child)
+     _evas_vg_render_pre(child, s, current);
+}
+
+static Eina_Bool
+_evas_vg_root_node_changed(void *data, Eo *obj,
+                           const Eo_Event_Description *desc EINA_UNUSED,
+                           void *event_info EINA_UNUSED)
+{
+   Efl_VG_Root_Node_Data *pd = data;
+   Efl_VG_Base_Data *bd = eo_data_scope_get(obj, EFL_VG_BASE_CLASS);
+
+   if (bd->changed) return EINA_TRUE;
+   bd->changed = EINA_TRUE;
+
+   if (pd->parent) evas_object_change(pd->parent, pd->data);
+   return EINA_TRUE;
 }
 
 void
-_evas_vg_root_node_eo_base_parent_set(Eo *obj,
-                                      Evas_VG_Root_Node_Data *pd EINA_UNUSED,
-                                      Eo *parent)
+_efl_vg_root_node_eo_base_parent_set(Eo *obj,
+                                     Efl_VG_Root_Node_Data *pd,
+                                     Eo *parent)
 {
-   // Nice little hack, jump over parent parent_set in Evas_VG_Root
-   eo_do_super(obj, EVAS_VG_NODE_CLASS, eo_parent_set(parent));
+   // Nice little hack, jump over parent parent_set in Efl_VG_Root
+   eo_do_super(obj, EFL_VG_BASE_CLASS, eo_parent_set(parent));
    if (parent && !eo_isa(parent, EVAS_VG_CLASS))
-     eo_error_set(obj);
+     {
+        eo_error_set(obj);
+     }
+   else
+     {
+        pd->parent = parent;
+        pd->data = parent ? eo_data_scope_get(parent, EVAS_OBJECT_CLASS) : NULL;
+     }
 }
 
 void
-_evas_vg_root_node_eo_base_constructor(Eo *obj,
-                                       Evas_VG_Root_Node_Data *pd EINA_UNUSED)
+_efl_vg_root_node_eo_base_constructor(Eo *obj,
+                                      Efl_VG_Root_Node_Data *pd)
 {
+   Efl_VG_Container_Data *cd;
+   Efl_VG_Base_Data *nd;
    Eo *parent;
-   Evas_VG_Node_Data *nd;
 
-   // Nice little hack, jump over parent constructor in Evas_VG_Root
-   eo_do_super(obj, EVAS_VG_NODE_CLASS, eo_constructor());
+   // Nice little hack, jump over parent constructor in Efl_VG_Root
+   eo_do_super(obj, EFL_VG_BASE_CLASS, eo_constructor());
    eo_do(obj, parent = eo_parent_get());
-   nd = eo_data_scope_get(obj, EVAS_VG_NODE_CLASS);
-   nd->render_pre = &_evas_vg_root_node_render_pre;
+   if (!eo_isa(parent, EVAS_VG_CLASS))
+     eo_error_set(obj);
 
-   evas_vg_root_node_vg_set(obj, parent);
-}
+   cd = eo_data_scope_get(obj, EFL_VG_CONTAINER_CLASS);
+   cd->children = NULL;
 
-void
-_evas_vg_root_node_eo_base_destructor(Eo *obj,
-                                      Evas_VG_Root_Node_Data *pd EINA_UNUSED)
-{
-   evas_vg_root_node_vg_set(obj, NULL);
-   eo_do_super(obj, MY_CLASS, eo_destructor());
+   nd = eo_data_scope_get(obj, EFL_VG_BASE_CLASS);
+   nd->render_pre = _evas_vg_root_node_render_pre;
+   nd->data = cd;
+
+   eo_do(obj, eo_event_callback_add(EFL_GFX_CHANGED, _evas_vg_root_node_changed, pd));
 }
 
-#include "evas_vg_root_node.eo.c"
+#include "efl_vg_root_node.eo.c"
index bda7383..71a987f 100644 (file)
@@ -3,20 +3,17 @@
 
 #include "evas_vg_private.h"
 
-#define MY_CLASS EVAS_VG_SHAPE_CLASS
+#define MY_CLASS EFL_VG_SHAPE_CLASS
 
-typedef struct _Evas_VG_Shape_Data Evas_VG_Shape_Data;
-struct _Evas_VG_Shape_Data
+typedef struct _Efl_VG_Shape_Data Efl_VG_Shape_Data;
+struct _Efl_VG_Shape_Data
 {
-   Efl_Gfx_Path_Command *ops;
-   double *points;
-
-   Evas_VG_Node *fill;
+   Efl_VG *fill;
 
    struct {
       Efl_Gfx_Dash *dash;
-      Evas_VG_Node *fill;
-      Evas_VG_Node *marker;
+      Efl_VG *fill;
+      Efl_VG *marker;
 
       double scale;
       double width;
@@ -31,91 +28,86 @@ struct _Evas_VG_Shape_Data
    } stroke;
 };
 
-static void
-_evas_vg_shape_efl_gfx_shape_path_set(Eo *obj EINA_UNUSED,
-                                      Evas_VG_Shape_Data *pd,
-                                      const Efl_Gfx_Path_Command *ops,
-                                      const double *points)
-{
-   free(pd->points);
-   pd->points = NULL;
-   free(pd->ops);
-   pd->ops = NULL;
-   efl_gfx_path_dup(&pd->ops, &pd->points, ops, points);
-
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
-}
-
-static void
-_evas_vg_shape_efl_gfx_shape_path_get(Eo *obj EINA_UNUSED,
-                                      Evas_VG_Shape_Data *pd,
-                                      const Efl_Gfx_Path_Command **op,
-                                      const double **points)
-{
-   if (op) *op = pd->ops;
-   if (points) *points = pd->points;
-}
-
 static Eina_Bool
-_evas_vg_shape_evas_vg_node_bound_get(Eo *obj EINA_UNUSED,
-                                      Evas_VG_Shape_Data *pd EINA_UNUSED,
-                                      Eina_Rectangle *r EINA_UNUSED)
+_efl_vg_shape_efl_vg_base_bound_get(Eo *obj,
+                                    Efl_VG_Shape_Data *pd,
+                                    Eina_Rectangle *r)
 {
    return EINA_FALSE;
 }
 
 static void
-_evas_vg_shape_fill_set(Eo *obj,
-                        Evas_VG_Shape_Data *pd,
-                        Evas_VG_Node *f)
+_efl_vg_shape_fill_set(Eo *obj EINA_UNUSED,
+                       Efl_VG_Shape_Data *pd,
+                       Efl_VG *f)
 {
-   Evas_VG_Node *tmp = pd->fill;
+   Efl_VG *tmp = pd->fill;
 
    pd->fill = eo_ref(f);
    eo_unref(tmp);
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
-static Evas_VG_Node *
-_evas_vg_shape_fill_get(Eo *obj EINA_UNUSED, Evas_VG_Shape_Data *pd)
+static Efl_VG *
+_efl_vg_shape_fill_get(Eo *obj EINA_UNUSED, Efl_VG_Shape_Data *pd)
 {
    return pd->fill;
 }
 
 static void
-_evas_vg_shape_efl_gfx_shape_stroke_scale_set(Eo *obj,
-                                              Evas_VG_Shape_Data *pd,
-                                              double s)
+_efl_vg_shape_efl_gfx_shape_stroke_scale_set(Eo *obj EINA_UNUSED,
+                                             Efl_VG_Shape_Data *pd,
+                                             double s)
 {
    pd->stroke.scale = s;
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
 static double
-_evas_vg_shape_efl_gfx_shape_stroke_scale_get(Eo *obj EINA_UNUSED,
-                                              Evas_VG_Shape_Data *pd)
+_efl_vg_shape_efl_gfx_shape_stroke_scale_get(Eo *obj EINA_UNUSED,
+                                             Efl_VG_Shape_Data *pd)
 {
    return pd->stroke.scale;
 }
 
 static void
-_evas_vg_shape_efl_gfx_shape_stroke_color_set(Eo *obj,
-                                              Evas_VG_Shape_Data *pd,
-                                              int r, int g, int b, int a)
+_efl_vg_shape_efl_gfx_shape_stroke_color_set(Eo *obj EINA_UNUSED,
+                                             Efl_VG_Shape_Data *pd,
+                                             int r, int g, int b, int a)
 {
    pd->stroke.r = r;
    pd->stroke.g = g;
    pd->stroke.b = b;
    pd->stroke.a = a;
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+
+   _efl_vg_base_changed(obj);
+}
+
+static Eina_Bool
+_efl_vg_shape_efl_gfx_base_color_part_set(Eo *obj, Efl_VG_Shape_Data *pd,
+                                          const char * part,
+                                          int r, int g, int b, int a)
+{
+   Eina_Bool ret;
+
+   if (part && !strcmp(part, "stroke"))
+     {
+        _efl_vg_shape_efl_gfx_shape_stroke_color_set(obj, pd, r, g, b, a);
+        return EINA_TRUE;
+     }
+
+   eo_do_super(obj, EFL_VG_SHAPE_CLASS,
+               ret = efl_gfx_color_part_set(part, r, g, b, a));
+
+   return ret;
 }
 
 static void
-_evas_vg_shape_efl_gfx_shape_stroke_color_get(Eo *obj EINA_UNUSED,
-                                              Evas_VG_Shape_Data *pd,
-                                              int *r, int *g, int *b, int *a)
+_efl_vg_shape_efl_gfx_shape_stroke_color_get(Eo *obj EINA_UNUSED,
+                                             Efl_VG_Shape_Data *pd,
+                                             int *r, int *g, int *b, int *a)
 {
    if (r) *r = pd->stroke.r;
    if (g) *g = pd->stroke.g;
@@ -123,63 +115,84 @@ _evas_vg_shape_efl_gfx_shape_stroke_color_get(Eo *obj EINA_UNUSED,
    if (a) *a = pd->stroke.a;
 }
 
+static Eina_Bool
+_efl_vg_shape_efl_gfx_base_color_part_get(Eo *obj, Efl_VG_Shape_Data *pd,
+                                          const char * part,
+                                          int *r, int *g, int *b, int *a)
+{
+   Eina_Bool ret;
+
+   if (part && !strcmp(part, "stroke"))
+     {
+        _efl_vg_shape_efl_gfx_shape_stroke_color_get(obj, pd, r, g, b, a);
+        return EINA_TRUE;
+     }
+
+   eo_do_super(obj, EFL_VG_SHAPE_CLASS,
+               ret = efl_gfx_color_part_get(part, r, g, b, a));
+
+   return ret;
+}
+
 static void
-_evas_vg_shape_stroke_fill_set(Eo *obj,
-                               Evas_VG_Shape_Data *pd,
-                               Evas_VG_Node *f)
+_efl_vg_shape_stroke_fill_set(Eo *obj EINA_UNUSED,
+                              Efl_VG_Shape_Data *pd,
+                              Efl_VG *f)
 {
-   Evas_VG_Node *tmp = pd->fill;
+   Efl_VG *tmp = pd->fill;
 
    pd->stroke.fill = eo_ref(f);
    eo_unref(tmp);
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
-static Evas_VG_Node *
-_evas_vg_shape_stroke_fill_get(Eo *obj EINA_UNUSED,
-                               Evas_VG_Shape_Data *pd)
+static Efl_VG *
+_efl_vg_shape_stroke_fill_get(Eo *obj EINA_UNUSED,
+                              Efl_VG_Shape_Data *pd)
 {
    return pd->stroke.fill;
 }
 
 static void
-_evas_vg_shape_efl_gfx_shape_stroke_width_set(Eo *obj,
-                                              Evas_VG_Shape_Data *pd,
-                                              double w)
+_efl_vg_shape_efl_gfx_shape_stroke_width_set(Eo *obj EINA_UNUSED,
+                                             Efl_VG_Shape_Data *pd,
+                                             double w)
 {
    pd->stroke.width = w;
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+
+   _efl_vg_base_changed(obj);
 }
 
 static double
-_evas_vg_shape_efl_gfx_shape_stroke_width_get(Eo *obj EINA_UNUSED,
-                                              Evas_VG_Shape_Data *pd)
+_efl_vg_shape_efl_gfx_shape_stroke_width_get(Eo *obj EINA_UNUSED,
+                                             Efl_VG_Shape_Data *pd)
 {
    return pd->stroke.width;
 }
 
 static void
-_evas_vg_shape_efl_gfx_shape_stroke_location_set(Eo *obj,
-                                                 Evas_VG_Shape_Data *pd,
-                                                 double centered)
+_efl_vg_shape_efl_gfx_shape_stroke_location_set(Eo *obj EINA_UNUSED,
+                                                Efl_VG_Shape_Data *pd,
+                                                double centered)
 {
    pd->stroke.centered = centered;
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+
+   _efl_vg_base_changed(obj);
 }
 
 static double
-_evas_vg_shape_efl_gfx_shape_stroke_location_get(Eo *obj EINA_UNUSED,
-                                                 Evas_VG_Shape_Data *pd)
+_efl_vg_shape_efl_gfx_shape_stroke_location_get(Eo *obj EINA_UNUSED,
+                                                Efl_VG_Shape_Data *pd)
 {
    return pd->stroke.centered;
 }
 
 static void
-_evas_vg_shape_efl_gfx_shape_stroke_dash_set(Eo *obj,
-                                             Evas_VG_Shape_Data *pd,
-                                             const Efl_Gfx_Dash *dash,
-                                             unsigned int length)
+_efl_vg_shape_efl_gfx_shape_stroke_dash_set(Eo *obj EINA_UNUSED,
+                                            Efl_VG_Shape_Data *pd,
+                                            const Efl_Gfx_Dash *dash,
+                                            unsigned int length)
 {
    free(pd->stroke.dash);
    pd->stroke.dash = NULL;
@@ -191,161 +204,341 @@ _evas_vg_shape_efl_gfx_shape_stroke_dash_set(Eo *obj,
    memcpy(pd->stroke.dash, dash, sizeof (Efl_Gfx_Dash) * length);
    pd->stroke.dash_count = length;
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
 static void
-_evas_vg_shape_efl_gfx_shape_stroke_dash_get(Eo *obj EINA_UNUSED,
-                                             Evas_VG_Shape_Data *pd,
-                                             const Efl_Gfx_Dash **dash,
-                                             unsigned int *length)
+_efl_vg_shape_efl_gfx_shape_stroke_dash_get(Eo *obj EINA_UNUSED,
+                                            Efl_VG_Shape_Data *pd,
+                                            const Efl_Gfx_Dash **dash,
+                                            unsigned int *length)
 {
    if (dash) *dash = pd->stroke.dash;
    if (length) *length = pd->stroke.dash_count;
 }
 
 static void
-_evas_vg_shape_stroke_marker_set(Eo *obj,
-                                 Evas_VG_Shape_Data *pd,
-                                 Evas_VG_Shape *m)
+_efl_vg_shape_stroke_marker_set(Eo *obj EINA_UNUSED,
+                                Efl_VG_Shape_Data *pd,
+                                Efl_VG_Shape *m)
 {
-   Evas_VG_Node *tmp = pd->stroke.marker;
+   Efl_VG *tmp = pd->stroke.marker;
 
    pd->stroke.marker = eo_ref(m);
    eo_unref(tmp);
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
-static Evas_VG_Shape *
-_evas_vg_shape_stroke_marker_get(Eo *obj EINA_UNUSED,
-                                 Evas_VG_Shape_Data *pd)
+static Efl_VG_Shape *
+_efl_vg_shape_stroke_marker_get(Eo *obj EINA_UNUSED,
+                                Efl_VG_Shape_Data *pd)
 {
    return pd->stroke.marker;
 }
 
 static void
-_evas_vg_shape_efl_gfx_shape_stroke_cap_set(Eo *obj EINA_UNUSED,
-                                            Evas_VG_Shape_Data *pd,
-                                            Efl_Gfx_Cap c)
+_efl_vg_shape_efl_gfx_shape_stroke_cap_set(Eo *obj EINA_UNUSED,
+                                           Efl_VG_Shape_Data *pd,
+                                           Efl_Gfx_Cap c)
 {
    pd->stroke.cap = c;
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
 static Efl_Gfx_Cap
-_evas_vg_shape_efl_gfx_shape_stroke_cap_get(Eo *obj EINA_UNUSED,
-                                            Evas_VG_Shape_Data *pd)
+_efl_vg_shape_efl_gfx_shape_stroke_cap_get(Eo *obj EINA_UNUSED,
+                                           Efl_VG_Shape_Data *pd)
 {
    return pd->stroke.cap;
 }
 
 static void
-_evas_vg_shape_efl_gfx_shape_stroke_join_set(Eo *obj EINA_UNUSED,
-                                             Evas_VG_Shape_Data *pd,
-                                             Efl_Gfx_Join j)
+_efl_vg_shape_efl_gfx_shape_stroke_join_set(Eo *obj EINA_UNUSED,
+                                            Efl_VG_Shape_Data *pd,
+                                            Efl_Gfx_Join j)
 {
    pd->stroke.join = j;
 
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
+   _efl_vg_base_changed(obj);
 }
 
 static Efl_Gfx_Join
-_evas_vg_shape_efl_gfx_shape_stroke_join_get(Eo *obj EINA_UNUSED,
-                                             Evas_VG_Shape_Data *pd)
+_efl_vg_shape_efl_gfx_shape_stroke_join_get(Eo *obj EINA_UNUSED,
+                                            Efl_VG_Shape_Data *pd)
 {
    return pd->stroke.join;
 }
 
 static void
-_evas_vg_shape_efl_gfx_base_color_set(Eo *obj,
-                                      Evas_VG_Shape_Data *pd,
-                                      int r, int g, int b, int a)
+_efl_vg_shape_render_pre(Eo *obj EINA_UNUSED,
+                         Eina_Matrix3 *parent,
+                         Ector_Surface *s,
+                         void *data,
+                         Efl_VG_Base_Data *nd)
 {
-   eo_do_super(obj, MY_CLASS, efl_gfx_color_set(r, g, b, a));
-   eo_do_super(obj, MY_CLASS, evas_vg_node_changed());
-}
+   Efl_VG_Shape_Data *pd = data;
+   Efl_VG_Base_Data *fill, *stroke_fill, *stroke_marker, *mask;
+   double xn = nd->x, yn = nd->y ;
 
-static Eina_Bool
-_evas_vg_shape_render_pre(Eo *obj EINA_UNUSED,
-                          Eina_Matrix3 *parent,
-                          Ector_Surface *s,
-                          void *data,
-                          Evas_VG_Node_Data *nd)
-{
-   Evas_VG_Shape_Data *pd = data;
-   Ector_Renderer *fill_r = NULL, *stroke_r = NULL;
-   EVAS_VG_COMPUTE_MATRIX(current, parent, nd);
+   if (!nd->changed) return ;
+   nd->changed = EINA_FALSE;
 
-   if(pd->fill)
-     {
-         _evas_vg_render_pre(pd->fill, s, current);
-         Evas_VG_Node_Data *filld = eo_data_scope_get(pd->fill, EVAS_VG_NODE_CLASS);
-         fill_r = filld->renderer;
-     }
-   if(pd->stroke.fill)
-     {
-         _evas_vg_render_pre(pd->stroke.fill, s, current);
-         Evas_VG_Node_Data *filld = eo_data_scope_get(pd->stroke.fill, EVAS_VG_NODE_CLASS);
-         stroke_r = filld->renderer;
-     }
+   if(parent) eina_matrix3_point_transform(parent, nd->x, nd->y, &xn, &yn);
+
+   EFL_VG_COMPUTE_MATRIX(current, parent, nd);
 
-   _evas_vg_render_pre(pd->stroke.marker, s, current);
-   _evas_vg_render_pre(nd->mask, s, current);
+   fill = _evas_vg_render_pre(pd->fill, s, current);
+   stroke_fill = _evas_vg_render_pre(pd->stroke.fill, s, current);
+   stroke_marker = _evas_vg_render_pre(pd->stroke.marker, s, current);
+   mask = _evas_vg_render_pre(nd->mask, s, current);
 
    if (!nd->renderer)
      {
-        eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_SHAPE_CLASS));
+        eo_do(s, nd->renderer = ector_surface_renderer_factory_new(ECTOR_RENDERER_GENERIC_SHAPE_MIXIN));
      }
 
    eo_do(nd->renderer,
          ector_renderer_transformation_set(current),
-         ector_renderer_origin_set(nd->x, nd->y),
+         ector_renderer_origin_set(xn, yn),
          ector_renderer_color_set(nd->r, nd->g, nd->b, nd->a),
          ector_renderer_visibility_set(nd->visibility),
-         ector_renderer_mask_set(nd->mask),
-         ector_renderer_shape_fill_set(fill_r),
-         ector_renderer_shape_stroke_fill_set(stroke_r),
-         ector_renderer_shape_stroke_marker_set(pd->stroke.marker),
-         efl_gfx_shape_stroke_scale_set(pd->stroke.scale),
-         efl_gfx_shape_stroke_color_set(pd->stroke.r,
-                                        pd->stroke.g,
-                                        pd->stroke.b,
-                                        pd->stroke.a),
-         efl_gfx_shape_stroke_width_set(pd->stroke.width),
-         efl_gfx_shape_stroke_location_set(pd->stroke.centered),
-         efl_gfx_shape_stroke_dash_set(pd->stroke.dash, pd->stroke.dash_count),
-         efl_gfx_shape_stroke_cap_set(pd->stroke.cap),
-         efl_gfx_shape_stroke_join_set(pd->stroke.join),
-         efl_gfx_shape_path_set(pd->ops, pd->points),
+         ector_renderer_mask_set(mask ? mask->renderer : NULL),
+         ector_renderer_shape_fill_set(fill ? fill->renderer : NULL),
+         ector_renderer_shape_stroke_fill_set(stroke_fill ? stroke_fill->renderer : NULL),
+         ector_renderer_shape_stroke_marker_set(stroke_marker ? stroke_marker->renderer : NULL),
+         efl_gfx_shape_dup(obj),
          ector_renderer_prepare());
-
-   return EINA_TRUE;
 }
 
 static void
-_evas_vg_shape_eo_base_constructor(Eo *obj, Evas_VG_Shape_Data *pd)
+_efl_vg_shape_eo_base_constructor(Eo *obj, Efl_VG_Shape_Data *pd)
 {
-   Evas_VG_Node_Data *nd;
+   Efl_VG_Base_Data *nd;
 
    eo_do_super(obj, MY_CLASS, eo_constructor());
 
    pd->stroke.cap = EFL_GFX_CAP_BUTT;
    pd->stroke.join = EFL_GFX_JOIN_MITER;
    pd->stroke.scale = 1;
-   pd->stroke.a = 0;
    pd->stroke.centered = 0.5;
 
-   nd = eo_data_scope_get(obj, EVAS_VG_NODE_CLASS);
-   nd->render_pre = &_evas_vg_shape_render_pre;
+   nd = eo_data_scope_get(obj, EFL_VG_BASE_CLASS);
+   nd->render_pre = _efl_vg_shape_render_pre;
    nd->data = pd;
 }
 
 static void
-_evas_vg_shape_eo_base_destructor(Eo *obj, Evas_VG_Shape_Data *pd EINA_UNUSED)
+_efl_vg_shape_eo_base_destructor(Eo *obj, Efl_VG_Shape_Data *pd EINA_UNUSED)
 {
    eo_do_super(obj, MY_CLASS, eo_destructor());
 }
 
-#include "evas_vg_shape.eo.c"
+EAPI double
+evas_vg_shape_stroke_scale_get(Eo *obj)
+{
+   return eo_do(obj, efl_gfx_shape_stroke_scale_get());
+}
+
+EAPI void
+evas_vg_shape_stroke_scale_set(Eo *obj, double s)
+{
+   eo_do(obj, efl_gfx_shape_stroke_scale_set(s));
+}
+
+EAPI void
+evas_vg_shape_stroke_color_get(Eo *obj, int *r, int *g, int *b, int *a)
+{
+   eo_do(obj, efl_gfx_shape_stroke_color_get(r, g, b, a));
+}
+
+EAPI void
+evas_vg_shape_stroke_color_set(Eo *obj, int r, int g, int b, int a)
+{
+   eo_do(obj, efl_gfx_shape_stroke_color_set(r, g, b, a));
+}
+
+EAPI double
+evas_vg_shape_stroke_width_get(Eo *obj)
+{
+   return eo_do(obj, efl_gfx_shape_stroke_width_get());
+}
+
+EAPI void
+evas_vg_shape_stroke_width_set(Eo *obj, double w)
+{
+   eo_do(obj, efl_gfx_shape_stroke_width_set(w));
+}
+
+EAPI double
+evas_vg_shape_stroke_location_get(Eo *obj)
+{
+
+   return eo_do(obj, efl_gfx_shape_stroke_location_get());
+}
+
+EAPI void
+evas_vg_shape_stroke_location_set(Eo *obj, double centered)
+{
+   eo_do(obj, efl_gfx_shape_stroke_location_set(centered));
+}
+
+EAPI void
+evas_vg_shape_stroke_dash_get(Eo *obj, const Efl_Gfx_Dash **dash, unsigned int *length)
+{
+   eo_do(obj, efl_gfx_shape_stroke_dash_get(dash, length));
+}
+
+EAPI void
+evas_vg_shape_stroke_dash_set(Eo *obj, const Efl_Gfx_Dash *dash, unsigned int length)
+{
+   eo_do(obj, efl_gfx_shape_stroke_dash_set(dash, length));
+}
+
+EAPI Efl_Gfx_Cap
+evas_vg_shape_stroke_cap_get(Eo *obj)
+{
+   return eo_do(obj, efl_gfx_shape_stroke_cap_get());
+}
+
+EAPI void
+evas_vg_shape_stroke_cap_set(Eo *obj, Efl_Gfx_Cap c)
+{
+   eo_do(obj, efl_gfx_shape_stroke_cap_set(c));
+}
+
+EAPI Efl_Gfx_Join
+evas_vg_shape_stroke_join_get(Eo *obj)
+{
+   return eo_do(obj, efl_gfx_shape_stroke_join_get());
+}
+
+EAPI void
+evas_vg_shape_stroke_join_set(Eo *obj, Efl_Gfx_Join j)
+{
+   eo_do(obj, efl_gfx_shape_stroke_join_set(j));
+}
+
+EAPI void
+evas_vg_shape_shape_path_set(Eo *obj, const Efl_Gfx_Path_Command *op, const double *points)
+{
+   eo_do(obj, efl_gfx_shape_path_set(op, points));
+}
+
+EAPI void
+evas_vg_shape_shape_path_get(Eo *obj, const Efl_Gfx_Path_Command **op, const double **points)
+{
+   eo_do(obj, efl_gfx_shape_path_get(op, points));
+}
+
+EAPI void
+evas_vg_shape_shape_path_length_get(Eo *obj, unsigned int *commands, unsigned int *points)
+{
+   eo_do(obj, efl_gfx_shape_path_length_get(commands, points));
+}
+
+EAPI void
+evas_vg_shape_shape_current_get(Eo *obj, double *x, double *y)
+{
+   eo_do(obj, efl_gfx_shape_current_get(x, y));
+}
+
+EAPI void
+evas_vg_shape_shape_current_ctrl_get(Eo *obj, double *x, double *y)
+{
+   eo_do(obj, efl_gfx_shape_current_ctrl_get(x, y));
+}
+
+EAPI void
+evas_vg_shape_shape_dup(Eo *obj, Eo *dup_from)
+{
+   eo_do(obj, efl_gfx_shape_dup(dup_from));
+}
+
+EAPI void
+evas_vg_shape_shape_reset(Eo *obj)
+{
+   eo_do(obj, efl_gfx_shape_reset());
+}
+
+EAPI void
+evas_vg_shape_shape_append_move_to(Eo *obj, double x, double y)
+{
+   eo_do(obj, efl_gfx_shape_append_move_to(x, y));
+}
+
+EAPI void
+evas_vg_shape_shape_append_line_to(Eo *obj, double x, double y)
+{
+   eo_do(obj, efl_gfx_shape_append_line_to(x, y));
+}
+
+EAPI void
+evas_vg_shape_shape_append_quadratic_to(Eo *obj, double x, double y, double ctrl_x, double ctrl_y)
+{
+   eo_do(obj, efl_gfx_shape_append_quadratic_to(x, y, ctrl_x, ctrl_y));
+}
+
+EAPI void
+evas_vg_shape_shape_append_squadratic_to(Eo *obj, double x, double y)
+{
+   eo_do(obj, efl_gfx_shape_append_squadratic_to(x, y));
+}
+
+EAPI void
+evas_vg_shape_shape_append_cubic_to(Eo *obj, double x, double y, double ctrl_x0, double ctrl_y0, double ctrl_x1, double ctrl_y1)
+{
+   eo_do(obj, efl_gfx_shape_append_cubic_to(x, y, ctrl_x0, ctrl_y0, ctrl_x1, ctrl_y1));
+}
+
+EAPI void
+evas_vg_shape_shape_append_scubic_to(Eo *obj, double x, double y, double ctrl_x, double ctrl_y)
+{
+   eo_do(obj, efl_gfx_shape_append_scubic_to(x, y, ctrl_x, ctrl_y));
+}
+
+EAPI void
+evas_vg_shape_shape_append_arc_to(Eo *obj, double x, double y, double rx, double ry, double angle, Eina_Bool large_arc, Eina_Bool sweep)
+{
+   eo_do(obj, efl_gfx_shape_append_arc_to(x, y, rx, ry, angle, large_arc, sweep));
+}
+
+EAPI void
+evas_vg_shape_shape_append_close(Eo *obj)
+{
+   eo_do(obj, efl_gfx_shape_append_close());
+}
+
+EAPI void
+evas_vg_shape_shape_append_circle(Eo *obj, double x, double y, double radius)
+{
+   eo_do(obj, efl_gfx_shape_append_circle(x, y, radius));
+}
+
+EAPI void
+evas_vg_shape_shape_append_rect(Eo *obj, double x, double y, double w, double h, double rx, double ry)
+{
+   eo_do(obj, efl_gfx_shape_append_rect(x, y, w, h, rx, ry));
+}
+
+EAPI void
+evas_vg_shape_shape_append_svg_path(Eo *obj, const char *svg_path_data)
+{
+   eo_do(obj, efl_gfx_shape_append_svg_path(svg_path_data));
+}
+
+EAPI Eina_Bool
+evas_vg_shape_shape_interpolate(Eo *obj, const Eo *from, const Eo *to, double pos_map)
+{
+   return eo_do(obj, efl_gfx_shape_interpolate(from, to, pos_map));
+}
+
+EAPI Eina_Bool
+evas_vg_shape_shape_equal_commands(Eo *obj, const Eo *with)
+{
+
+   return eo_do(obj, efl_gfx_shape_equal_commands(with));
+}
+
+#include "efl_vg_shape.eo.c"
index e6da210..7bef005 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <Eina.h>
 #include <eina_safety_checks.h>
+#include <Ector.h>
 
 #include "Evas.h"
 
@@ -717,6 +718,7 @@ struct _Evas_Public_Data
    struct {
       Evas_Module *module;
       Evas_Func *func;
+      Ector_Surface *surface;
       struct {
          void *output;
 
@@ -1334,9 +1336,10 @@ struct _Evas_Func
    void  (*texture_image_set)            (void *data, void *texture, void *image);
 
    void  (*output_copy)                  (void *data, void *buffer, int stride, int width, int height, uint format, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);
-   void *(*ector_begin)                   (void *data, void *surface, int width, int height);
    Ector_Surface *(*ector_get)           (void *data);
-   void  (*ector_draw)                   (void *data, void *context, void *surface, Ector_Renderer *r, Eina_Array *clips, int x, int y, Eina_Bool do_async);
+   void  (*ector_begin)                  (void *data, void *context, void *surface, int x, int y, Eina_Bool do_async);
+   void  (*ector_renderer_draw)          (void *data, void *context, void *surface, Ector_Renderer *r, Eina_Array *clips, Eina_Bool do_async);
+   void  (*ector_end)                    (void *data, void *context, void *surface, Eina_Bool do_async);
 };
 
 struct _Evas_Image_Save_Func
diff --git a/src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo b/src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo
new file mode 100644 (file)
index 0000000..d5070ab
--- /dev/null
@@ -0,0 +1,18 @@
+class Ector.Cairo_Software.Surface (Ector.Cairo.Surface)
+{
+   eo_prefix: ector_cairo_software_surface;
+   legacy_prefix: null;
+   properties {
+      surface {
+         set {
+        }
+        get {
+        }
+        values {
+           void *pixels;
+           uint width;
+           uint height;
+        }
+      }
+   }
+}
index bec0208..103ec41 100644 (file)
 
 #include "Evas_Engine_GL_Generic.h"
 
-
-#include "software/Ector_Software.h"
-
-
 #ifdef EVAS_CSERVE2
 #include "evas_cs2_private.h"
 #endif
 
+#include "cairo/Ector_Cairo.h"
+#include "software/Ector_Software.h"
+
+#include "ector_cairo_software_surface.eo.h"
+
 #define EVAS_GL_NO_GL_H_CHECK 1
 #include "Evas_GL.h"
 
@@ -1928,57 +1929,31 @@ eng_texture_image_set(void *data EINA_UNUSED, void *texture, void *image)
    e3d_texture_import((E3D_Texture *)texture, im->tex->pt->texture);
 }
 
-
-// Opengl hack for ector START
-
 static Ector_Surface *_software_ector = NULL;
+static Eina_Bool use_cairo;
 
 static Ector_Surface *
 eng_ector_get(void *data EINA_UNUSED)
 {
    if (!_software_ector)
      {
-        _software_ector = eo_add(ECTOR_SOFTWARE_SURFACE_CLASS, NULL);
+        const char *ector_backend;
+
+        ector_backend = getenv("ECTOR_BACKEND");
+        if (ector_backend && !strcasecmp(ector_backend, "freetype"))
+          {
+             _software_ector = eo_add(ECTOR_SOFTWARE_SURFACE_CLASS, NULL);
+             use_cairo = EINA_FALSE;
+          }
+        else
+          {
+             _software_ector = eo_add(ECTOR_CAIRO_SOFTWARE_SURFACE_CLASS, NULL);
+             use_cairo = EINA_TRUE;
+          }
      }
    return _software_ector;
 }
 
-static void *
-eng_ector_begin(void *data, void *surface, int width, int height )
-{
-   if (!surface) {
-    return eng_image_new_from_copied_data(data, width, height, NULL, EINA_TRUE, EVAS_COLORSPACE_ARGB8888);
-   } else {
-      int cur_w , cur_h;
-      Evas_GL_Image *glim = surface;
-      cur_w = glim->im->cache_entry.w;
-      cur_h = glim->im->cache_entry.h;
-      if (width != cur_w || height != cur_h) {
-        eng_image_free(data, surface);
-        return eng_image_new_from_copied_data(data, width, height, NULL, EINA_TRUE, EVAS_COLORSPACE_ARGB8888);
-      }
-      // clear the buffer.
-      void *pixels = evas_cache_image_pixels(&glim->im->cache_entry);
-      memset(pixels, 0, cur_w * cur_h *4);
-   }
-   return surface;
-}
-
-struct _Evas_Thread_Command_Ector
-{
-   void *surface;
-   Ector_Renderer *r;
-   Eina_Array *clips;
-
-   DATA32 mul_col;
-   Ector_Rop render_op;
-   int x, y;
-
-   Eina_Bool free_it;
-};
-
-typedef struct _Evas_Thread_Command_Ector Evas_Thread_Command_Ector;
-
 static Ector_Rop
 _evas_render_op_to_ector_rop(Evas_Render_Op op)
 {
@@ -1994,82 +1969,40 @@ _evas_render_op_to_ector_rop(Evas_Render_Op op)
 }
 
 static void
-_draw_thread_ector_cleanup(Evas_Thread_Command_Ector *ector)
+eng_ector_renderer_draw(void *data, void *context EINA_UNUSED, void *surface, Ector_Renderer *renderer, Eina_Array *clips, int x, int y, Eina_Bool do_async EINA_UNUSED)
 {
+   Evas_GL_Image *dst = surface;
+   Evas_Engine_GL_Context *gc;
+   Render_Engine_GL_Generic *re = data;
    Eina_Rectangle *r;
-
-   while ((r = eina_array_pop(ector->clips)))
-     eina_rectangle_free(r);
-   eina_array_free(ector->clips);
-   eo_unref(ector->r);
-
-}
-
-static void
-_draw_thread_ector_draw(void *data)
-{
-   Evas_Thread_Command_Ector *ector = data;
-   RGBA_Image *surface = ector->surface;
-   void *pixels = evas_cache_image_pixels(&surface->cache_entry);
-   unsigned int w, h;
-
-   w = surface->cache_entry.w;
-   h = surface->cache_entry.h;
-
-   // FIXME: do not reset cairo context if not necessary
-   eo_do(_software_ector,
-         ector_surface_set(pixels, w, h));
-
-   eo_do(ector->r,
-         ector_renderer_draw(ector->render_op,
-                             ector->clips,
-                             ector->x,
-                             ector->y,
-                             ector->mul_col));
-
-   evas_common_cpu_end_opt();
-
-   _draw_thread_ector_cleanup(ector);
-}
-
-static void
-eng_ector_draw(void *data EINA_UNUSED, void *context, 
-                void *surface, Ector_Renderer *renderer, 
-                Eina_Array *clips, int x, int y, Eina_Bool do_async EINA_UNUSED)
-{
-   Evas_GL_Image *gl_img = surface;
-   RGBA_Image *dst = gl_img->im;
-   RGBA_Draw_Context *dc = context;
-   Evas_Thread_Command_Ector ector;
    Eina_Array *c;
-   Eina_Rectangle *r;
    Eina_Rectangle clip;
    Eina_Array_Iterator it;
    unsigned int i;
 
-   if (0 && dc->clip.use)
+   gc = re->window_gl_context_get(re->software.ob);
+   if (gc->dc->clip.use)
      {
-        clip.x = dc->clip.x;
-        clip.y = dc->clip.y;
-        clip.w = dc->clip.w;
-        clip.h = dc->clip.h;
+        clip.x = gc->dc->clip.x;
+        clip.y = gc->dc->clip.y;
+        clip.w = gc->dc->clip.w;
+        clip.h = gc->dc->clip.h;
      }
    else
      {
         clip.x = 0;
         clip.y = 0;
-        clip.w = dst->cache_entry.w;
-        clip.h = dst->cache_entry.h;
+        clip.w = dst->w;
+        clip.h = dst->h;
      }
-   //Hermet: Multiple Clippers???
+
+   c = eina_array_new(8);
    if (clips)
      {
-        //printf("Multiple clips \n");
-        c = eina_array_new(8);
         EINA_ARRAY_ITER_NEXT(clips, i, r, it)
           {
              Eina_Rectangle *rc;
-             //printf("Multiple :%d , %d ,%d , %d\n",r->x, r->y, r->w, r->h);
+
              rc = eina_rectangle_new(r->x, r->y, r->w, r->h);
              if (!rc) continue;
 
@@ -2078,28 +2011,88 @@ eng_ector_draw(void *data EINA_UNUSED, void *context,
              else
                eina_rectangle_free(rc);
           }
+
+        if (eina_array_count(c) == 0 &&
+            eina_array_count(clips) > 0)
+          return ;
+     }
+
+   if (eina_array_count(c) == 0)
+     eina_array_push(c, eina_rectangle_new(clip.x, clip.y, clip.w, clip.h));
+
+   eo_do(renderer,
+         ector_renderer_draw(_evas_render_op_to_ector_rop(gc->dc->render_op),
+                             c,
+                             // mul_col will be applied by GL during ector_end
+                             0xffffffff));
+
+   while ((r = eina_array_pop(c)))
+     eina_rectangle_free(r);
+   eina_array_free(c);
+}
+
+static void *software_buffer = NULL;
+
+static void
+eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, void *surface, int x, int y, Eina_Bool do_async EINA_UNUSED)
+{
+   Evas_Engine_GL_Context *gl_context;
+   Render_Engine_GL_Generic *re = data;
+   int w, h;
+
+   re->window_use(re->software.ob);
+   gl_context = re->window_gl_context_get(re->software.ob);
+   evas_gl_common_context_target_surface_set(gl_context, surface);
+   gl_context->dc = context;
+
+   w = gl_context->w; h = gl_context->h;
+
+   software_buffer = realloc(software_buffer, sizeof (unsigned int) * w * h);
+   if (use_cairo)
+     {
+        eo_do(_software_ector,
+              ector_cairo_software_surface_set(software_buffer, w, h));
      }
    else
      {
-        //printf("Single Clip : %d , %d ,%d , %d\n",clip.x, clip.y, clip.w, clip.h);
-        c = eina_array_new(1);
-        eina_array_push(c, eina_rectangle_new(clip.x, clip.y, clip.w, clip.h));
+        eo_do(_software_ector,
+              ector_software_surface_set(software_buffer, w, h));
      }
+}
 
-   ector.surface = dst;
-   ector.r = eo_ref(renderer);
-   ector.clips = c;
-   ector.render_op = _evas_render_op_to_ector_rop(dc->render_op);
-   ector.mul_col = dc->col.col;
-   ector.x = x;
-   ector.y = y;
-   ector.free_it = EINA_FALSE;
+static void
+eng_ector_end(void *data, void *context EINA_UNUSED, void *surface EINA_UNUSED, Eina_Bool do_async EINA_UNUSED)
+{
+   Evas_Engine_GL_Context *gl_context;
+   Render_Engine_GL_Generic *re = data;
+   Evas_GL_Image *im;
+   int w, h;
 
-    _draw_thread_ector_draw(&ector);
-}
+   gl_context = re->window_gl_context_get(re->software.ob);
+   w = gl_context->w; h = gl_context->h;
+
+   if (use_cairo)
+     {
+        eo_do(_software_ector,
+              ector_cairo_software_surface_set(NULL, 0, 0));
+     }
+   else
+     {
+        eo_do(_software_ector,
+              ector_software_surface_set(NULL, 0, 0));
+     }
 
+   im = evas_gl_common_image_new_from_copied_data(gl_context, w, h, software_buffer, 1, EVAS_COLORSPACE_ARGB8888);
+   // We actually just bluntly push the pixel all over the
+   // destination surface. We don't have the actual information
+   // of the widget size. This is not a problem.
+   // Later on, we don't want that information and today when
+   // using GL backend, you just need to turn on Evas_Map on
+   // the Evas_Object_VG.
+   evas_gl_common_image_draw(gl_context, im, 0, 0, w, h, 0, 0, w, h, 0);
 
-// opengl hack for ector END
+   evas_gl_common_image_free(im);
+}
 
 static Evas_Func func, pfunc;
 
@@ -2234,10 +2227,10 @@ module_open(Evas_Module *em)
    ORD(texture_filter_get);
    ORD(texture_image_set);
 
-   /* ector features */
-   ORD(ector_begin);
    ORD(ector_get);
-   ORD(ector_draw);
+   ORD(ector_begin);
+   ORD(ector_renderer_draw);
+   ORD(ector_end);
 
    /* now advertise out own api */
    em->functions = (void *)(&func);
index 9ae9782..9387f31 100644 (file)
@@ -2,9 +2,18 @@ class Ector.Cairo_Software.Surface (Ector.Cairo.Surface)
 {
    eo_prefix: ector_cairo_software_surface;
    legacy_prefix: null;
-   implements {
-      Ector.Generic.Surface.surface.set;
-      Ector.Generic.Surface.surface.get;
+   properties {
+      surface {
+         set {
+        }
+        get {
+        }
+        values {
+           void *pixels;
+           uint width;
+           uint height;
+        }
+      }
    }
    implements {
       Eo.Base.finalize;
index 9028999..6af3e5e 100644 (file)
 
 #include "cairo/Ector_Cairo.h"
 
-#include "ector_cairo_software_surface.eo.h"
-
 #include "software/Ector_Software.h"
 
+#include "ector_cairo_software_surface.eo.h"
+
 #ifdef EVAS_GL
 //----------------------------------//
 // OSMesa...
@@ -295,6 +295,8 @@ typedef struct _Evas_Thread_Command_Image Evas_Thread_Command_Image;
 typedef struct _Evas_Thread_Command_Font Evas_Thread_Command_Font;
 typedef struct _Evas_Thread_Command_Map Evas_Thread_Command_Map;
 typedef struct _Evas_Thread_Command_Multi_Font Evas_Thread_Command_Multi_Font;
+typedef struct _Evas_Thread_Command_Ector Evas_Thread_Command_Ector;
+typedef struct _Evas_Thread_Command_Ector_Surface Evas_Thread_Command_Ector_Surface;
 
 struct _Evas_Thread_Command_Rect
 {
@@ -385,6 +387,23 @@ struct _Evas_Thread_Command_Multi_Font
    Evas_Font_Array *texts;
 };
 
+struct _Evas_Thread_Command_Ector
+{
+   Ector_Renderer *r;
+   Eina_Array *clips;
+
+   DATA32 mul_col;
+   Ector_Rop render_op;
+
+   Eina_Bool free_it;
+};
+
+struct _Evas_Thread_Command_Ector_Surface
+{
+   void *surface;
+   int x, y;
+};
+
 Eina_Mempool *_mp_command_rect = NULL;
 Eina_Mempool *_mp_command_line = NULL;
 Eina_Mempool *_mp_command_polygon = NULL;
@@ -392,7 +411,8 @@ Eina_Mempool *_mp_command_image = NULL;
 Eina_Mempool *_mp_command_font = NULL;
 Eina_Mempool *_mp_command_map = NULL;
 Eina_Mempool *_mp_command_multi_font = NULL;
-
+Eina_Mempool *_mp_command_ector = NULL;
+Eina_Mempool *_mp_command_ector_surface = NULL;
 /*
  *****
  **
@@ -3089,25 +3109,30 @@ eng_output_idle_flush(void *data)
 }
 
 static Ector_Surface *_software_ector = NULL;
+static Eina_Bool use_cairo;
 
 static Ector_Surface *
 eng_ector_get(void *data EINA_UNUSED)
 {
    if (!_software_ector)
      {
-        //TODO FIX it Properly
-        _software_ector = eo_add(ECTOR_SOFTWARE_SURFACE_CLASS, NULL);
-        //_software_ector = eo_add(ECTOR_CAIRO_SOFTWARE_SURFACE_CLASS, NULL);
+        const char *ector_backend;
+
+        ector_backend = getenv("ECTOR_BACKEND");
+        if (ector_backend && !strcasecmp(ector_backend, "freetype"))
+          {
+             _software_ector = eo_add(ECTOR_SOFTWARE_SURFACE_CLASS, NULL);
+             use_cairo = EINA_FALSE;
+          }
+        else
+          {
+             _software_ector = eo_add(ECTOR_CAIRO_SOFTWARE_SURFACE_CLASS, NULL);
+             use_cairo = EINA_TRUE;
+          }
      }
    return _software_ector;
 }
 
-static void *
-eng_ector_begin(void *data EINA_UNUSED, void *surface EINA_UNUSED, int width EINA_UNUSED, int height EINA_UNUSED)
-{
-   return NULL;
-}
-
 static Ector_Rop
 _evas_render_op_to_ector_rop(Evas_Render_Op op)
 {
@@ -3140,22 +3165,10 @@ static void
 _draw_thread_ector_draw(void *data)
 {
    Evas_Thread_Command_Ector *ector = data;
-   RGBA_Image *surface = ector->surface;
-   void *pixels = evas_cache_image_pixels(&surface->cache_entry);
-   unsigned int w, h;
-
-   w = surface->cache_entry.w;
-   h = surface->cache_entry.h;
-
-   // FIXME: do not reset cairo context if not necessary
-   eo_do(_software_ector,
-         ector_surface_set(pixels, w, h));
 
    eo_do(ector->r,
          ector_renderer_draw(ector->render_op,
                              ector->clips,
-                             ector->x,
-                             ector->y,
                              ector->mul_col));
 
    evas_common_cpu_end_opt();
@@ -3164,7 +3177,7 @@ _draw_thread_ector_draw(void *data)
 }
 
 static void
-eng_ector_renderer_draw(void *data EINA_UNUSED, void *context, void *surface, Ector_Renderer *renderer, Eina_Array *clips, int x, int y, Eina_Bool do_async)
+eng_ector_renderer_draw(void *data EINA_UNUSED, void *context, void *surface, Ector_Renderer *renderer, Eina_Array *clips, Eina_Bool do_async)
 {
    RGBA_Image *dst = surface;
    RGBA_Draw_Context *dc = context;
@@ -3189,15 +3202,14 @@ eng_ector_renderer_draw(void *data EINA_UNUSED, void *context, void *surface, Ec
         clip.w = dst->cache_entry.w;
         clip.h = dst->cache_entry.h;
      }
-   //Hermet: Multiple Clippers???
+
+   c = eina_array_new(8);
    if (clips)
      {
-        //printf("Multiple clips \n");
-        c = eina_array_new(8);
         EINA_ARRAY_ITER_NEXT(clips, i, r, it)
           {
              Eina_Rectangle *rc;
-             //printf("Multiple :%d , %d ,%d , %d\n",r->x, r->y, r->w, r->h);
+
              rc = eina_rectangle_new(r->x, r->y, r->w, r->h);
              if (!rc) continue;
 
@@ -3206,21 +3218,20 @@ eng_ector_renderer_draw(void *data EINA_UNUSED, void *context, void *surface, Ec
              else
                eina_rectangle_free(rc);
           }
-     }
-   else
-     {
-        //printf("Single Clip : %d , %d ,%d , %d\n",clip.x, clip.y, clip.w, clip.h);
-        c = eina_array_new(1);
-        eina_array_push(c, eina_rectangle_new(clip.x, clip.y, clip.w, clip.h));
+
+        if (eina_array_count(c) == 0 &&
+            eina_array_count(clips) > 0)
+          return ;
      }
 
-   ector.surface = surface;
+   if (eina_array_count(c) == 0)
+     eina_array_push(c, eina_rectangle_new(clip.x, clip.y, clip.w, clip.h));
+
    ector.r = eo_ref(renderer);
    ector.clips = c;
    ector.render_op = _evas_render_op_to_ector_rop(dc->render_op);
-   ector.mul_col = dc->col.col;
-   ector.x = x;
-   ector.y = y;
+   ector.mul_col = ector_color_multiply(dc->mul.use ? dc->mul.col : 0xffffffff,
+                                        dc->col.col);;
    ector.free_it = EINA_FALSE;
 
    if (do_async)
@@ -3245,6 +3256,108 @@ eng_ector_renderer_draw(void *data EINA_UNUSED, void *context, void *surface, Ec
      }
 }
 
+static void
+_draw_thread_ector_surface_set(void *data)
+{
+   Evas_Thread_Command_Ector_Surface *ector_surface = data;
+   RGBA_Image *surface = ector_surface->surface;
+   void *pixels = NULL;
+   unsigned int w = 0;
+   unsigned int h = 0;
+   unsigned int x = 0;
+   unsigned int y = 0;
+
+   if (surface)
+     {
+        pixels = evas_cache_image_pixels(&surface->cache_entry);
+        w = surface->cache_entry.w;
+        h = surface->cache_entry.h;
+        x = ector_surface->x;
+        y = ector_surface->y;
+     }
+
+   if (use_cairo)
+     {
+        eo_do(_software_ector,
+              ector_cairo_software_surface_set(pixels, w, h),
+              ector_surface_reference_point_set(x, y));
+     }
+   else
+     {
+        eo_do(_software_ector,
+              ector_software_surface_set(pixels, w, h),
+              ector_surface_reference_point_set(x, y));
+     }
+
+   evas_common_cpu_end_opt();
+
+   eina_mempool_free(_mp_command_ector_surface, ector_surface);
+}
+
+static void
+eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, void *surface, int x, int y, Eina_Bool do_async)
+{
+   if (do_async)
+     {
+        Evas_Thread_Command_Ector_Surface *nes;
+
+        nes = eina_mempool_malloc(_mp_command_ector_surface, sizeof (Evas_Thread_Command_Ector_Surface));
+        if (!nes) return ;
+
+        nes->surface = surface;
+        nes->x = x;
+        nes->y = y;
+
+        evas_thread_cmd_enqueue(_draw_thread_ector_surface_set, nes);
+     }
+   else
+     {
+        RGBA_Image *sf = surface;
+        void *pixels = NULL;
+        unsigned int w = 0;
+        unsigned int h = 0;
+
+        pixels = evas_cache_image_pixels(&sf->cache_entry);
+        w = sf->cache_entry.w;
+        h = sf->cache_entry.h;
+
+        if (use_cairo)
+          {
+             eo_do(_software_ector,
+                   ector_cairo_software_surface_set(pixels, w, h),
+                   ector_surface_reference_point_set(x, y));
+          }
+        else
+          {
+             eo_do(_software_ector,
+                   ector_software_surface_set(pixels, w, h),
+                   ector_surface_reference_point_set(x, y));
+          }
+     }
+}
+
+static void
+eng_ector_end(void *data EINA_UNUSED, void *context EINA_UNUSED, void *surface EINA_UNUSED, Eina_Bool do_async)
+{
+   if (do_async)
+     {
+        Evas_Thread_Command_Ector_Surface *nes;
+
+        nes = eina_mempool_malloc(_mp_command_ector_surface, sizeof (Evas_Thread_Command_Ector_Surface));
+        if (!nes) return ;
+
+        nes->surface = NULL;
+
+        evas_thread_cmd_enqueue(_draw_thread_ector_surface_set, nes);
+     }
+   else
+     {
+        eo_do(_software_ector, ector_cairo_software_surface_set(NULL, 0, 0));
+
+        evas_common_cpu_end_opt();
+     }
+}
+
 //------------------------------------------------//
 
 /*
@@ -3419,9 +3532,10 @@ static Evas_Func func =
      NULL, // eng_texture_filter_set
      NULL, // eng_texture_filter_get
      NULL, // eng_texture_image_set
-     eng_ector_begin,
      eng_ector_get,
-     eng_ector_renderer_draw
+     eng_ector_begin,
+     eng_ector_renderer_draw,
+     eng_ector_end
    /* FUTURE software generic calls go here */
 };
 
@@ -4470,6 +4584,12 @@ module_open(Evas_Module *em)
    _mp_command_multi_font =
      eina_mempool_add("chained_mempool", "Evas_Thread_Command_Multi_Font",
                       NULL, sizeof(Evas_Thread_Command_Multi_Font), 128);
+   _mp_command_ector =
+     eina_mempool_add("chained_mempool", "Evas_Thread_Command_Ector",
+                      NULL, sizeof(Evas_Thread_Command_Ector), 128);
+   _mp_command_ector_surface =
+     eina_mempool_add("chained_mempool", "Evas_Thread_Command_Ector_Surface",
+                      NULL, sizeof(Evas_Thread_Command_Ector_Surface), 128);
 
    init_gl();
    evas_common_pipe_init();
@@ -4488,6 +4608,7 @@ module_close(Evas_Module *em EINA_UNUSED)
    eina_mempool_del(_mp_command_image);
    eina_mempool_del(_mp_command_font);
    eina_mempool_del(_mp_command_map);
+   eina_mempool_del(_mp_command_ector);
    eina_log_domain_unregister(_evas_soft_gen_log_dom);
 }
 
@@ -4504,22 +4625,99 @@ static Evas_Module_Api evas_modapi =
 
 EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, software_generic);
 
+Eina_Bool evas_engine_software_generic_init(void)
+{
+   return evas_module_register(&evas_modapi, EVAS_MODULE_TYPE_ENGINE);
+}
+
+// Time to destroy the ector context
+void evas_engine_software_generic_shutdown(void)
+{
+   if (_software_ector) eo_del(_software_ector);
+   _software_ector = NULL;
+
+   evas_module_unregister(&evas_modapi, EVAS_MODULE_TYPE_ENGINE);
+}
+
 #ifndef EVAS_STATIC_BUILD_SOFTWARE_GENERIC
 EVAS_EINA_MODULE_DEFINE(engine, software_generic);
 #endif
 
+#define USE(Obj, Sym, Error)                            \
+  if (!Sym) Sym = _ector_cairo_symbol_get(Obj, #Sym);   \
+  if (!Sym) return Error;
+
+static inline void *
+_ector_cairo_symbol_get(Eo *ector_surface, const char *name)
+{
+   void *sym;
+
+   eo_do(ector_surface,
+         sym = ector_cairo_surface_symbol_get(name));
+   return sym;
+}
+
+typedef struct _cairo_surface_t cairo_surface_t;
+typedef enum {
+  CAIRO_FORMAT_INVALID   = -1,
+  CAIRO_FORMAT_ARGB32    = 0,
+  CAIRO_FORMAT_RGB24     = 1,
+  CAIRO_FORMAT_A8        = 2,
+  CAIRO_FORMAT_A1        = 3,
+  CAIRO_FORMAT_RGB16_565 = 4,
+  CAIRO_FORMAT_RGB30     = 5
+} cairo_format_t;
+
+static cairo_surface_t *(*cairo_image_surface_create_for_data)(unsigned char *data,
+                                                               cairo_format_t format,
+                                                               int width,
+                                                               int height,
+                                                               int stride) = NULL;
+static void (*cairo_surface_destroy)(cairo_surface_t *surface) = NULL;
+static cairo_t *(*cairo_create)(cairo_surface_t *target) = NULL;
+static void (*cairo_destroy)(cairo_t *cr) = NULL;
+
 typedef struct _Ector_Cairo_Software_Surface_Data Ector_Cairo_Software_Surface_Data;
 struct _Ector_Cairo_Software_Surface_Data
 {
 };
 
 void
-_ector_cairo_software_surface_ector_generic_surface_surface_set(Eo *obj, Ector_Cairo_Software_Surface_Data *pd, void *pixels, unsigned int width, unsigned int height)
+_ector_cairo_software_surface_surface_set(Eo *obj, Ector_Cairo_Software_Surface_Data *pd, void *pixels, unsigned int width, unsigned int height)
 {
+   USE(obj, cairo_image_surface_create_for_data, );
+   USE(obj, cairo_surface_destroy, );
+   USE(obj, cairo_create, );
+   USE(obj, cairo_destroy, );
+
+   if (pd->surface) cairo_surface_destroy(pd->surface); pd->surface = NULL;
+   if (pd->ctx) cairo_destroy(pd->ctx); pd->ctx = NULL;
+
+   pd->pixels = NULL;
+   pd->width = 0;
+   pd->height = 0;
+
+   if (pixels)
+     {
+        pd->surface = cairo_image_surface_create_for_data(pixels,
+                                                          CAIRO_FORMAT_ARGB32,
+                                                          width, height, width * sizeof (int));
+        if (!pd->surface) goto end;
+
+        pd->ctx = cairo_create(pd->surface);
+        if (!pd->ctx) goto end;
+     }
+
+   pd->pixels = pixels;
+   pd->width = width;
+   pd->height = height;
+
+ end:
+   eo_do(obj, ector_cairo_surface_context_set(pd->ctx));
 }
 
 void
-_ector_cairo_software_surface_ector_generic_surface_surface_get(Eo *obj EINA_UNUSED, Ector_Cairo_Software_Surface_Data *pd, void **pixels, unsigned int *width, unsigned int *height)
+_ector_cairo_software_surface_surface_get(Eo *obj EINA_UNUSED, Ector_Cairo_Software_Surface_Data *pd, void **pixels, unsigned int *width, unsigned int *height)
 {
 }