From eeb52084a277e96b98e91343ded73fd47212c32a Mon Sep 17 00:00:00 2001 From: Subhransu Sekhar Mohanty Date: Wed, 11 Mar 2015 19:22:43 +0900 Subject: [PATCH] ector : integration of ector library in efl1.30.0 branch for tizen2.4 Change-Id: I1f5e8482e4d8003e21afe75f51a2839a736567c7 --- configure.ac | 2 + pc/ector.pc | 12 + src/Makefile_Ector.am | 24 +- src/Makefile_Efl.am | 11 +- src/Makefile_Evas.am | 29 +- src/lib/ector/Ector.h | 1 + src/lib/ector/cairo/ector_cairo_private.h | 9 +- src/lib/ector/cairo/ector_cairo_surface.c | 69 +- src/lib/ector/cairo/ector_cairo_surface.eo | 1 + src/lib/ector/cairo/ector_renderer_cairo_base.c | 208 +++ src/lib/ector/cairo/ector_renderer_cairo_base.eo | 11 +- .../cairo/ector_renderer_cairo_gradient_linear.c | 21 +- .../cairo/ector_renderer_cairo_gradient_linear.eo | 4 +- .../cairo/ector_renderer_cairo_gradient_radial.c | 38 +- .../cairo/ector_renderer_cairo_gradient_radial.eo | 4 +- src/lib/ector/cairo/ector_renderer_cairo_shape.c | 69 +- src/lib/ector/cairo/ector_renderer_cairo_shape.eo | 1 - src/lib/ector/ector_generic_surface.eo | 19 +- src/lib/ector/ector_main.c | 12 +- src/lib/ector/ector_private.h | 51 +- src/lib/ector/ector_renderer_base.c | 10 + src/lib/ector/ector_renderer_generic_base.eo | 3 - src/lib/ector/ector_renderer_generic_gradient.eo | 10 +- .../ector_renderer_generic_gradient_linear.eo | 10 +- .../ector_renderer_generic_gradient_radial.eo | 14 +- src/lib/ector/ector_renderer_generic_shape.eo | 5 +- src/lib/ector/ector_renderer_gradient.c | 26 +- src/lib/ector/ector_renderer_shape.c | 39 +- src/lib/ector/ector_surface.c | 15 - src/lib/ector/ector_util.h | 13 + src/lib/ector/software/ector_blend_private.h | 117 -- src/lib/ector/software/ector_drawhelper.c | 176 +++ src/lib/ector/software/ector_drawhelper_private.h | 101 ++ src/lib/ector/software/ector_drawhelper_sse2.c | 359 ++++++ .../ector/software/ector_renderer_software_base.eo | 5 +- .../ector_renderer_software_gradient_linear.c | 67 +- .../ector_renderer_software_gradient_linear.eo | 4 +- .../ector_renderer_software_gradient_radial.c | 84 +- .../ector_renderer_software_gradient_radial.eo | 4 +- .../ector/software/ector_renderer_software_shape.c | 345 ++--- .../software/ector_renderer_software_shape.eo | 2 +- src/lib/ector/software/ector_software_gradient.c | 516 ++++++-- src/lib/ector/software/ector_software_private.h | 154 ++- src/lib/ector/software/ector_software_rasterizer.c | 582 +++++---- src/lib/ector/software/ector_software_surface.c | 69 +- src/lib/ector/software/ector_software_surface.eo | 14 +- src/lib/efl/Efl.h | 58 +- src/lib/efl/interfaces/efl_gfx_base.eo | 45 + src/lib/efl/interfaces/efl_gfx_fill.eo | 72 ++ src/lib/efl/interfaces/efl_gfx_gradient_base.eo | 38 + src/lib/efl/interfaces/efl_gfx_gradient_linear.eo | 6 +- src/lib/efl/interfaces/efl_gfx_gradient_radial.eo | 2 +- src/lib/efl/interfaces/efl_gfx_shape.c | 1333 ++++++++++++++++++++ src/lib/efl/interfaces/efl_gfx_shape.eo | 144 ++- src/lib/efl/interfaces/efl_gfx_stack.eo | 154 +++ src/lib/efl/interfaces/efl_gfx_view.eo | 27 + src/lib/efl/interfaces/efl_interfaces_main.c | 13 +- src/lib/evas/Evas_Common.h | 21 +- src/lib/evas/Evas_Eo.h | 14 +- src/lib/evas/Evas_Legacy.h | 81 +- src/lib/evas/canvas/efl_vg_base.eo | 106 ++ src/lib/evas/canvas/efl_vg_container.eo | 9 + src/lib/evas/canvas/efl_vg_gradient.eo | 10 + src/lib/evas/canvas/efl_vg_gradient_linear.eo | 12 + src/lib/evas/canvas/efl_vg_gradient_radial.eo | 14 + src/lib/evas/canvas/efl_vg_image.eo | 35 + src/lib/evas/canvas/efl_vg_root_node.eo | 8 + src/lib/evas/canvas/efl_vg_shape.eo | 47 + src/lib/evas/canvas/evas_object_vg.c | 134 +- src/lib/evas/canvas/evas_vg.eo | 77 +- src/lib/evas/canvas/evas_vg_container.c | 53 +- src/lib/evas/canvas/evas_vg_gradient.c | 60 +- src/lib/evas/canvas/evas_vg_gradient_linear.c | 99 +- src/lib/evas/canvas/evas_vg_gradient_radial.c | 118 +- src/lib/evas/canvas/evas_vg_image.c | 38 +- src/lib/evas/canvas/evas_vg_loader_svg.c | 12 +- src/lib/evas/canvas/evas_vg_node.c | 338 +++-- src/lib/evas/canvas/evas_vg_private.h | 55 +- src/lib/evas/canvas/evas_vg_root_node.c | 104 +- src/lib/evas/canvas/evas_vg_shape.c | 517 +++++--- src/lib/evas/include/evas_private.h | 7 +- .../gl_generic/ector_cairo_software_surface.eo | 18 + src/modules/evas/engines/gl_generic/evas_engine.c | 229 ++-- .../ector_cairo_software_surface.eo | 15 +- .../evas/engines/software_generic/evas_engine.c | 284 ++++- 85 files changed, 5864 insertions(+), 1883 deletions(-) create mode 100644 pc/ector.pc create mode 100644 src/lib/ector/cairo/ector_renderer_cairo_base.c create mode 100644 src/lib/ector/ector_util.h delete mode 100644 src/lib/ector/software/ector_blend_private.h create mode 100644 src/lib/ector/software/ector_drawhelper.c create mode 100644 src/lib/ector/software/ector_drawhelper_private.h create mode 100644 src/lib/ector/software/ector_drawhelper_sse2.c create mode 100644 src/lib/efl/interfaces/efl_gfx_fill.eo create mode 100644 src/lib/efl/interfaces/efl_gfx_gradient_base.eo create mode 100644 src/lib/efl/interfaces/efl_gfx_shape.c create mode 100644 src/lib/efl/interfaces/efl_gfx_stack.eo create mode 100644 src/lib/efl/interfaces/efl_gfx_view.eo create mode 100644 src/lib/evas/canvas/efl_vg_base.eo create mode 100644 src/lib/evas/canvas/efl_vg_container.eo create mode 100644 src/lib/evas/canvas/efl_vg_gradient.eo create mode 100644 src/lib/evas/canvas/efl_vg_gradient_linear.eo create mode 100644 src/lib/evas/canvas/efl_vg_gradient_radial.eo create mode 100644 src/lib/evas/canvas/efl_vg_image.eo create mode 100644 src/lib/evas/canvas/efl_vg_root_node.eo create mode 100644 src/lib/evas/canvas/efl_vg_shape.eo create mode 100644 src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo diff --git a/configure.ac b/configure.ac index a62495c..b20af4f 100644 --- a/configure.ac +++ b/configure.ac @@ -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 index 0000000..3df0995 --- /dev/null +++ b/pc/ector.pc @@ -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 diff --git a/src/Makefile_Ector.am b/src/Makefile_Ector.am index 9ed32d5..d6ff0ad 100644 --- a/src/Makefile_Ector.am +++ b/src/Makefile_Ector.am @@ -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 diff --git a/src/Makefile_Efl.am b/src/Makefile_Efl.am index 2525020..b65dafc 100644 --- a/src/Makefile_Efl.am +++ b/src/Makefile_Efl.am @@ -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 diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index abf22bd..d3ad0f7 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -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 \ diff --git a/src/lib/ector/Ector.h b/src/lib/ector/Ector.h index fe8d13c..0a53fac 100644 --- a/src/lib/ector/Ector.h +++ b/src/lib/ector/Ector.h @@ -174,6 +174,7 @@ EAPI int ector_shutdown(void); #include "ector_surface.h" #include "ector_renderer.h" +#include "ector_util.h" #endif diff --git a/src/lib/ector/cairo/ector_cairo_private.h b/src/lib/ector/cairo/ector_cairo_private.h index eef2d104..07446a8 100644 --- a/src/lib/ector/cairo/ector_cairo_private.h +++ b/src/lib/ector/cairo/ector_cairo_private.h @@ -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 * diff --git a/src/lib/ector/cairo/ector_cairo_surface.c b/src/lib/ector/cairo/ector_cairo_surface.c index c2d42a9..8875c04 100644 --- a/src/lib/ector/cairo/ector_cairo_surface.c +++ b/src/lib/ector/cairo/ector_cairo_surface.c @@ -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" diff --git a/src/lib/ector/cairo/ector_cairo_surface.eo b/src/lib/ector/cairo/ector_cairo_surface.eo index 10f6d9f..298c681 100644 --- a/src/lib/ector/cairo/ector_cairo_surface.eo +++ b/src/lib/ector/cairo/ector_cairo_surface.eo @@ -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 index 0000000..190fb8a --- /dev/null +++ b/src/lib/ector/cairo/ector_renderer_cairo_base.c @@ -0,0 +1,208 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include + +#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" diff --git a/src/lib/ector/cairo/ector_renderer_cairo_base.eo b/src/lib/ector/cairo/ector_renderer_cairo_base.eo index 7075710..c34b9a8 100644 --- a/src/lib/ector/cairo/ector_renderer_cairo_base.eo +++ b/src/lib/ector/cairo/ector_renderer_cairo_base.eo @@ -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; + } } diff --git a/src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.c b/src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.c index d0a39f8..19f3055 100644 --- a/src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.c +++ b/src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.c @@ -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, ); diff --git a/src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.eo b/src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.eo index 6007fd3..3d4ed9a 100644 --- a/src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.eo +++ b/src/lib/ector/cairo/ector_renderer_cairo_gradient_linear.eo @@ -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; } } diff --git a/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.c b/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.c index 84207ef..521b06d 100644 --- a/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.c +++ b/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.c @@ -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)); } diff --git a/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.eo b/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.eo index ab9595f..fb79bec 100644 --- a/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.eo +++ b/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.eo @@ -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; } } diff --git a/src/lib/ector/cairo/ector_renderer_cairo_shape.c b/src/lib/ector/cairo/ector_renderer_cairo_shape.c index dcdedea..babf113 100644 --- a/src/lib/ector/cairo/ector_renderer_cairo_shape.c +++ b/src/lib/ector/cairo/ector_renderer_cairo_shape.c @@ -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); } diff --git a/src/lib/ector/cairo/ector_renderer_cairo_shape.eo b/src/lib/ector/cairo/ector_renderer_cairo_shape.eo index 55bd049..7dd1b31 100644 --- a/src/lib/ector/cairo/ector_renderer_cairo_shape.eo +++ b/src/lib/ector/cairo/ector_renderer_cairo_shape.eo @@ -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; } diff --git a/src/lib/ector/ector_generic_surface.eo b/src/lib/ector/ector_generic_surface.eo index b8a60b5..42a5f3e 100644 --- a/src/lib/ector/ector_generic_surface.eo +++ b/src/lib/ector/ector_generic_surface.eo @@ -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; } } diff --git a/src/lib/ector/ector_main.c b/src/lib/ector/ector_main.c index 5f09214..fa7413e 100644 --- a/src/lib/ector/ector_main.c +++ b/src/lib/ector/ector_main.c @@ -22,7 +22,7 @@ #include #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; diff --git a/src/lib/ector/ector_private.h b/src/lib/ector/ector_private.h index 896c849..49f772b 100644 --- a/src/lib/ector/ector_private.h +++ b/src/lib/ector/ector_private.h @@ -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; diff --git a/src/lib/ector/ector_renderer_base.c b/src/lib/ector/ector_renderer_base.c index 70b636b..4f45542 100644 --- a/src/lib/ector/ector_renderer_base.c +++ b/src/lib/ector/ector_renderer_base.c @@ -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" diff --git a/src/lib/ector/ector_renderer_generic_base.eo b/src/lib/ector/ector_renderer_generic_base.eo index 91275d5..50e7e94 100644 --- a/src/lib/ector/ector_renderer_generic_base.eo +++ b/src/lib/ector/ector_renderer_generic_base.eo @@ -96,8 +96,6 @@ abstract Ector.Renderer.Generic.Base (Eo.Base) params { @in Ector_Rop op; @in array *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; } } diff --git a/src/lib/ector/ector_renderer_generic_gradient.eo b/src/lib/ector/ector_renderer_generic_gradient.eo index 4a34141..2c0cc83 100644 --- a/src/lib/ector/ector_renderer_generic_gradient.eo +++ b/src/lib/ector/ector_renderer_generic_gradient.eo @@ -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; } } diff --git a/src/lib/ector/ector_renderer_generic_gradient_linear.eo b/src/lib/ector/ector_renderer_generic_gradient_linear.eo index 89ab3e1..13ab2e6 100644 --- a/src/lib/ector/ector_renderer_generic_gradient_linear.eo +++ b/src/lib/ector/ector_renderer_generic_gradient_linear.eo @@ -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; } } diff --git a/src/lib/ector/ector_renderer_generic_gradient_radial.eo b/src/lib/ector/ector_renderer_generic_gradient_radial.eo index 563c954..cef25eb 100644 --- a/src/lib/ector/ector_renderer_generic_gradient_radial.eo +++ b/src/lib/ector/ector_renderer_generic_gradient_radial.eo @@ -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; } } diff --git a/src/lib/ector/ector_renderer_generic_shape.eo b/src/lib/ector/ector_renderer_generic_shape.eo index edbec7b4..2205b79 100644 --- a/src/lib/ector/ector_renderer_generic_shape.eo +++ b/src/lib/ector/ector_renderer_generic_shape.eo @@ -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 diff --git a/src/lib/ector/ector_renderer_gradient.c b/src/lib/ector/ector_renderer_gradient.c index 792f839..6cf676f 100644 --- a/src/lib/ector/ector_renderer_gradient.c +++ b/src/lib/ector/ector_renderer_gradient.c @@ -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; } diff --git a/src/lib/ector/ector_renderer_shape.c b/src/lib/ector/ector_renderer_shape.c index feab722..cda749d 100644 --- a/src/lib/ector/ector_renderer_shape.c +++ b/src/lib/ector/ector_renderer_shape.c @@ -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" diff --git a/src/lib/ector/ector_surface.c b/src/lib/ector/ector_surface.c index 949a4ef..eda912f 100644 --- a/src/lib/ector/ector_surface.c +++ b/src/lib/ector/ector_surface.c @@ -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 index 0000000..af8b591 --- /dev/null +++ b/src/lib/ector/ector_util.h @@ -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 index ba48a03..0000000 --- a/src/lib/ector/software/ector_blend_private.h +++ /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 index 0000000..8612199 --- /dev/null +++ b/src/lib/ector/software/ector_drawhelper.c @@ -0,0 +1,176 @@ + +#include +#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 index 0000000..4a7d59a --- /dev/null +++ b/src/lib/ector/software/ector_drawhelper_private.h @@ -0,0 +1,101 @@ +#ifndef ECTOR_DRAWHELPER_PRIVATE_H +#define ECTOR_DRAWHELPER_PRIVATE_H + +#ifdef HAVE_CONFIG_H +# include +#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 index 0000000..1199cdb --- /dev/null +++ b/src/lib/ector/software/ector_drawhelper_sse2.c @@ -0,0 +1,359 @@ + +#include +#include "ector_drawhelper_private.h" + +#ifdef BUILD_SSE3 +#include + +// 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 +} + diff --git a/src/lib/ector/software/ector_renderer_software_base.eo b/src/lib/ector/software/ector_renderer_software_base.eo index 9d9826f..6055be5 100644 --- a/src/lib/ector/software/ector_renderer_software_base.eo +++ b/src/lib/ector/software/ector_renderer_software_base.eo @@ -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; + } } diff --git a/src/lib/ector/software/ector_renderer_software_gradient_linear.c b/src/lib/ector/software/ector_renderer_software_gradient_linear.c index 621d7ff..a6e32b0 100644 --- a/src/lib/ector/software/ector_renderer_software_gradient_linear.c +++ b/src/lib/ector/software/ector_renderer_software_gradient_linear.c @@ -13,28 +13,30 @@ 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" diff --git a/src/lib/ector/software/ector_renderer_software_gradient_linear.eo b/src/lib/ector/software/ector_renderer_software_gradient_linear.eo index 77455c0..32f83df 100644 --- a/src/lib/ector/software/ector_renderer_software_gradient_linear.eo +++ b/src/lib/ector/software/ector_renderer_software_gradient_linear.eo @@ -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; } } diff --git a/src/lib/ector/software/ector_renderer_software_gradient_radial.c b/src/lib/ector/software/ector_renderer_software_gradient_radial.c index d8d1792..a05b487 100644 --- a/src/lib/ector/software/ector_renderer_software_gradient_radial.c +++ b/src/lib/ector/software/ector_renderer_software_gradient_radial.c @@ -12,36 +12,36 @@ 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" diff --git a/src/lib/ector/software/ector_renderer_software_gradient_radial.eo b/src/lib/ector/software/ector_renderer_software_gradient_radial.eo index 36d61ad..85625f3 100644 --- a/src/lib/ector/software/ector_renderer_software_gradient_radial.eo +++ b/src/lib/ector/software/ector_renderer_software_gradient_radial.eo @@ -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; } } diff --git a/src/lib/ector/software/ector_renderer_software_shape.c b/src/lib/ector/software/ector_renderer_software_shape.c index 49823a1..2e4fbea 100644 --- a/src/lib/ector/software/ector_renderer_software_shape.c +++ b/src/lib/ector/software/ector_renderer_software_shape.c @@ -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); diff --git a/src/lib/ector/software/ector_renderer_software_shape.eo b/src/lib/ector/software/ector_renderer_software_shape.eo index d5216ba..267ef7c 100644 --- a/src/lib/ector/software/ector_renderer_software_shape.eo +++ b/src/lib/ector/software/ector_renderer_software_shape.eo @@ -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; diff --git a/src/lib/ector/software/ector_software_gradient.c b/src/lib/ector/software/ector_software_gradient.c index bf2f8be..028fb9c 100644 --- a/src/lib/ector/software/ector_software_gradient.c +++ b/src/lib/ector/software/ector_software_gradient.c @@ -1,135 +1,369 @@ +#include +#include #include + #include "ector_private.h" #include "ector_software_private.h" -#include "ector_blend_private.h" +#include "ector_drawhelper_private.h" -//Remove -#include -#include #define GRADIENT_STOPTABLE_SIZE 1024 #define FIXPT_BITS 8 #define FIXPT_SIZE (1<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 + +#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 } diff --git a/src/lib/ector/software/ector_software_private.h b/src/lib/ector/software/ector_software_private.h index ef979a0..9e30a31 100644 --- a/src/lib/ector/software/ector_software_private.h +++ b/src/lib/ector/software/ector_software_private.h @@ -1,132 +1,122 @@ #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); diff --git a/src/lib/ector/software/ector_software_rasterizer.c b/src/lib/ector/software/ector_software_rasterizer.c index 67207d5..7807c5f 100644 --- a/src/lib/ector/software/ector_software_rasterizer.c +++ b/src/lib/ector/software/ector_software_rasterizer.c @@ -1,77 +1,73 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include #include + #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, ¤t_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, ¶ms); + sw_ft_grays_raster.raster_render(rasterizer->raster, ¶ms); - 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); +} diff --git a/src/lib/ector/software/ector_software_surface.c b/src/lib/ector/software/ector_software_surface.c index 80b5e1d..02d93c3 100644 --- a/src/lib/ector/software/ector_software_surface.c +++ b/src/lib/ector/software/ector_software_surface.c @@ -10,66 +10,71 @@ 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" diff --git a/src/lib/ector/software/ector_software_surface.eo b/src/lib/ector/software/ector_software_surface.eo index b324f78..3ed863c 100644 --- a/src/lib/ector/software/ector_software_surface.eo +++ b/src/lib/ector/software/ector_software_surface.eo @@ -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; } diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h index 55cb3c9..cbdb89f 100644 --- a/src/lib/efl/Efl.h +++ b/src/lib/efl/Efl.h @@ -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" diff --git a/src/lib/efl/interfaces/efl_gfx_base.eo b/src/lib/efl/interfaces/efl_gfx_base.eo index e5b719c..df9369c 100644 --- a/src/lib/efl/interfaces/efl_gfx_base.eo +++ b/src/lib/efl/interfaces/efl_gfx_base.eo @@ -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, which range from 0 to 255. 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 index 0000000..1ce4dd8 --- /dev/null +++ b/src/lib/efl/interfaces/efl_gfx_fill.eo @@ -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 index 0000000..b50d7bc --- /dev/null +++ b/src/lib/efl/interfaces/efl_gfx_gradient_base.eo @@ -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 */ + } + } + } +} diff --git a/src/lib/efl/interfaces/efl_gfx_gradient_linear.eo b/src/lib/efl/interfaces/efl_gfx_gradient_linear.eo index 88c1d80..0d9299f 100644 --- a/src/lib/efl/interfaces/efl_gfx_gradient_linear.eo +++ b/src/lib/efl/interfaces/efl_gfx_gradient_linear.eo @@ -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 { diff --git a/src/lib/efl/interfaces/efl_gfx_gradient_radial.eo b/src/lib/efl/interfaces/efl_gfx_gradient_radial.eo index 5a84c78..b9eeb72 100644 --- a/src/lib/efl/interfaces/efl_gfx_gradient_radial.eo +++ b/src/lib/efl/interfaces/efl_gfx_gradient_radial.eo @@ -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 index 0000000..ef0c2a7 --- /dev/null +++ b/src/lib/efl/interfaces/efl_gfx_shape.c @@ -0,0 +1,1333 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include + +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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_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, + ¤t_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, + ¤t_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, + ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_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, + ¤t_x, ¤t_y, + _efl_gfx_shape_append_arc_to, + EINA_TRUE)) + return ; + break; + default: + return ; + } + } +} + +#include "interfaces/efl_gfx_shape.eo.c" diff --git a/src/lib/efl/interfaces/efl_gfx_shape.eo b/src/lib/efl/interfaces/efl_gfx_shape.eo index d04d9c5..8547dc5 100644 --- a/src/lib/efl/interfaces/efl_gfx_shape.eo +++ b/src/lib/efl/interfaces/efl_gfx_shape.eo @@ -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 index 0000000..a104d0d --- /dev/null +++ b/src/lib/efl/interfaces/efl_gfx_stack.eo @@ -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 objects belonging to + the same layer 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 objects belonging to + the same layer 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 index 0000000..9d609d5 --- /dev/null +++ b/src/lib/efl/interfaces/efl_gfx_view.eo @@ -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. */ + } + } + } +} diff --git a/src/lib/efl/interfaces/efl_interfaces_main.c b/src/lib/efl/interfaces/efl_interfaces_main.c index 3aecd65..6ae1cb3 100644 --- a/src/lib/efl/interfaces/efl_interfaces_main.c +++ b/src/lib/efl/interfaces/efl_interfaces_main.c @@ -12,7 +12,16 @@ #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"); diff --git a/src/lib/evas/Evas_Common.h b/src/lib/evas/Evas_Common.h index 35a155b..8275130 100644 --- a/src/lib/evas/Evas_Common.h +++ b/src/lib/evas/Evas_Common.h @@ -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 { diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h index 9f877d4..380585f 100644 --- a/src/lib/evas/Evas_Eo.h +++ b/src/lib/evas/Evas_Eo.h @@ -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" diff --git a/src/lib/evas/Evas_Legacy.h b/src/lib/evas/Evas_Legacy.h index 87e78d0..19bc9d3 100644 --- a/src/lib/evas/Evas_Legacy.h +++ b/src/lib/evas/Evas_Legacy.h @@ -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 index 0000000..2b8d9e7 --- /dev/null +++ b/src/lib/evas/canvas/efl_vg_base.eo @@ -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 index 0000000..4d8a085 --- /dev/null +++ b/src/lib/evas/canvas/efl_vg_container.eo @@ -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 index 0000000..de78039 --- /dev/null +++ b/src/lib/evas/canvas/efl_vg_gradient.eo @@ -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 index 0000000..bc9c664 --- /dev/null +++ b/src/lib/evas/canvas/efl_vg_gradient_linear.eo @@ -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 index 0000000..0d60589 --- /dev/null +++ b/src/lib/evas/canvas/efl_vg_gradient_radial.eo @@ -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 index 0000000..62d7451 --- /dev/null +++ b/src/lib/evas/canvas/efl_vg_image.eo @@ -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 index 0000000..685bf7e --- /dev/null +++ b/src/lib/evas/canvas/efl_vg_root_node.eo @@ -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 index 0000000..ab6468c --- /dev/null +++ b/src/lib/evas/canvas/efl_vg_shape.eo @@ -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; + } +} diff --git a/src/lib/evas/canvas/evas_object_vg.c b/src/lib/evas/canvas/evas_object_vg.c index daaebf8..afbe045 100644 --- a/src/lib/evas/canvas/evas_object_vg.c +++ b/src/lib/evas/canvas/evas_object_vg.c @@ -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; diff --git a/src/lib/evas/canvas/evas_vg.eo b/src/lib/evas/canvas/evas_vg.eo index da307a2..8247f46 100644 --- a/src/lib/evas/canvas/evas_vg.eo +++ b/src/lib/evas/canvas/evas_vg.eo @@ -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; } } diff --git a/src/lib/evas/canvas/evas_vg_container.c b/src/lib/evas/canvas/evas_vg_container.c index 10f630e..fdf8124 100644 --- a/src/lib/evas/canvas/evas_vg_container.c +++ b/src/lib/evas/canvas/evas_vg_container.c @@ -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" diff --git a/src/lib/evas/canvas/evas_vg_gradient.c b/src/lib/evas/canvas/evas_vg_gradient.c index e448005..321e9bf 100644 --- a/src/lib/evas/canvas/evas_vg_gradient.c +++ b/src/lib/evas/canvas/evas_vg_gradient.c @@ -5,13 +5,11 @@ #include -#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" diff --git a/src/lib/evas/canvas/evas_vg_gradient_linear.c b/src/lib/evas/canvas/evas_vg_gradient_linear.c index 2dea1a5..814bd47 100644 --- a/src/lib/evas/canvas/evas_vg_gradient_linear.c +++ b/src/lib/evas/canvas/evas_vg_gradient_linear.c @@ -5,10 +5,10 @@ #include -#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" diff --git a/src/lib/evas/canvas/evas_vg_gradient_radial.c b/src/lib/evas/canvas/evas_vg_gradient_radial.c index b2ef343..a61f990 100644 --- a/src/lib/evas/canvas/evas_vg_gradient_radial.c +++ b/src/lib/evas/canvas/evas_vg_gradient_radial.c @@ -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" diff --git a/src/lib/evas/canvas/evas_vg_image.c b/src/lib/evas/canvas/evas_vg_image.c index f9dceb7..1bb0b1b 100644 --- a/src/lib/evas/canvas/evas_vg_image.c +++ b/src/lib/evas/canvas/evas_vg_image.c @@ -3,8 +3,10 @@ #include -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" diff --git a/src/lib/evas/canvas/evas_vg_loader_svg.c b/src/lib/evas/canvas/evas_vg_loader_svg.c index 3eb62fa..bf726d5 100644 --- a/src/lib/evas/canvas/evas_vg_loader_svg.c +++ b/src/lib/evas/canvas/evas_vg_loader_svg.c @@ -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; diff --git a/src/lib/evas/canvas/evas_vg_node.c b/src/lib/evas/canvas/evas_vg_node.c index 6b16256..ee95037 100644 --- a/src/lib/evas/canvas/evas_vg_node.c +++ b/src/lib/evas/canvas/evas_vg_node.c @@ -6,17 +6,26 @@ #include #include -#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" diff --git a/src/lib/evas/canvas/evas_vg_private.h b/src/lib/evas/canvas/evas_vg_private.h index 26e22f5..8f5bf4f 100644 --- a/src/lib/evas/canvas/evas_vg_private.h +++ b/src/lib/evas/canvas/evas_vg_private.h @@ -3,18 +3,17 @@ #include -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 diff --git a/src/lib/evas/canvas/evas_vg_root_node.c b/src/lib/evas/canvas/evas_vg_root_node.c index b47091d..8362dfd 100644 --- a/src/lib/evas/canvas/evas_vg_root_node.c +++ b/src/lib/evas/canvas/evas_vg_root_node.c @@ -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 -#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" diff --git a/src/lib/evas/canvas/evas_vg_shape.c b/src/lib/evas/canvas/evas_vg_shape.c index bda7383..71a987f 100644 --- a/src/lib/evas/canvas/evas_vg_shape.c +++ b/src/lib/evas/canvas/evas_vg_shape.c @@ -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" diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index e6da210..7bef005 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -7,6 +7,7 @@ #include #include +#include #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 index 0000000..d5070ab --- /dev/null +++ b/src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo @@ -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; + } + } + } +} diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index bec0208..103ec41 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -17,14 +17,15 @@ #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); diff --git a/src/modules/evas/engines/software_generic/ector_cairo_software_surface.eo b/src/modules/evas/engines/software_generic/ector_cairo_software_surface.eo index 9ae9782..9387f31 100644 --- a/src/modules/evas/engines/software_generic/ector_cairo_software_surface.eo +++ b/src/modules/evas/engines/software_generic/ector_cairo_software_surface.eo @@ -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; diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 9028999..6af3e5e 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -20,10 +20,10 @@ #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) { } -- 2.7.4