jose has some new gradient work - these are his patches. nice work joseg! yes
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 26 Aug 2008 05:45:04 +0000 (05:45 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 26 Aug 2008 05:45:04 +0000 (05:45 +0000)
- some enignes break as they dont have the stubbed out functions, and
xrender/gl engines dont even implement the drawing and need to (but are
stubbed out).

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@35677 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

24 files changed:
src/lib/Evas.h
src/lib/canvas/Makefile.am
src/lib/canvas/evas_object_gradient2.c [new file with mode: 0644]
src/lib/canvas/evas_object_gradient2_linear.c [new file with mode: 0644]
src/lib/canvas/evas_object_gradient2_radial.c [new file with mode: 0644]
src/lib/canvas/evas_object_image.c
src/lib/canvas/evas_object_line.c
src/lib/canvas/evas_object_polygon.c
src/lib/canvas/evas_object_rectangle.c
src/lib/canvas/evas_object_smart.c
src/lib/canvas/evas_object_text.c
src/lib/canvas/evas_object_textblock.c
src/lib/engines/common/Makefile.am
src/lib/engines/common/evas_gradient.h
src/lib/engines/common/evas_gradient2_linear.c [new file with mode: 0644]
src/lib/engines/common/evas_gradient2_main.c [new file with mode: 0644]
src/lib/engines/common/evas_gradient2_radial.c [new file with mode: 0644]
src/lib/engines/common/evas_pipe.c
src/lib/engines/common/evas_pipe.h
src/lib/include/evas_common.h
src/lib/include/evas_private.h
src/modules/engines/gl_x11/evas_engine.c
src/modules/engines/software_generic/evas_engine.c
src/modules/engines/xrender_x11/evas_engine.c

index 910f392..9ce19df 100644 (file)
@@ -86,6 +86,7 @@ typedef enum _Evas_Colorspace
    EVAS_COLORSPACE_RGB565_A5P /**< 16bit rgb565 + Alpha plane at end - 5 bits of the 8 being used per alpha byte */
 } Evas_Colorspace; /**< Colorspaces for pixel data supported by Evas */
 
+typedef struct _Evas_Transform Evas_Transform; /**< An Evas projective or affine transform */
 typedef struct _Evas_Rectangle        Evas_Rectangle; /**< A generic rectangle handle */
 typedef struct _Evas_Coord_Rectangle  Evas_Coord_Rectangle; /**< A generic rectangle handle */
 typedef struct _Evas_Smart_Class      Evas_Smart_Class; /**< A smart object base class */
@@ -103,6 +104,13 @@ typedef int           Evas_Coord;
 typedef int           Evas_Font_Size;
 typedef int           Evas_Angle;
 
+struct _Evas_Transform /** An affine or projective coordinate transformation matrix */
+{
+   float mxx, mxy, mxz;
+   float myx, myy, myz;
+   float mzx, mzy, mzz;
+};
+
 struct _Evas_Rectangle /** A rectangle */
 {
    int x; /**< top-left x co-ordinate of rectangle */
@@ -460,6 +468,23 @@ extern "C" {
    EAPI void              evas_object_gradient_offset_set    (Evas_Object *obj, float offset);
    EAPI float             evas_object_gradient_offset_get    (const Evas_Object *obj);
 
+/* new gradient2 objects - generic properties */
+   EAPI void              evas_object_gradient2_color_np_stop_insert (Evas_Object *obj, int r, int g, int b, int a, float pos);
+   EAPI void              evas_object_gradient2_fill_spread_set   (Evas_Object *obj, int tile_mode);
+   EAPI int               evas_object_gradient2_fill_spread_get   (const Evas_Object *obj);
+   EAPI void              evas_object_gradient2_fill_transform_set (Evas_Object *obj, Evas_Transform *t);
+   EAPI void              evas_object_gradient2_fill_transform_get (const Evas_Object *obj, Evas_Transform *t);
+
+/* linear gradient2 objects */
+   EAPI Evas_Object      *evas_object_gradient2_linear_add            (Evas *e);
+   EAPI void              evas_object_gradient2_linear_fill_set (Evas_Object *obj, float x0, float y0, float x1, float y1);
+   EAPI void              evas_object_gradient2_linear_fill_get (const Evas_Object *obj, float *x0, float *y0, float *x1, float *y1);
+
+/* radial gradient2 objects */
+   EAPI Evas_Object      *evas_object_gradient2_radial_add            (Evas *e);
+   EAPI void              evas_object_gradient2_radial_fill_set (Evas_Object *obj, float cx, float cy, float rx, float ry);
+   EAPI void              evas_object_gradient2_radial_fill_get (const Evas_Object *obj, float *cx, float *cy, float *rx, float *ry);
+
 /* polygon objects */
    EAPI Evas_Object      *evas_object_polygon_add           (Evas *e);
    EAPI void              evas_object_polygon_point_add     (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
index db66ba6..c11f1fc 100644 (file)
@@ -23,6 +23,7 @@ evas_layer.c \
 evas_main.c \
 evas_name.c \
 evas_object_gradient.c \
+evas_object_gradient2.c \
 evas_object_image.c \
 evas_object_main.c \
 evas_object_inform.c \
@@ -40,4 +41,8 @@ evas_smart.c \
 evas_stack.c \
 evas_async_events.c
 
+EXTRA_DIST = \
+evas_object_gradient2_linear.c \
+evas_object_gradient2_radial.c
+
 libevas_canvas_la_DEPENDENCIES = $(top_builddir)/config.h
diff --git a/src/lib/canvas/evas_object_gradient2.c b/src/lib/canvas/evas_object_gradient2.c
new file mode 100644 (file)
index 0000000..366cbba
--- /dev/null
@@ -0,0 +1,214 @@
+#include "evas_common.h"
+#include "evas_private.h"
+
+typedef struct _Evas_Object_Gradient2      Evas_Object_Gradient2;
+
+struct _Evas_Object_Gradient2
+{
+   DATA32            magic;
+
+   struct {
+      struct {
+         Evas_Common_Transform  transform;
+         int         spread;
+      } fill;
+      unsigned char    gradient_opaque : 1;
+   } cur, prev;
+
+   unsigned char     gradient_changed : 1;
+};
+
+
+/**
+ * Inserts a color stop to the given evas gradient object.
+ *
+ * The @p pos parameter determines where along the unit interval
+ * [0,1] the color is to be inserted. The r,g,b,a data are assumed
+ * input as being NON-PREMULTIPLIED.
+ *
+ * @param   obj      The given evas gradient object.
+ * @param   r        Red component of the given color.
+ * @param   g        Green component of the given color.
+ * @param   b        Blue component of the given color.
+ * @param   a        Alpha component of the given color.
+ * @param   pos      The pos in [0,1] of this stop.
+ * @ingroup Evas_Object_Gradient_Group
+ */
+EAPI void
+evas_object_gradient2_color_np_stop_insert(Evas_Object *obj, int r, int g, int b, int a, float pos)
+{
+   Evas_Object_Gradient2 *og;
+   void *engine_data;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   og = (Evas_Object_Gradient2 *)(obj->object_data);
+   MAGIC_CHECK(og, Evas_Object_Gradient2, MAGIC_OBJ_GRADIENT);
+   return;
+   MAGIC_CHECK_END();
+   engine_data = obj->func->engine_data_get(obj);
+   if (engine_data)
+      obj->layer->evas->engine.func->gradient2_color_np_stop_insert(obj->layer->evas->engine.data.output,
+                                                            engine_data,
+                                                            r, g, b, a, pos);
+   og->gradient_changed = 1;
+   evas_object_change(obj);
+}
+
+/**
+ * Deletes all stops set for the given evas gradient object or any set data.
+ * @param   obj The given evas gradient object.
+ * @ingroup Evas_Object_Gradient_Group
+ */
+EAPI void
+evas_object_gradient2_clear(Evas_Object *obj)
+{
+   Evas_Object_Gradient2 *og;
+   void *engine_data;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   og = (Evas_Object_Gradient2 *)(obj->object_data);
+   MAGIC_CHECK(og, Evas_Object_Gradient2, MAGIC_OBJ_GRADIENT);
+   return;
+   MAGIC_CHECK_END();
+   engine_data = obj->func->engine_data_get(obj);
+   if (engine_data)
+      obj->layer->evas->engine.func->gradient2_clear(obj->layer->evas->engine.data.output,
+                                                    engine_data);
+   og->gradient_changed = 1;
+   og->cur.gradient_opaque = 0;
+   evas_object_change(obj);
+}
+
+
+/**
+ * Sets the tiling mode for the given evas gradient object's fill.
+ * @param   obj   The given evas gradient object.
+ * @param   spread One of EVAS_TEXTURE_REFLECT, EVAS_TEXTURE_REPEAT,
+ * EVAS_TEXTURE_RESTRICT, or EVAS_TEXTURE_PAD.
+ * @ingroup Evas_Object_Gradient_Group
+ */
+EAPI void
+evas_object_gradient2_fill_spread_set(Evas_Object *obj, int spread)
+{
+   Evas_Object_Gradient2 *og;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   og = (Evas_Object_Gradient2 *)(obj->object_data);
+   MAGIC_CHECK(og, Evas_Object_Gradient2, MAGIC_OBJ_GRADIENT);
+   return;
+   MAGIC_CHECK_END();
+   if (spread == og->cur.fill.spread) return;
+   og->cur.fill.spread = spread;
+   og->gradient_changed = 1;
+   evas_object_change(obj);
+}
+
+/**
+ * Retrieves the spread (tiling mode) for the given gradient object's fill.
+ * @param   obj The given evas gradient object.
+ * @return  The current spread mode of the gradient object.
+ * @ingroup Evas_Object_Gradient_Group
+ */
+EAPI int
+evas_object_gradient2_fill_spread_get(const Evas_Object *obj)
+{
+   Evas_Object_Gradient2 *og;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return EVAS_TEXTURE_REPEAT;
+   MAGIC_CHECK_END();
+   og = (Evas_Object_Gradient2 *)(obj->object_data);
+   MAGIC_CHECK(og, Evas_Object_Gradient2, MAGIC_OBJ_GRADIENT);
+   return EVAS_TEXTURE_REPEAT;
+   MAGIC_CHECK_END();
+   return og->cur.fill.spread;
+}
+
+EAPI void
+evas_object_gradient2_fill_transform_set (Evas_Object *obj, Evas_Transform *t)
+{
+   Evas_Object_Gradient2 *og;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   og = (Evas_Object_Gradient2 *)(obj->object_data);
+   MAGIC_CHECK(og, Evas_Object_Gradient2, MAGIC_OBJ_GRADIENT);
+   return;
+   MAGIC_CHECK_END();
+   if (!t)
+     {
+       og->cur.fill.transform.mxx = 1;
+       og->cur.fill.transform.mxy = 0;
+       og->cur.fill.transform.mxz = 0;
+       og->cur.fill.transform.myx = 0;
+       og->cur.fill.transform.myy = 1;
+       og->cur.fill.transform.myz = 0;
+       og->cur.fill.transform.mzx = 0;
+       og->cur.fill.transform.mzy = 0;
+       og->cur.fill.transform.mzz = 1;
+
+       og->gradient_changed;
+       evas_object_change(obj);
+       return;
+     }
+   if ( (og->cur.fill.transform.mxx == t->mxx) ||
+        (og->cur.fill.transform.mxy == t->mxy) ||
+        (og->cur.fill.transform.mxy == t->mxy) ||
+        (og->cur.fill.transform.mxy == t->mxy) ||
+        (og->cur.fill.transform.mxy == t->mxy) ||
+        (og->cur.fill.transform.mxy == t->mxy) ||
+        (og->cur.fill.transform.mxy == t->mxy) ||
+        (og->cur.fill.transform.mxy == t->mxy) ||
+        (og->cur.fill.transform.mxy == t->mxy) )
+           return;
+
+   og->cur.fill.transform.mxx = t->mxx;
+   og->cur.fill.transform.mxy = t->mxy;
+   og->cur.fill.transform.mxz = t->mxz;
+   og->cur.fill.transform.myx = t->myx;
+   og->cur.fill.transform.myy = t->myy;
+   og->cur.fill.transform.myz = t->myz;
+   og->cur.fill.transform.mzx = t->mzx;
+   og->cur.fill.transform.mzy = t->mzy;
+   og->cur.fill.transform.mzz = t->mzz;
+
+   og->gradient_changed;
+   evas_object_change(obj);
+}
+
+EAPI void
+evas_object_gradient2_fill_transform_get (const Evas_Object *obj, Evas_Transform *t)
+{
+   Evas_Object_Gradient2 *og;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   og = (Evas_Object_Gradient2 *)(obj->object_data);
+   MAGIC_CHECK(og, Evas_Object_Gradient2, MAGIC_OBJ_GRADIENT);
+   return;
+   MAGIC_CHECK_END();
+   if (t)
+     {
+        t->mxx = og->cur.fill.transform.mxx;
+        t->mxy = og->cur.fill.transform.mxy;
+        t->mxz = og->cur.fill.transform.mxz;
+        t->myx = og->cur.fill.transform.myx;
+        t->myy = og->cur.fill.transform.myy;
+        t->myz = og->cur.fill.transform.myz;
+        t->mzx = og->cur.fill.transform.mzx;
+        t->mzy = og->cur.fill.transform.mzy;
+        t->mzz = og->cur.fill.transform.mzz;
+     }
+}
+
+
+#include "evas_object_gradient2_linear.c"
+#include "evas_object_gradient2_radial.c"
diff --git a/src/lib/canvas/evas_object_gradient2_linear.c b/src/lib/canvas/evas_object_gradient2_linear.c
new file mode 100644 (file)
index 0000000..fd7ffff
--- /dev/null
@@ -0,0 +1,466 @@
+#include "evas_common.h"
+#include "evas_private.h"
+
+/* private magic number for linear gradient objects */
+static const char lg_type[] = "linear_gradient";
+
+/* private struct for gradient object internal data */
+typedef struct _Evas_Object_Gradient2_Linear      Evas_Object_Gradient2_Linear;
+
+struct _Evas_Object_Gradient2_Linear
+{
+   Evas_Object_Gradient2 base;
+
+   DATA32            magic;
+
+   struct {
+      struct {
+          float  x0, y0, x1, y1;
+      } fill;
+   } cur, prev;
+
+   void             *engine_data;
+
+   unsigned char     gradient_changed : 1;
+   unsigned char     changed : 1;
+};
+
+/* private methods for linear gradient objects */
+static void evas_object_gradient2_linear_init(Evas_Object *obj);
+static void *evas_object_gradient2_linear_new(void);
+
+static void evas_object_gradient2_linear_free(Evas_Object *obj);
+static void evas_object_gradient2_linear_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
+static void evas_object_gradient2_linear_render_pre(Evas_Object *obj);
+static void evas_object_gradient2_linear_render_post(Evas_Object *obj);
+
+static int evas_object_gradient2_linear_visual_type_get(Evas_Object *obj);
+static void *evas_object_gradient2_linear_engine_data_get(Evas_Object *obj);
+
+static int evas_object_gradient2_linear_is_opaque(Evas_Object *obj);
+static int evas_object_gradient2_linear_was_opaque(Evas_Object *obj);
+
+static const Evas_Object_Func object_func =
+{
+   /* methods (compulsory) */
+   evas_object_gradient2_linear_free,
+     evas_object_gradient2_linear_render,
+     evas_object_gradient2_linear_render_pre,
+     evas_object_gradient2_linear_render_post,
+     evas_object_gradient2_linear_visual_type_get,
+     evas_object_gradient2_linear_engine_data_get,
+   /* these are optional. NULL = nothing */
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     evas_object_gradient2_linear_is_opaque,
+     evas_object_gradient2_linear_was_opaque,
+     NULL,
+     NULL,
+     NULL
+};
+
+/* the actual api call to add a gradient */
+
+/**
+ * @defgroup Evas_Object_Gradient_Linear_Group Evas linear_gradient Object Functions
+ *
+ * Functions that work on evas linear gradient objects.
+ *
+ * The following example shows how
+ */
+
+/**
+ * Adds a gradient object to the given evas.
+ * @param   e The given evas.
+ * @return  A new evas gradient object if successful.  Otherwise, @c NULL.
+ * @ingroup Evas_Object_Gradient_Group
+ */
+EAPI Evas_Object *
+evas_object_gradient2_linear_add(Evas *e)
+{
+   Evas_Object *obj;
+
+   MAGIC_CHECK(e, Evas, MAGIC_EVAS);
+   return NULL;
+   MAGIC_CHECK_END();
+   obj = evas_object_new();
+   evas_object_gradient2_linear_init(obj);
+   evas_object_inject(obj, e);
+   if (obj->object_data)
+     {
+       Evas_Object_Gradient2_Linear *o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+
+       o->engine_data = e->engine.func->gradient2_linear_new(e->engine.data.output);
+     }
+   return obj;
+}
+
+/**
+ * @defgroup Evas_Object_Gradient_Linear_Fill_Group Linear_Gradient Object Fill Functions
+ *
+ * Functions that deal with the fill geometry of the linear gradient object.
+ */
+
+/**
+ * Sets the start and end points of the linear gradient geometry for the object.
+ *
+ * Note that the gradient may extend beyond these,
+ * according to its spread value - restrict, repeat, or reflect.  To have
+ * only one 'cycle' of the gradient drawn, the spread value must be set
+ * to restrict.
+ * The default values for the fill parameters is @p x0 = 0, @p y0 = 0,
+ * @p x1 = 0 and @p y1 = 0.
+ *
+ * @param   obj The given evas linear gradient object.
+ * @param   x0   The X coordinate of the start point.
+ * @param   y0   The Y coordinate of the start point.
+ * @param   x1   The X coordinate of the end point.
+ * @param   y1   The Y coordinate of the end point
+ * @ingroup Evas_Object_Gradient_Linear_Fill_Group
+ */
+EAPI void
+evas_object_gradient2_linear_fill_set(Evas_Object *obj, float x0, float y0, float x1, float y1)
+{
+   Evas_Object_Gradient2_Linear *o;
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   MAGIC_CHECK(o, Evas_Object_Gradient2_Linear, MAGIC_OBJ_GRADIENT_LINEAR);
+   return;
+   MAGIC_CHECK_END();
+   if ((o->cur.fill.x0 == x0) &&
+       (o->cur.fill.y0 == y0) &&
+       (o->cur.fill.x1 == x1) &&
+       (o->cur.fill.y1 == y1)) return;
+   o->cur.fill.x0 = x0;
+   o->cur.fill.y0 = y0;
+   o->cur.fill.x1 = x1;
+   o->cur.fill.y1 = y1;
+   o->gradient_changed = 1;
+   o->changed = 1;
+   evas_object_change(obj);
+}
+
+EAPI void
+evas_object_gradient2_linear_fill_get(const Evas_Object *obj, float *x0, float *y0, float *x1, float *y1)
+{
+   Evas_Object_Gradient2_Linear *o;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   if (x0) *x0 = 0;
+   if (y0) *y0 = 0;
+   if (x1) *x1 = 0;
+   if (y1) *y1 = 0;
+   return;
+   MAGIC_CHECK_END();
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   MAGIC_CHECK(o, Evas_Object_Gradient2_Linear, MAGIC_OBJ_GRADIENT_LINEAR);
+   if (x0) *x0 = 0;
+   if (y0) *y0 = 0;
+   if (x1) *x1 = 0;
+   if (y1) *y1 = 0;
+   return;
+   MAGIC_CHECK_END();
+   if (x0) *x0 = o->cur.fill.x0;
+   if (y0) *y0 = o->cur.fill.y0;
+   if (x1) *x1 = o->cur.fill.x1;
+   if (y1) *y1 = o->cur.fill.y1;
+   return;
+}
+
+
+
+/* all nice and private */
+static void
+evas_object_gradient2_linear_init(Evas_Object *obj)
+{
+   /* alloc grad ob, setup methods and default values */
+   obj->object_data = evas_object_gradient2_linear_new();
+   /* set up default settings for this kind of object */
+   obj->cur.color.r = 255;
+   obj->cur.color.g = 255;
+   obj->cur.color.b = 255;
+   obj->cur.color.a = 255;
+   obj->cur.geometry.x = 0;
+   obj->cur.geometry.y = 0;
+   obj->cur.geometry.w = 0;
+   obj->cur.geometry.h = 0;
+   obj->cur.layer = 0;
+   obj->cur.anti_alias = 1;
+   obj->cur.interpolation_color_space = EVAS_COLOR_SPACE_ARGB;
+   obj->cur.render_op = EVAS_RENDER_BLEND;
+   /* set up object-specific settings */
+   obj->prev = obj->cur;
+   /* set up methods (compulsory) */
+   obj->func = &object_func;
+   obj->type = lg_type;
+   obj->changed = 1;
+}
+
+static void *
+evas_object_gradient2_linear_new(void)
+{
+   Evas_Object_Gradient2_Linear *o;
+   Evas_Object_Gradient2 *og;
+
+   /* alloc obj private data */
+   o = calloc(1, sizeof(Evas_Object_Gradient2_Linear));
+   if (!o) return NULL;
+   o->magic = MAGIC_OBJ_GRADIENT_LINEAR;
+   o->cur.fill.x0 = 0;
+   o->cur.fill.y0 = 0;
+   o->cur.fill.x1 = 1;
+   o->cur.fill.y1 = 1;
+   og = (Evas_Object_Gradient2 *)o;
+   og->magic = MAGIC_OBJ_GRADIENT;
+   og->cur.fill.transform.mxx = og->cur.fill.transform.myy = og->cur.fill.transform.mzz = 1;
+   og->cur.fill.spread = EVAS_TEXTURE_REPEAT;
+   og->cur.gradient_opaque = 0;
+   og->prev = og->cur;
+   og->gradient_changed = 1;
+   o->prev = o->cur;
+   o->changed = 1;
+   o->gradient_changed = 1;
+   return o;
+}
+
+static void
+evas_object_gradient2_linear_free(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Linear *o;
+
+   /* frees private object data. very simple here */
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   MAGIC_CHECK(o, Evas_Object_Gradient2_Linear, MAGIC_OBJ_GRADIENT_LINEAR);
+   return;
+   MAGIC_CHECK_END();
+   /* free obj */
+   if (o->engine_data)
+      obj->layer->evas->engine.func->gradient2_linear_free(obj->layer->evas->engine.data.output,
+                                                         o->engine_data);
+   free(o);
+   obj->object_data = NULL; 
+}
+
+
+
+static void
+evas_object_gradient2_linear_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
+{
+   Evas_Object_Gradient2_Linear *o;
+
+   /* render object to surface with context, and offxet by x,y */
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   obj->layer->evas->engine.func->context_multiplier_unset(output, context);
+   obj->layer->evas->engine.func->context_anti_alias_set(output, context, obj->cur.anti_alias);
+   obj->layer->evas->engine.func->context_render_op_set(output, context, obj->cur.render_op);
+   if (o->engine_data)
+     {
+       obj->layer->evas->engine.func->gradient2_linear_draw(output, context, surface,
+                                                    o->engine_data,
+                                                    obj->cur.geometry.x + x,
+                                                    obj->cur.geometry.y + y,
+                                                    obj->cur.geometry.w,
+                                                    obj->cur.geometry.h);
+     }
+}
+
+static void
+evas_object_gradient2_linear_render_pre(Evas_Object *obj)
+{
+   Evas_Rectangles rects = { 0, 0, NULL };
+   Evas_Object_Gradient2_Linear *o;
+   Evas_Object_Gradient2 *og;
+   int is_v, was_v;
+
+   /* dont pre-render the obj twice! */
+   if (obj->pre_render_done) return;
+   obj->pre_render_done = 1;
+   /* pre-render phase. this does anything an object needs to do just before */
+   /* rendering. this could mean loading the image data, retrieving it from */
+   /* elsewhere, decoding video etc. */
+   /* then when this is done the object needs to figure if it changed and */
+   /* if so what and where and add the appropriate redraw rectangles */
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   og = (Evas_Object_Gradient2 *)(o);
+   /* if someone is clipping this obj - go calculate the clipper */
+   if (obj->cur.clipper)
+     {
+       if (obj->cur.cache.clip.dirty)
+         evas_object_clip_recalc(obj->cur.clipper);
+       obj->cur.clipper->func->render_pre(obj->cur.clipper);
+     }
+   /* if it changed color */
+   if ((obj->cur.color.r != obj->prev.color.r) ||
+       (obj->cur.color.g != obj->prev.color.g) ||
+       (obj->cur.color.b != obj->prev.color.b) ||
+       (obj->cur.color.a != obj->prev.color.a))
+     { o->gradient_changed = 1;  o->changed = 1; }
+   if ((!o->gradient_changed) && ((obj->cur.cache.clip.r != obj->prev.cache.clip.r) ||
+       (obj->cur.cache.clip.g != obj->prev.cache.clip.g) ||
+       (obj->cur.cache.clip.b != obj->prev.cache.clip.b) ||
+       (obj->cur.cache.clip.a != obj->prev.cache.clip.a)))
+     { o->gradient_changed = 1;  o->changed = 1; }
+   if (!o->gradient_changed && (obj->cur.interpolation_color_space != obj->prev.interpolation_color_space))
+     { o->gradient_changed = 1;  o->changed = 1; }
+   if (!o->changed && (obj->cur.render_op != obj->prev.render_op))
+       o->changed = 1;
+//   if (!o->changed && (obj->cur.anti_alias != obj->prev.anti_alias))
+//     o->changed = 1;
+   if (og->gradient_changed)
+     { o->gradient_changed = 1;  o->changed = 1; }
+   if (o->changed && o->engine_data)
+     {
+       obj->layer->evas->engine.func->context_render_op_set(obj->layer->evas->engine.data.output,
+                                                            obj->layer->evas->engine.data.context, obj->cur.render_op);
+       obj->layer->evas->engine.func->context_multiplier_set(obj->layer->evas->engine.data.output,
+                                                               obj->layer->evas->engine.data.context,
+                                                               obj->cur.cache.clip.r, obj->cur.cache.clip.g,
+                                                               obj->cur.cache.clip.b, obj->cur.cache.clip.a);
+       obj->layer->evas->engine.func->context_color_interpolation_set(obj->layer->evas->engine.data.output,
+                                                                       obj->layer->evas->engine.data.context,
+                                                                       obj->cur.interpolation_color_space);
+       if (o->gradient_changed)
+         {
+           obj->layer->evas->engine.func->gradient2_linear_fill_set(obj->layer->evas->engine.data.output, o->engine_data, o->cur.fill.x0, o->cur.fill.y0, o->cur.fill.x1, o->cur.fill.y1);
+           obj->layer->evas->engine.func->gradient2_fill_transform_set(obj->layer->evas->engine.data.output, o->engine_data,
+                                                               &og->cur.fill.transform);
+           obj->layer->evas->engine.func->gradient2_fill_spread_set(obj->layer->evas->engine.data.output, o->engine_data,
+                                                               og->cur.fill.spread);
+           obj->layer->evas->engine.func->gradient2_linear_render_pre(obj->layer->evas->engine.data.output,
+                                                               obj->layer->evas->engine.data.context,
+                                                               o->engine_data);
+         }
+       og->cur.gradient_opaque = obj->layer->evas->engine.func->gradient2_linear_is_opaque(obj->layer->evas->engine.data.output,
+                                                                                  obj->layer->evas->engine.data.context,
+                                                                                  o->engine_data,
+                                                                                  obj->cur.cache.clip.x, obj->cur.cache.clip.y,
+                                                                                  obj->cur.cache.clip.w, obj->cur.cache.clip.h);
+
+       if (obj->cur.cache.clip.a != 255)
+           og->cur.gradient_opaque = 0;
+    }
+
+   /* now figure what changed and add draw rects */
+   /* if it just became visible or invisible */
+   is_v = evas_object_is_visible(obj);
+   was_v = evas_object_was_visible(obj);
+   if (is_v != was_v)
+     {
+       evas_object_render_pre_visible_change(&rects, obj, is_v, was_v);
+       goto done;
+     }
+   /* its 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(&rects, obj);
+   /* gradient changed */
+   if (o->changed || obj->restack)
+     {
+       evas_object_render_pre_prev_cur_add(&rects, obj);
+       goto done;
+     }
+   /* if it changed geometry */
+   if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
+       (obj->cur.geometry.y != obj->prev.geometry.y) ||
+       (obj->cur.geometry.w != obj->prev.geometry.w) ||
+       (obj->cur.geometry.h != obj->prev.geometry.h))
+     {
+       evas_object_render_pre_prev_cur_add(&rects, obj);
+       goto done;
+     }
+   /* it obviously didn't change - add a NO obscure - this "unupdates"  this */
+   /* area so if there were updates for it they get wiped. don't do it if we */
+   /* arent fully opaque and we are visible */
+   
+   if (evas_object_is_visible(obj) &&
+       evas_object_is_opaque(obj))
+     obj->layer->evas->engine.func->output_redraws_rect_del(obj->layer->evas->engine.data.output,
+                                                           obj->cur.cache.clip.x,
+                                                           obj->cur.cache.clip.y,
+                                                           obj->cur.cache.clip.w,
+                                                           obj->cur.cache.clip.h);
+   
+   done:
+   evas_object_render_pre_effect_updates(&rects, obj, is_v, was_v);
+}
+
+static void
+evas_object_gradient2_linear_render_post(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Linear *o;
+   Evas_Object_Gradient2 *og;
+
+   /* this moves the current data to the previous state parts of the object */
+   /* in whatever way is safest for the object. also if we don't need object */
+   /* data anymore we can free it if the object deems this is a good idea */
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   og = (Evas_Object_Gradient2 *)(o);
+   /* remove those pesky changes */
+   while (obj->clip.changes)
+     {
+       Evas_Rectangle *r;
+
+       r = (Evas_Rectangle *)obj->clip.changes->data;
+       obj->clip.changes = evas_list_remove(obj->clip.changes, r);
+       free(r);
+     }
+   /* move cur to prev safely for object data */
+   obj->prev = obj->cur;
+   obj->changed = 0;
+   o->prev = o->cur;
+   o->changed = 0;
+   o->gradient_changed = 0;
+   og->prev = og->cur;
+   og->gradient_changed = 0;
+}
+
+static int evas_object_gradient2_linear_visual_type_get(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Linear *o;
+
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   if (!o) return 0;
+   return MAGIC_OBJ_GRADIENT;
+}
+
+static void *evas_object_gradient2_linear_engine_data_get(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Linear *o;
+
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   if (!o) return NULL;
+   return o->engine_data;
+}
+
+
+static int
+evas_object_gradient2_linear_is_opaque(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Linear *o;
+   Evas_Object_Gradient2 *og;
+
+   /* this returns 1 if the internal object data implies that the object is */
+   /* currently fully opaque over the entire region it occupies */
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   if (!o->engine_data) return 0;
+   og = (Evas_Object_Gradient2 *)(o);
+   return og->cur.gradient_opaque;
+ }
+
+static int
+evas_object_gradient2_linear_was_opaque(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Linear *o;
+   Evas_Object_Gradient2 *og;
+
+   /* this returns 1 if the internal object data implies that the object was */
+   /* currently fully opaque over the entire region it occupies */
+   o = (Evas_Object_Gradient2_Linear *)(obj->object_data);
+   if (!o->engine_data) return 0;
+   og = (Evas_Object_Gradient2 *)(o);
+   return og->prev.gradient_opaque;
+}
diff --git a/src/lib/canvas/evas_object_gradient2_radial.c b/src/lib/canvas/evas_object_gradient2_radial.c
new file mode 100644 (file)
index 0000000..324762e
--- /dev/null
@@ -0,0 +1,465 @@
+#include "evas_common.h"
+#include "evas_private.h"
+
+/* private magic number for radial gradient objects */
+static const char rg_type[] = "radial_gradient";
+
+/* private struct for gradient object internal data */
+typedef struct _Evas_Object_Gradient2_Radial      Evas_Object_Gradient2_Radial;
+
+struct _Evas_Object_Gradient2_Radial
+{
+   Evas_Object_Gradient2 base;
+
+   DATA32            magic;
+
+   struct {
+      struct {
+         float  cx, cy, rx, ry;
+      } fill;
+   } cur, prev;
+
+   void             *engine_data;
+
+   unsigned char     gradient_changed : 1;
+   unsigned char     changed : 1;
+};
+
+/* private methods for radial gradient objects */
+static void evas_object_gradient2_radial_init(Evas_Object *obj);
+static void *evas_object_gradient2_radial_new(void);
+
+static void evas_object_gradient2_radial_free(Evas_Object *obj);
+static void evas_object_gradient2_radial_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
+static void evas_object_gradient2_radial_render_pre(Evas_Object *obj);
+static void evas_object_gradient2_radial_render_post(Evas_Object *obj);
+
+static int evas_object_gradient2_radial_visual_type_get(Evas_Object *obj);
+static void *evas_object_gradient2_radial_engine_data_get(Evas_Object *obj);
+
+static int evas_object_gradient2_radial_is_opaque(Evas_Object *obj);
+static int evas_object_gradient2_radial_was_opaque(Evas_Object *obj);
+
+static const Evas_Object_Func rg_object_func =
+{
+   /* methods (compulsory) */
+   evas_object_gradient2_radial_free,
+     evas_object_gradient2_radial_render,
+     evas_object_gradient2_radial_render_pre,
+     evas_object_gradient2_radial_render_post,
+     evas_object_gradient2_radial_visual_type_get,
+     evas_object_gradient2_radial_engine_data_get,
+   /* these are optional. NULL = nothing */
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     evas_object_gradient2_radial_is_opaque,
+     evas_object_gradient2_radial_was_opaque,
+     NULL,
+     NULL,
+     NULL
+};
+
+/* the actual api call to add a gradient */
+
+/**
+ * @defgroup Evas_Object_Gradient_Radial_Group Evas radial_gradient Object Functions
+ *
+ * Functions that work on evas radial gradient objects.
+ *
+ * The following example shows how
+ */
+
+/**
+ * Adds a gradient object to the given evas.
+ * @param   e The given evas.
+ * @return  A new evas gradient object if successful.  Otherwise, @c NULL.
+ * @ingroup Evas_Object_Gradient_Group
+ */
+EAPI Evas_Object *
+evas_object_gradient2_radial_add(Evas *e)
+{
+   Evas_Object *obj;
+
+   MAGIC_CHECK(e, Evas, MAGIC_EVAS);
+   return NULL;
+   MAGIC_CHECK_END();
+   obj = evas_object_new();
+   evas_object_gradient2_radial_init(obj);
+   evas_object_inject(obj, e);
+   if (obj->object_data)
+     {
+       Evas_Object_Gradient2_Radial *o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+
+       o->engine_data = e->engine.func->gradient2_radial_new(e->engine.data.output);
+     }
+   return obj;
+}
+
+/**
+ * @defgroup Evas_Object_Gradient_Radial_Fill_Group Radial_Gradient Object Fill Functions
+ *
+ * Functions that deal with the fill geometry of the radial gradient object.
+ */
+
+/**
+ * Sets the center and radii of the radial gradient geometry for the object.
+ *
+ * Note that the gradient may extend beyond these,
+ * according to its spread value - restrict, repeat, or reflect.  To have
+ * only one 'cycle' of the gradient drawn, the spread value must be set
+ * to restrict.
+ * The default values for the fill parameters is @p cx = 0, @p cy = 0,
+ * @p rx = 0 and @p ry = 0.
+ *
+ * @param   obj The given evas radial gradient object.
+ * @param   cx   The X coordinate of the start point.
+ * @param   cy   The Y coordinate of the start point.
+ * @param   rx   The length of the x-cordinate radius.
+ * @param   ry   The length of the y-coordinate radius.
+ * @ingroup Evas_Object_Gradient_Radial_Fill_Group
+ */
+EAPI void
+evas_object_gradient2_radial_fill_set(Evas_Object *obj, float cx, float cy, float rx, float ry)
+{
+   Evas_Object_Gradient2_Radial *o;
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   MAGIC_CHECK(o, Evas_Object_Gradient2_Radial, MAGIC_OBJ_GRADIENT_RADIAL);
+   return;
+   MAGIC_CHECK_END();
+   if ((o->cur.fill.cx == cx) &&
+       (o->cur.fill.cy == cy) &&
+       (o->cur.fill.rx == rx) &&
+       (o->cur.fill.ry == ry)) return;
+   o->cur.fill.cx = cx;
+   o->cur.fill.cy = cy;
+   o->cur.fill.rx = rx;
+   o->cur.fill.ry = ry;
+   o->gradient_changed = 1;
+   o->changed = 1;
+   evas_object_change(obj);
+}
+
+EAPI void
+evas_object_gradient2_radial_fill_get(const Evas_Object *obj, float *cx, float *cy, float *rx, float *ry)
+{
+   Evas_Object_Gradient2_Radial *o;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   if (cx) *cx = 0;
+   if (cy) *cy = 0;
+   if (rx) *rx = 0;
+   if (ry) *ry = 0;
+   return;
+   MAGIC_CHECK_END();
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   MAGIC_CHECK(o, Evas_Object_Gradient2_Radial, MAGIC_OBJ_GRADIENT_RADIAL);
+   if (cx) *cx = 0;
+   if (cy) *cy = 0;
+   if (rx) *rx = 0;
+   if (ry) *ry = 0;
+   return;
+   MAGIC_CHECK_END();
+   if (cx) *cx = o->cur.fill.cx;
+   if (cy) *cy = o->cur.fill.cy;
+   if (rx) *rx = o->cur.fill.rx;
+   if (ry) *ry = o->cur.fill.ry;
+   return;
+}
+
+
+
+/* all nice and private */
+static void
+evas_object_gradient2_radial_init(Evas_Object *obj)
+{
+   /* alloc grad ob, setup methods and default values */
+   obj->object_data = evas_object_gradient2_radial_new();
+   /* set up default settings for this kind of object */
+   obj->cur.color.r = 255;
+   obj->cur.color.g = 255;
+   obj->cur.color.b = 255;
+   obj->cur.color.a = 255;
+   obj->cur.geometry.x = 0;
+   obj->cur.geometry.y = 0;
+   obj->cur.geometry.w = 0;
+   obj->cur.geometry.h = 0;
+   obj->cur.layer = 0;
+   obj->cur.anti_alias = 1;
+   obj->cur.interpolation_color_space = EVAS_COLOR_SPACE_ARGB;
+   obj->cur.render_op = EVAS_RENDER_BLEND;
+   /* set up object-specific settings */
+   obj->prev = obj->cur;
+   /* set up methods (compulsory) */
+   obj->func = &rg_object_func;
+   obj->type = rg_type;
+   obj->changed = 1;
+}
+
+static void *
+evas_object_gradient2_radial_new(void)
+{
+   Evas_Object_Gradient2_Radial *o;
+   Evas_Object_Gradient2 *og;
+
+   /* alloc obj private data */
+   o = calloc(1, sizeof(Evas_Object_Gradient2_Radial));
+   if (!o) return NULL;
+   o->magic = MAGIC_OBJ_GRADIENT_RADIAL;
+   o->cur.fill.cx = 0;
+   o->cur.fill.cy = 0;
+   o->cur.fill.rx = 1;
+   o->cur.fill.ry = 1;
+   og = (Evas_Object_Gradient2 *)o;
+   og->magic = MAGIC_OBJ_GRADIENT;
+   og->cur.fill.transform.mxx = og->cur.fill.transform.myy = og->cur.fill.transform.mzz = 1;
+   og->cur.fill.spread = EVAS_TEXTURE_REPEAT;
+   og->cur.gradient_opaque = 0;
+   og->prev = og->cur;
+   og->gradient_changed = 1;
+   o->prev = o->cur;
+   o->changed = 1;
+   o->gradient_changed = 1;
+   return o;
+}
+
+static void
+evas_object_gradient2_radial_free(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Radial *o;
+
+   /* frees private object data. very simple here */
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   MAGIC_CHECK(o, Evas_Object_Gradient2_Radial, MAGIC_OBJ_GRADIENT_RADIAL);
+   return;
+   MAGIC_CHECK_END();
+   /* free obj */
+   if (o->engine_data)
+      obj->layer->evas->engine.func->gradient2_radial_free(obj->layer->evas->engine.data.output,
+                                                         o->engine_data);
+   free(o);
+   obj->object_data = NULL; 
+}
+
+
+
+static void
+evas_object_gradient2_radial_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
+{
+   Evas_Object_Gradient2_Radial *o;
+
+   /* render object to surface with context, and offxet by x,y */
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   obj->layer->evas->engine.func->context_multiplier_unset(output, context);
+   obj->layer->evas->engine.func->context_anti_alias_set(output, context, obj->cur.anti_alias);
+   obj->layer->evas->engine.func->context_render_op_set(output, context, obj->cur.render_op);
+   if (o->engine_data)
+     {
+       obj->layer->evas->engine.func->gradient2_radial_draw(output, context, surface,
+                                                    o->engine_data,
+                                                    obj->cur.geometry.x + x,
+                                                    obj->cur.geometry.y + y,
+                                                    obj->cur.geometry.w,
+                                                    obj->cur.geometry.h);
+     }
+}
+
+static void
+evas_object_gradient2_radial_render_pre(Evas_Object *obj)
+{
+   Evas_Rectangles rects = { 0, 0, NULL };
+   Evas_Object_Gradient2_Radial *o;
+   Evas_Object_Gradient2 *og;
+   int is_v, was_v;
+
+   /* dont pre-render the obj twice! */
+   if (obj->pre_render_done) return;
+   obj->pre_render_done = 1;
+   /* pre-render phase. this does anything an object needs to do just before */
+   /* rendering. this could mean loading the image data, retrieving it from */
+   /* elsewhere, decoding video etc. */
+   /* then when this is done the object needs to figure if it changed and */
+   /* if so what and where and add the appropriate redraw rectangles */
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   og = (Evas_Object_Gradient2 *)(o);
+   /* if someone is clipping this obj - go calculate the clipper */
+   if (obj->cur.clipper)
+     {
+       if (obj->cur.cache.clip.dirty)
+         evas_object_clip_recalc(obj->cur.clipper);
+       obj->cur.clipper->func->render_pre(obj->cur.clipper);
+     }
+   /* if it changed color */
+   if ((obj->cur.color.r != obj->prev.color.r) ||
+       (obj->cur.color.g != obj->prev.color.g) ||
+       (obj->cur.color.b != obj->prev.color.b) ||
+       (obj->cur.color.a != obj->prev.color.a))
+     { o->gradient_changed = 1;  o->changed = 1; }
+   if ((!o->gradient_changed) && ((obj->cur.cache.clip.r != obj->prev.cache.clip.r) ||
+       (obj->cur.cache.clip.g != obj->prev.cache.clip.g) ||
+       (obj->cur.cache.clip.b != obj->prev.cache.clip.b) ||
+       (obj->cur.cache.clip.a != obj->prev.cache.clip.a)))
+     { o->gradient_changed = 1;  o->changed = 1; }
+   if (!o->gradient_changed && (obj->cur.interpolation_color_space != obj->prev.interpolation_color_space))
+     { o->gradient_changed = 1;  o->changed = 1; }
+   if (!o->changed && (obj->cur.render_op != obj->prev.render_op))
+       o->changed = 1;
+//   if (!o->changed && (obj->cur.anti_alias != obj->prev.anti_alias))
+//     o->changed = 1;
+   if (og->gradient_changed)
+     { o->gradient_changed = 1;  o->changed = 1; }
+   if (o->changed && o->engine_data)
+     {
+       obj->layer->evas->engine.func->context_render_op_set(obj->layer->evas->engine.data.output,
+                                                            obj->layer->evas->engine.data.context, obj->cur.render_op);
+       obj->layer->evas->engine.func->context_multiplier_set(obj->layer->evas->engine.data.output,
+                                                               obj->layer->evas->engine.data.context,
+                                                               obj->cur.cache.clip.r, obj->cur.cache.clip.g,
+                                                               obj->cur.cache.clip.b, obj->cur.cache.clip.a);
+       obj->layer->evas->engine.func->context_color_interpolation_set(obj->layer->evas->engine.data.output,
+                                                                       obj->layer->evas->engine.data.context,
+                                                                       obj->cur.interpolation_color_space);
+       if (o->gradient_changed)
+         {
+           obj->layer->evas->engine.func->gradient2_radial_fill_set(obj->layer->evas->engine.data.output, o->engine_data, o->cur.fill.cx, o->cur.fill.cy, o->cur.fill.rx, o->cur.fill.ry);
+           obj->layer->evas->engine.func->gradient2_fill_transform_set(obj->layer->evas->engine.data.output, o->engine_data,
+                                                               &og->cur.fill.transform);
+           obj->layer->evas->engine.func->gradient2_fill_spread_set(obj->layer->evas->engine.data.output, o->engine_data,
+                                                               og->cur.fill.spread);
+           obj->layer->evas->engine.func->gradient2_radial_render_pre(obj->layer->evas->engine.data.output,
+                                                               obj->layer->evas->engine.data.context,
+                                                               o->engine_data);
+         }
+       og->cur.gradient_opaque = obj->layer->evas->engine.func->gradient2_radial_is_opaque(obj->layer->evas->engine.data.output,
+                                                                                  obj->layer->evas->engine.data.context,
+                                                                                  o->engine_data,
+                                                                                  obj->cur.cache.clip.x, obj->cur.cache.clip.y,
+                                                                                  obj->cur.cache.clip.w, obj->cur.cache.clip.h);
+
+       if (obj->cur.cache.clip.a != 255)
+           og->cur.gradient_opaque = 0;
+    }
+   /* now figure what changed and add draw rects */
+   /* if it just became visible or invisible */
+   is_v = evas_object_is_visible(obj);
+   was_v = evas_object_was_visible(obj);
+   if (is_v != was_v)
+     {
+       evas_object_render_pre_visible_change(&rects, obj, is_v, was_v);
+       goto done;
+     }
+   /* its 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(&rects, obj);
+   /* gradient changed */
+   if (o->changed || obj->restack)
+     {
+       evas_object_render_pre_prev_cur_add(&rects, obj);
+       goto done;
+     }
+   /* if it changed geometry */
+   if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
+       (obj->cur.geometry.y != obj->prev.geometry.y) ||
+       (obj->cur.geometry.w != obj->prev.geometry.w) ||
+       (obj->cur.geometry.h != obj->prev.geometry.h))
+     {
+       evas_object_render_pre_prev_cur_add(&rects, obj);
+       goto done;
+     }
+   /* it obviously didn't change - add a NO obscure - this "unupdates"  this */
+   /* area so if there were updates for it they get wiped. don't do it if we */
+   /* arent fully opaque and we are visible */
+   
+   if (evas_object_is_visible(obj) &&
+       evas_object_is_opaque(obj))
+     obj->layer->evas->engine.func->output_redraws_rect_del(obj->layer->evas->engine.data.output,
+                                                           obj->cur.cache.clip.x,
+                                                           obj->cur.cache.clip.y,
+                                                           obj->cur.cache.clip.w,
+                                                           obj->cur.cache.clip.h);
+   
+   done:
+   evas_object_render_pre_effect_updates(&rects, obj, is_v, was_v);
+}
+
+static void
+evas_object_gradient2_radial_render_post(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Radial *o;
+   Evas_Object_Gradient2 *og;
+
+   /* this moves the current data to the previous state parts of the object */
+   /* in whatever way is safest for the object. also if we don't need object */
+   /* data anymore we can free it if the object deems this is a good idea */
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   og = (Evas_Object_Gradient2 *)(o);
+   /* remove those pesky changes */
+   while (obj->clip.changes)
+     {
+       Evas_Rectangle *r;
+
+       r = (Evas_Rectangle *)obj->clip.changes->data;
+       obj->clip.changes = evas_list_remove(obj->clip.changes, r);
+       free(r);
+     }
+   /* move cur to prev safely for object data */
+   obj->prev = obj->cur;
+   obj->changed = 0;
+   o->prev = o->cur;
+   o->changed = 0;
+   o->gradient_changed = 0;
+   og->prev = og->cur;
+   og->gradient_changed = 0;
+}
+
+static int evas_object_gradient2_radial_visual_type_get(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Radial *o;
+
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   if (!o) return 0;
+   return MAGIC_OBJ_GRADIENT;
+}
+
+static void *evas_object_gradient2_radial_engine_data_get(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Radial *o;
+
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   if (!o) return NULL;
+   return o->engine_data;
+}
+
+
+static int
+evas_object_gradient2_radial_is_opaque(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Radial *o;
+   Evas_Object_Gradient2 *og;
+
+   /* this returns 1 if the internal object data implies that the object is */
+   /* currently fully opaque over the entire region it occupies */
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   if (!o->engine_data) return 0;
+   og = (Evas_Object_Gradient2 *)(o);
+   return og->cur.gradient_opaque;
+ }
+
+static int
+evas_object_gradient2_radial_was_opaque(Evas_Object *obj)
+{
+   Evas_Object_Gradient2_Radial *o;
+   Evas_Object_Gradient2 *og;
+
+   /* this returns 1 if the internal object data implies that the object was */
+   /* currently fully opaque over the entire region it occupies */
+   o = (Evas_Object_Gradient2_Radial *)(obj->object_data);
+   if (!o->engine_data) return 0;
+   og = (Evas_Object_Gradient2 *)(o);
+   return og->prev.gradient_opaque;
+}
index 487350c..aa8f72e 100644 (file)
@@ -70,6 +70,9 @@ static void evas_object_image_free(Evas_Object *obj);
 static void evas_object_image_render_pre(Evas_Object *obj);
 static void evas_object_image_render_post(Evas_Object *obj);
 
+static int evas_object_image_visual_type_get(Evas_Object *obj);
+static void *evas_object_image_engine_data_get(Evas_Object *obj);
+
 static int evas_object_image_is_opaque(Evas_Object *obj);
 static int evas_object_image_was_opaque(Evas_Object *obj);
 static int evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
@@ -83,6 +86,8 @@ static const Evas_Object_Func object_func =
    evas_object_image_render,
    evas_object_image_render_pre,
    evas_object_image_render_post,
+     evas_object_image_visual_type_get,
+     evas_object_image_engine_data_get,
    /* these are optional. NULL = nothing */
    NULL,
    NULL,
@@ -2336,6 +2341,24 @@ evas_object_image_render_post(Evas_Object *obj)
    /* FIXME: copy strings across */
 }
 
+static int evas_object_image_visual_type_get(Evas_Object *obj)
+{
+   Evas_Object_Image *o;
+
+   o = (Evas_Object_Image *)(obj->object_data);
+   if (!o) return 0;
+   return MAGIC_OBJ_IMAGE;
+}
+
+static void *evas_object_image_engine_data_get(Evas_Object *obj)
+{
+   Evas_Object_Image *o;
+
+   o = (Evas_Object_Image *)(obj->object_data);
+   if (!o) return NULL;
+   return o->engine_data;
+}
+
 static int
 evas_object_image_is_opaque(Evas_Object *obj)
 {
index 15bf61c..1f6ff0b 100644 (file)
@@ -33,6 +33,9 @@ static void evas_object_line_free(Evas_Object *obj);
 static void evas_object_line_render_pre(Evas_Object *obj);
 static void evas_object_line_render_post(Evas_Object *obj);
 
+static int evas_object_line_visual_type_get(Evas_Object *obj);
+static void *evas_object_line_engine_data_get(Evas_Object *obj);
+
 static int evas_object_line_is_opaque(Evas_Object *obj);
 static int evas_object_line_was_opaque(Evas_Object *obj);
 static int evas_object_line_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
@@ -46,6 +49,8 @@ static const Evas_Object_Func object_func =
      evas_object_line_render,
      evas_object_line_render_pre,
      evas_object_line_render_post,
+     evas_object_line_visual_type_get,
+     evas_object_line_engine_data_get,
    /* these are optional. NULL = nothing */
      NULL,
      NULL,
@@ -403,6 +408,24 @@ evas_object_line_render_post(Evas_Object *obj)
    o->changed = 0;
 }
 
+static int evas_object_line_visual_type_get(Evas_Object *obj)
+{
+   Evas_Object_Line *o;
+
+   o = (Evas_Object_Line *)(obj->object_data);
+   if (!o) return 0;
+   return MAGIC_OBJ_SHAPE;
+}
+
+static void *evas_object_line_engine_data_get(Evas_Object *obj)
+{
+   Evas_Object_Line *o;
+
+   o = (Evas_Object_Line *)(obj->object_data);
+   if (!o) return NULL;
+   return o->engine_data;
+}
+
 static int
 evas_object_line_is_opaque(Evas_Object *obj)
 {
index d327a61..35ac120 100644 (file)
@@ -31,6 +31,9 @@ static void evas_object_polygon_free(Evas_Object *obj);
 static void evas_object_polygon_render_pre(Evas_Object *obj);
 static void evas_object_polygon_render_post(Evas_Object *obj);
 
+static int evas_object_polygon_visual_type_get(Evas_Object *obj);
+static void *evas_object_polygon_engine_data_get(Evas_Object *obj);
+
 static int evas_object_polygon_is_opaque(Evas_Object *obj);
 static int evas_object_polygon_was_opaque(Evas_Object *obj);
 static int evas_object_polygon_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
@@ -43,6 +46,8 @@ static const Evas_Object_Func object_func =
      evas_object_polygon_render,
      evas_object_polygon_render_pre,
      evas_object_polygon_render_post,
+     evas_object_polygon_visual_type_get,
+     evas_object_polygon_engine_data_get,
    /* these are optional. NULL = nothing */
      NULL,
      NULL,
@@ -409,6 +414,24 @@ evas_object_polygon_render_post(Evas_Object *obj)
    o->changed = 0;
 }
 
+static int evas_object_polygon_visual_type_get(Evas_Object *obj)
+{
+   Evas_Object_Polygon *o;
+
+   o = (Evas_Object_Polygon *)(obj->object_data);
+   if (!o) return 0;
+   return MAGIC_OBJ_SHAPE;
+}
+
+static void *evas_object_polygon_engine_data_get(Evas_Object *obj)
+{
+   Evas_Object_Polygon *o;
+
+   o = (Evas_Object_Polygon *)(obj->object_data);
+   if (!o) return NULL;
+   return o->engine_data;
+}
+
 static int
 evas_object_polygon_is_opaque(Evas_Object *obj)
 {
index 306877b..6264609 100644 (file)
@@ -20,6 +20,10 @@ static void evas_object_rectangle_render(Evas_Object *obj, void *output, void *c
 static void evas_object_rectangle_free(Evas_Object *obj);
 static void evas_object_rectangle_render_pre(Evas_Object *obj);
 static void evas_object_rectangle_render_post(Evas_Object *obj);
+
+static int evas_object_rectangle_visual_type_get(Evas_Object *obj);
+static void *evas_object_rectangle_engine_data_get(Evas_Object *obj);
+
 static int evas_object_rectangle_is_opaque(Evas_Object *obj);
 static int evas_object_rectangle_was_opaque(Evas_Object *obj);
 
@@ -39,6 +43,8 @@ static const Evas_Object_Func object_func =
      evas_object_rectangle_render,
      evas_object_rectangle_render_pre,
      evas_object_rectangle_render_post,
+     evas_object_rectangle_visual_type_get,
+     evas_object_rectangle_engine_data_get,
    /* these are optional. NULL = nothing */
      NULL,
      NULL,
@@ -312,6 +318,25 @@ evas_object_rectangle_was_opaque(Evas_Object *obj)
    return 1;
 }
 
+static int evas_object_rectangle_visual_type_get(Evas_Object *obj)
+{
+   Evas_Object_Rectangle *o;
+
+   o = (Evas_Object_Rectangle *)(obj->object_data);
+   if (!o) return 0;
+   return MAGIC_OBJ_SHAPE;
+}
+
+static void *evas_object_rectangle_engine_data_get(Evas_Object *obj)
+{
+   Evas_Object_Rectangle *o;
+
+   o = (Evas_Object_Rectangle *)(obj->object_data);
+   if (!o) return NULL;
+   return o->engine_data;
+}
+
+
 #if 0 /* usless calls for a rect object. much more useful for images etc. */
 static void
 evas_object_rectangle_store(Evas_Object *obj)
index aaffd3e..cc67630 100644 (file)
@@ -32,6 +32,9 @@ static void evas_object_smart_free(Evas_Object *obj);
 static void evas_object_smart_render_pre(Evas_Object *obj);
 static void evas_object_smart_render_post(Evas_Object *obj);
 
+static int evas_object_smart_visual_type_get(Evas_Object *obj);
+static void *evas_object_smart_engine_data_get(Evas_Object *obj);
+
 static const Evas_Object_Func object_func =
 {
    /* methods (compulsory) */
@@ -39,6 +42,8 @@ static const Evas_Object_Func object_func =
      evas_object_smart_render,
      evas_object_smart_render_pre,
      evas_object_smart_render_post,
+     evas_object_smart_visual_type_get,
+     evas_object_smart_engine_data_get,
      /* these are optional. NULL = nothing */
      NULL,
      NULL,
@@ -626,3 +631,21 @@ evas_object_smart_render_post(Evas_Object *obj)
 {
    obj->prev = obj->cur;
 }
+
+static int evas_object_smart_visual_type_get(Evas_Object *obj)
+{
+   Evas_Object_Smart *o;
+
+   o = (Evas_Object_Smart *)(obj->object_data);
+   if (!o) return 0;
+   return MAGIC_OBJ_CONTAINER;
+}
+
+static void *evas_object_smart_engine_data_get(Evas_Object *obj)
+{
+   Evas_Object_Smart *o;
+
+   o = (Evas_Object_Smart *)(obj->object_data);
+   if (!o) return NULL;
+   return o->engine_data;
+}
index 55a9648..3f9d39d 100644 (file)
@@ -43,6 +43,9 @@ static void evas_object_text_free(Evas_Object *obj);
 static void evas_object_text_render_pre(Evas_Object *obj);
 static void evas_object_text_render_post(Evas_Object *obj);
 
+static int evas_object_text_visual_type_get(Evas_Object *obj);
+static void *evas_object_text_engine_data_get(Evas_Object *obj);
+
 static int evas_object_text_is_opaque(Evas_Object *obj);
 static int evas_object_text_was_opaque(Evas_Object *obj);
 
@@ -53,6 +56,8 @@ static const Evas_Object_Func object_func =
      evas_object_text_render,
      evas_object_text_render_pre,
      evas_object_text_render_post,
+     evas_object_text_visual_type_get,
+     evas_object_text_engine_data_get,
    /* these are optional. NULL = nothing */
      NULL,
      NULL,
@@ -1664,6 +1669,24 @@ evas_object_text_render_post(Evas_Object *obj)
    o->changed = 0;
 }
 
+static int evas_object_text_visual_type_get(Evas_Object *obj)
+{
+   Evas_Object_Text *o;
+
+   o = (Evas_Object_Text *)(obj->object_data);
+   if (!o) return 0;
+   return MAGIC_OBJ_SHAPE;
+}
+
+static void *evas_object_text_engine_data_get(Evas_Object *obj)
+{
+   Evas_Object_Text *o;
+
+   o = (Evas_Object_Text *)(obj->object_data);
+   if (!o) return NULL;
+   return o->engine_data;
+}
+
 static int
 evas_object_text_is_opaque(Evas_Object *obj)
 {
index baeaa8d..93ac7d8 100644 (file)
@@ -143,6 +143,9 @@ static void evas_object_textblock_free(Evas_Object *obj);
 static void evas_object_textblock_render_pre(Evas_Object *obj);
 static void evas_object_textblock_render_post(Evas_Object *obj);
 
+static int evas_object_textblock_visual_type_get(Evas_Object *obj);
+static void *evas_object_textblock_engine_data_get(Evas_Object *obj);
+
 static int evas_object_textblock_is_opaque(Evas_Object *obj);
 static int evas_object_textblock_was_opaque(Evas_Object *obj);
 
@@ -155,6 +158,8 @@ static const Evas_Object_Func object_func =
      evas_object_textblock_render,
      evas_object_textblock_render_pre,
      evas_object_textblock_render_post,
+     evas_object_textblock_visual_type_get,
+     evas_object_textblock_engine_data_get,
    /* these are optional. NULL = nothing */
      NULL,
      NULL,
@@ -4873,6 +4878,24 @@ evas_object_textblock_render_post(Evas_Object *obj)
 /*   o->changed = 0; */
 }
 
+static int evas_object_textblock_visual_type_get(Evas_Object *obj)
+{
+   Evas_Object_Textblock *o;
+
+   o = (Evas_Object_Textblock *)(obj->object_data);
+   if (!o) return 0;
+   return MAGIC_OBJ_CUSTOM;
+}
+
+static void *evas_object_textblock_engine_data_get(Evas_Object *obj)
+{
+   Evas_Object_Textblock *o;
+
+   o = (Evas_Object_Textblock *)(obj->object_data);
+   if (!o) return NULL;
+   return o->engine_data;
+}
+
 static int
 evas_object_textblock_is_opaque(Evas_Object *obj)
 {
index 516caf9..643bc42 100644 (file)
@@ -46,6 +46,9 @@ evas_gradient_radial.c \
 evas_gradient_angular.c \
 evas_gradient_rectangular.c \
 evas_gradient_sinusoidal.c \
+evas_gradient2_main.c \
+evas_gradient2_linear.c \
+evas_gradient2_radial.c \
 evas_image_load.c \
 evas_image_save.c \
 evas_image_main.c \
index d32d356..50e2cb8 100644 (file)
@@ -28,4 +28,23 @@ EAPI void           evas_common_gradient_draw              (RGBA_Image *dst, RGB
 EAPI RGBA_Gradient_Type *evas_common_gradient_geometer_get (const char *name);
 
 
+
+EAPI void           evas_common_gradient2_free             (RGBA_Gradient2 *gr);
+EAPI RGBA_Gradient2 *evas_common_gradient2_linear_new              (void);
+EAPI void           evas_common_gradient2_linear_fill_set (RGBA_Gradient2 *gr, float x0, float y0, float x1, float y1);
+EAPI RGBA_Gradient2 *evas_common_gradient2_radial_new              (void);
+EAPI void           evas_common_gradient2_radial_fill_set (RGBA_Gradient2 *gr, float cx, float cy, float rx, float ry);
+EAPI void           evas_common_gradient2_clear            (RGBA_Gradient2 *gr);
+EAPI void           evas_common_gradient2_color_np_stop_insert   (RGBA_Gradient2 *gr, int r, int g, int b, int a, float pos);
+EAPI void           evas_common_gradient2_fill_spread_set  (RGBA_Gradient2 *gr, int spread);
+EAPI void           evas_common_gradient2_fill_transform_set (RGBA_Gradient2 *gr, Evas_Common_Transform *t);
+EAPI void           evas_common_gradient2_map              (RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len);
+EAPI void           evas_common_gradient2_draw             (RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient2 *gr);
+
+EAPI RGBA_Gradient2_Type *evas_common_gradient2_type_linear_get      (void);
+EAPI RGBA_Gradient2_Type *evas_common_gradient2_type_radial_get      (void);
+//EAPI RGBA_Gradient2_Type *evas_common_gradient2_type_angular_get     (void);
+//EAPI RGBA_Gradient2_Type *evas_common_gradient2_type_rectangular_get (void);
+//EAPI RGBA_Gradient2_Type *evas_common_gradient2_type_sinusoidal_get  (void);
+
 #endif /* _EVAS_GRADIENT_H */
diff --git a/src/lib/engines/common/evas_gradient2_linear.c b/src/lib/engines/common/evas_gradient2_linear.c
new file mode 100644 (file)
index 0000000..3a829fa
--- /dev/null
@@ -0,0 +1,723 @@
+#include "evas_common.h"
+#include "evas_private.h"
+#include <math.h>
+
+typedef struct _Linear_Data   Linear_Data;
+
+struct _Linear_Data
+{
+   float    x0, y0, x1, y1;
+   float    fx0, fy0, fx1, fy1;
+   int      ayx, ayy;
+   int      len;
+   unsigned char int_axis_aligned : 1;
+};
+
+
+static void 
+linear_init(void);
+
+static void 
+linear_shutdown(void);
+
+static void 
+linear_init_geom(RGBA_Gradient2 *gr);
+
+static void
+linear_update_geom(RGBA_Gradient2 *gr);
+
+static void 
+linear_free_geom(void *gdata);
+
+static int
+linear_has_alpha(RGBA_Gradient2 *gr, int op);
+
+static int
+linear_has_mask(RGBA_Gradient2 *gr, int op);
+
+static int
+linear_get_map_len(RGBA_Gradient2 *gr);
+
+static Gfx_Func_Gradient2_Fill
+linear_get_fill_func(RGBA_Gradient2 *gr, int op);
+
+static RGBA_Gradient2_Type  linear = {"linear", linear_init, linear_shutdown,
+                                     linear_init_geom,
+                                     linear_update_geom, linear_free_geom,
+                                     linear_has_alpha, linear_has_mask,
+                                     linear_get_map_len, linear_get_fill_func};
+
+
+EAPI RGBA_Gradient2_Type  *
+evas_common_gradient2_type_linear_get(void)
+{
+    return &linear;
+}
+
+EAPI RGBA_Gradient2 *
+evas_common_gradient2_linear_new(void)
+{
+   RGBA_Gradient2 *gr;
+
+   gr = calloc(1, sizeof(RGBA_Gradient2));
+   if (!gr) return NULL;
+   gr->references = 1;
+   gr->type.id = MAGIC_OBJ_GRADIENT_LINEAR;
+   gr->type.geometer = &linear;
+   linear_init_geom(gr);
+   return gr;
+}
+
+EAPI void
+evas_common_gradient2_linear_fill_set(RGBA_Gradient2 *gr, float x0, float y0, float x1, float y1)
+{
+   Linear_Data *linear_data;
+
+   if (!gr) return;
+   if (gr->type.id != MAGIC_OBJ_GRADIENT_LINEAR) return;
+   if (gr->type.geometer != &linear) return;
+   linear_data = (Linear_Data *)gr->type.gdata;
+   if (!linear_data) return;
+   linear_data->x0 = x0;  linear_data->y0 = y0;
+   linear_data->x1 = x1;  linear_data->y1 = y1;
+}
+
+
+
+/** internal functions **/
+
+static void
+linear_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                  int x, int y, void *params_data);
+
+static void
+linear_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                 int x, int y, void *params_data);
+
+static void
+linear_restrict_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                   int x, int y, void *params_data);
+
+static void
+linear_restrict_masked_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                          int x, int y, void *params_data);
+
+static void
+linear_pad_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+              int x, int y, void *params_data);
+
+
+
+static void 
+linear_init(void)
+{
+}
+
+static void 
+linear_shutdown(void)
+{
+}
+
+static void 
+linear_free_geom(void *gdata)
+{
+   Linear_Data *data = (Linear_Data *)gdata;
+   if (data) free(data);
+}
+
+static void
+linear_init_geom(RGBA_Gradient2 *gr)
+{
+   Linear_Data *linear_data;
+
+   if (!gr || (gr->type.geometer != &linear)) return;
+   linear_data = (Linear_Data *)gr->type.gdata;
+   if (!linear_data)
+     {
+       linear_data = calloc(1, sizeof(Linear_Data));
+       if (!linear_data)  return;
+       linear_data->ayy = 65536;  linear_data->ayx = 0;
+     }
+   gr->type.gdata = linear_data;
+}
+
+
+static void
+linear_update_geom(RGBA_Gradient2 *gr)
+{
+   Linear_Data *linear_data;
+   double f;
+   int len;
+
+   if (!gr || (gr->type.geometer != &linear)) return;
+   linear_data = (Linear_Data *)gr->type.gdata;
+   if (!linear_data) return;
+
+   linear_data->int_axis_aligned = 0;
+   linear_data->len = 0;
+   f = (gr->fill.transform.mxx * gr->fill.transform.myy) - (gr->fill.transform.mxy * gr->fill.transform.myx);
+   if (!f) return;
+
+   f = 1.0 / f;
+   linear_data->fx0 = (((gr->fill.transform.myy * linear_data->x0) - (gr->fill.transform.mxy * linear_data->y0)) * f) - gr->fill.transform.mxz;
+   linear_data->fy0 = ((-(gr->fill.transform.myx * linear_data->x0) + (gr->fill.transform.mxx * linear_data->y0)) * f) - gr->fill.transform.myz;
+
+   linear_data->fx1 = (((gr->fill.transform.myy * linear_data->x1) - (gr->fill.transform.mxy * linear_data->y1)) * f)  - gr->fill.transform.mxz;
+   linear_data->fy1 = ((-(gr->fill.transform.myx * linear_data->x1) + (gr->fill.transform.mxx * linear_data->y1)) * f) - gr->fill.transform.myz;
+
+   f = hypot(linear_data->fx0 - linear_data->fx1, linear_data->fy0 - linear_data->fy1);
+   linear_data->len = len = f;
+   if (!len) return;
+
+   linear_data->ayx = ((double)(linear_data->fx1 - linear_data->fx0) * 65536) / f;
+   linear_data->ayy = ((double)(linear_data->fy1 - linear_data->fy0) * 65536) / f;
+
+// 1/512 = 0.001953125 <-- will use this one as our subpixel pos tolerance.
+// 1/256 = 0.00390625  <-- though this one would be ok too for our uses.
+
+   if (fabs(linear_data->fy0 - linear_data->fy1) < 0.001953125)
+     {
+       if ( (fabs(((int)linear_data->fy0) - linear_data->fy0) < 0.001953125) &&
+           (fabs(((int)linear_data->fy1) - linear_data->fy1) < 0.001953125) )
+          { linear_data->int_axis_aligned = 1;  linear_data->ayy = 0; }
+     }
+   else if (fabs(linear_data->fx0 - linear_data->fx1) < 0.001953125)
+     {
+       if ( (fabs(((int)linear_data->fx0) - linear_data->fx0) < 0.001953125) &&
+           (fabs(((int)linear_data->fx1) - linear_data->fx1) < 0.001953125) )
+          { linear_data->int_axis_aligned = 1;  linear_data->ayx = 0; }
+     }
+}
+
+static int
+linear_has_alpha(RGBA_Gradient2 *gr, int op)
+{
+   if (!gr || (gr->type.geometer != &linear)) return 0;
+   if (gr->has_alpha | gr->map.has_alpha)
+       return 1;
+   if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) || 
+         (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
+       return 0;
+   if (gr->fill.spread == _EVAS_TEXTURE_RESTRICT)
+       return 1;
+   return 0;
+}
+
+static int
+linear_has_mask(RGBA_Gradient2 *gr, int op)
+{
+   if (!gr || (gr->type.geometer != &linear)) return 0;
+   if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) || 
+         (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
+     {
+       if (gr->fill.spread == _EVAS_TEXTURE_RESTRICT)
+           return 1;
+     }
+   return 0;
+}
+
+static int
+linear_get_map_len(RGBA_Gradient2 *gr)
+{
+   Linear_Data   *linear_data;
+
+   if (!gr || (gr->type.geometer != &linear)) return 0;
+   linear_data = (Linear_Data *)gr->type.gdata;
+   if (!linear_data) return 0;
+   return linear_data->len;
+}
+
+static Gfx_Func_Gradient2_Fill
+linear_get_fill_func(RGBA_Gradient2 *gr, int op)
+{
+   Linear_Data   *linear_data;
+   Gfx_Func_Gradient2_Fill  sfunc = NULL;
+   int masked_op = 0;
+
+   if (!gr || (gr->type.geometer != &linear))
+       return sfunc;
+   linear_data = (Linear_Data *)gr->type.gdata;
+   if (!linear_data) return sfunc;
+
+   if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) || 
+         (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
+       masked_op = 1;
+
+   switch (gr->fill.spread)
+     {
+      case _EVAS_TEXTURE_REPEAT:
+       sfunc = linear_repeat_aa;
+      break;
+      case _EVAS_TEXTURE_REFLECT:
+       sfunc = linear_reflect_aa;
+      break;
+      case _EVAS_TEXTURE_RESTRICT:
+       if (masked_op)
+          sfunc = linear_restrict_masked_aa;
+       else
+          sfunc = linear_restrict_aa;
+      break;
+      case _EVAS_TEXTURE_PAD:
+       sfunc = linear_pad_aa;
+      break;
+      default:
+       sfunc = linear_repeat_aa;
+      break;
+     }
+   return sfunc;
+}
+
+
+/* the fill functions */
+
+#ifdef BUILD_MMX
+#define INTERP_256_P2R(a, s, mma, mms, mmd, mmz) \
+           MOV_A2R(a, mma) \
+           MOV_P2R(s, mms, mmz) \
+           INTERP_256_R2R(mma, mms, mmd, mm5)
+
+#define MUL_256_A2R(a, mma, mmd, mmz) \
+       MOV_A2R(a, mma) \
+       MUL4_256_R2R(mma, mmd)
+#endif
+
+static void
+linear_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                 int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Linear_Data  *gdata = (Linear_Data *)params_data;
+   int      yy;
+
+   evas_common_cpu_end_opt();
+   yy = (gdata->ayx * (x - gdata->fx0 + 0.5)) + (gdata->ayy * (y - gdata->fy0 + 0.5)) - 32768;
+
+   if (gdata->int_axis_aligned && (gdata->ayx == 0))
+     {
+       DATA32  c;
+
+       y = (yy >> 16);
+       y = y % src_len;
+       if (y < 0)
+          y += src_len;
+       c = src[y];
+       while (dst < dst_end)
+           *dst++ = c;
+       return;
+     }
+
+   if (gdata->int_axis_aligned && (gdata->ayy == 0))
+     {
+       Gfx_Func_Copy  func;
+       int  l;
+
+       x = (yy >> 16);
+       x = x % src_len;
+       if (x < 0)
+          x += src_len;
+       if (gdata->ayx < 0)
+         {
+           l = x + 1;  x = 0;
+         }
+       else
+           l = src_len - x;
+       if (l > dst_len) l = dst_len;
+       func = evas_common_draw_func_copy_get(1, (gdata->ayx < 0 ? -1 : 0));
+       func(src + x, dst, l);
+       if (l == dst_len) return;
+       dst += l;  dst_len -= l;
+       l = dst_len / src_len;
+       while (l--)
+         {
+           func(src, dst, src_len);
+           dst += src_len;
+         }
+       l = dst_len % src_len;
+       if (gdata->ayx < 0)
+          src += src_len - l;
+       func(src, dst, l);
+       return;
+     }
+
+#ifdef BUILD_MMX
+   pxor_r2r(mm0, mm0);
+   MOV_A2R(ALPHA_255, mm5)
+#endif
+   while (dst < dst_end)
+     {
+       int  l = (yy >> 16);
+       int  a = 1 + ((yy & 0xffff) >> 8);
+
+       l = l % src_len;
+       if (l < 0)
+          l += src_len;
+#ifdef BUILD_MMX
+       MOV_P2R(src[l], mm1, mm0)
+#else
+       *dst = src[l];
+#endif
+       if (l + 1 < src_len)
+         {
+#ifdef BUILD_MMX
+           INTERP_256_P2R(a, src[l + 1], mm3, mm2, mm1, mm0)
+#else
+           *dst = INTERP_256(a, src[l + 1], *dst);
+#endif
+         }
+       if (l == (src_len - 1))
+         {
+#ifdef BUILD_MMX
+           INTERP_256_P2R(a, src[0], mm3, mm2, mm1, mm0)
+#else
+          *dst = INTERP_256(a, src[0], *dst);
+#endif
+         }
+#ifdef BUILD_MMX
+       MOV_R2P(mm1, *dst, mm0)
+#endif
+       dst++;  yy += gdata->ayx;
+     }
+}
+
+
+static void
+linear_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                  int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Linear_Data  *gdata = (Linear_Data *)params_data;
+   int      yy;
+
+   evas_common_cpu_end_opt();
+   yy = (gdata->ayx * (x - gdata->fx0 + 0.5)) + (gdata->ayy * (y - gdata->fy0 + 0.5)) - 32768;
+
+   if (gdata->int_axis_aligned && (gdata->ayx == 0))
+     {
+       DATA32  c;
+
+       y = (yy >> 16);
+       if (y < 0)  y = -y;
+       if (y >= src_len)
+         {
+           int  m = (y % (2 * src_len));
+
+           y = (y % src_len);
+           if (m >= src_len)
+               y = src_len - y - 1;
+         }
+       c = src[y];
+       while (dst < dst_end)
+           *dst++ = c;
+       return;
+     }
+
+   if (gdata->int_axis_aligned && (gdata->ayy == 0))
+     {
+       Gfx_Func_Copy  func, ofunc;
+       int  l, sgn;
+
+       x = (yy >> 16);
+       sgn = (gdata->ayx < 0 ? -1 : 1);
+       if (x < 0)
+         {
+           x = -x;  sgn *= -1;
+         }
+       if (x >= src_len)
+         {
+           int  m = (x % (2 * src_len));
+
+           x = (x % src_len);
+           if (m >= src_len)
+             { x = src_len - x - 1;  sgn *= -1; }
+         }
+
+       if (sgn < 0)
+         {
+           l = x + 1;  x = 0;
+         }
+       else
+           l = src_len - x;
+
+       if (l > dst_len) l = dst_len;
+       func = evas_common_draw_func_copy_get(1, 0);
+       ofunc = evas_common_draw_func_copy_get(1, -1);
+
+       if (sgn > 0)
+          func(src + x, dst, l);
+       else
+          ofunc(src + x, dst, l);
+       if (l == dst_len) return;
+
+       dst += l;  dst_len -= l;
+       l = dst_len / src_len;
+       sgn *= -1;
+       while (l--)
+         {
+           if (sgn > 0)
+              func(src, dst, src_len);
+           else
+              ofunc(src, dst, src_len);
+           sgn *= -1;
+           dst += src_len;
+         }
+       l = dst_len % src_len;
+       if (sgn < 0)
+         {
+           src += src_len - l;
+           ofunc(src, dst, l);
+         }
+       else
+          func(src, dst, l);
+       return;
+     }
+
+#ifdef BUILD_MMX
+   pxor_r2r(mm0, mm0);
+   MOV_A2R(ALPHA_255, mm5)
+#endif
+   while (dst < dst_end)
+     {
+       int  l = (yy >> 16);
+       int  a = 1 + ((yy & 0xffff) >> 8);
+
+       if (l < 0) { l = -l;  a = 257 - a; }
+       if (l >= src_len)
+         {
+           int  m = (l % (2 * src_len));
+
+           l = (l % src_len);
+           if (m >= src_len)
+             { l = src_len - l - 1;  a = 257 - a; }
+         }
+#ifdef BUILD_MMX
+       MOV_P2R(src[l], mm1, mm0)
+#else
+       *dst = src[l];
+#endif
+       if (l + 1 < src_len)
+         {
+#ifdef BUILD_MMX
+           INTERP_256_P2R(a, src[l + 1], mm3, mm2, mm1, mm0)
+#else
+           *dst = INTERP_256(a, src[l + 1], *dst);
+#endif
+         }
+#ifdef BUILD_MMX
+       MOV_R2P(mm1, *dst, mm0)
+#endif
+       dst++;  yy += gdata->ayx;
+     }
+}
+
+
+static void
+linear_restrict_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                   int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Linear_Data  *gdata = (Linear_Data *)params_data;
+   int      yy;
+
+   evas_common_cpu_end_opt();
+   yy = (gdata->ayx * (x - gdata->fx0 + 0.5)) + (gdata->ayy * (y - gdata->fy0 + 0.5)) - 32768;
+
+   if (gdata->int_axis_aligned && (gdata->ayx == 0))
+     {
+       DATA32  c;
+
+       y = (yy >> 16);
+       if ((y < 0) || (y >= src_len))
+         {
+           memset(dst, 0, sizeof(DATA32) * dst_len);
+           return;
+         }
+       c = src[y];
+       while (dst < dst_end)
+           *dst++ = c;
+       return;
+     }
+
+   if (gdata->int_axis_aligned && (gdata->ayy == 0))
+     {
+       Gfx_Func_Copy  func;
+       int sgn;
+
+       x = yy >> 16;
+       sgn = (gdata->ayx < 0 ? -1 : 1);
+       if ((unsigned)x < src_len)
+         {
+           if ((sgn > 0) && ((src_len - x) >= dst_len))
+             {
+               func = evas_common_draw_func_copy_get(dst_len, 0);
+               func(src + x, dst, dst_len);
+               return;
+             }
+           if ((sgn < 0) && (x >= (dst_len - 1)))
+             {
+               func = evas_common_draw_func_copy_get(dst_len, -1);
+               func(src + x - (dst_len - 1), dst, dst_len);
+               return;
+             }
+         }
+       while (dst < dst_end)
+         {
+           *dst = 0;
+           if ((unsigned)x < src_len)
+               *dst = src[x];
+           dst++;  x += sgn;
+         }
+       return;
+     }
+
+#ifdef BUILD_MMX
+   pxor_r2r(mm0, mm0);
+   MOV_A2R(ALPHA_255, mm5)
+#endif
+   while (dst < dst_end)
+     {
+       int  l = (yy >> 16);
+
+       *dst = 0;
+       if ((unsigned)(l + 1) < (src_len + 1))
+         {
+           int  a = 1 + ((yy & 0xffff) >> 8);
+           int    lp = l;
+
+           if (l == -1) lp = 0;
+#ifdef BUILD_MMX
+           MOV_P2R(src[lp], mm1, mm0)
+#else
+           *dst = src[lp];
+#endif
+           if (lp + 1 < src_len)
+             {
+#ifdef BUILD_MMX
+               INTERP_256_P2R(a, src[lp + 1], mm3, mm2, mm1, mm0)
+#else
+               *dst = INTERP_256(a, src[lp + 1], *dst);
+#endif
+             }
+           if (l == -1)
+             {
+#ifdef BUILD_MMX
+               MUL_256_A2R(a, mm3, mm1, mm0)
+#else
+               *dst = MUL_256(a, *dst);
+#endif
+             }
+           if (l == (src_len - 1))
+             {
+#ifdef BUILD_MMX
+               a = 257 - a;
+               MUL_256_A2R(a, mm3, mm1, mm0)
+#else
+               *dst = MUL_256(257 - a, *dst);
+#endif
+             }
+         }
+#ifdef BUILD_MMX
+           MOV_R2P(mm1, *dst, mm0)
+#endif
+       dst++;  yy += gdata->ayx;
+     }
+}
+
+
+static void
+linear_restrict_masked_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                          int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Linear_Data  *gdata = (Linear_Data *)params_data;
+   int      yy;
+
+   evas_common_cpu_end_opt();
+   yy = (gdata->ayx * (x - gdata->fx0 + 0.5)) + (gdata->ayy * (y - gdata->fy0 + 0.5)) - 32768;
+
+#ifdef BUILD_MMX
+   pxor_r2r(mm0, mm0);
+   MOV_A2R(ALPHA_255, mm5)
+#endif
+   while (dst < dst_end)
+     {
+       int  l = (yy >> 16);
+
+       *dst = 0;  *mask = 0;
+       if ((unsigned)(l + 1) < (src_len + 1))
+         {
+           int  a = 1 + ((yy & 0xffff) >> 8);
+           int    lp = l;
+
+           if (l == -1) lp = 0;
+
+#ifdef BUILD_MMX
+           MOV_P2R(src[lp], mm1, mm0)
+#else
+           *dst = src[lp];  *mask = 255;
+#endif
+           if (lp + 1 < src_len)
+             {
+#ifdef BUILD_MMX
+               INTERP_256_P2R(a, src[lp + 1], mm3, mm2, mm1, mm0)
+#else
+               *dst = INTERP_256(a, src[lp + 1], *dst);
+#endif
+             }
+#ifdef BUILD_MMX
+           MOV_R2P(mm1, *dst, mm0)
+#endif
+           if (l == -1)
+               *mask = a - 1;
+           if (l == (src_len - 1))
+               *mask = 256 - a;
+         }
+       dst++;  mask++;  yy += gdata->ayx;
+     }
+}
+
+
+static void
+linear_pad_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+              int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Linear_Data  *gdata = (Linear_Data *)params_data;
+   int      yy;
+
+   evas_common_cpu_end_opt();
+   yy = (gdata->ayx * (x - gdata->fx0 + 0.5)) + (gdata->ayy * (y - gdata->fy0 + 0.5)) - 32768;
+
+#ifdef BUILD_MMX
+   pxor_r2r(mm0, mm0);
+   MOV_A2R(ALPHA_255, mm5)
+#endif
+   while (dst < dst_end)
+     {
+       int  l = (yy >> 16);
+
+       if (l < 0) *dst = src[0];
+       if (l >= src_len) *dst = src[src_len - 1];
+       if ((unsigned)l < src_len)
+         {
+           int  a = 1 + ((yy & 0xffff) >> 8);
+
+#ifdef BUILD_MMX
+           MOV_P2R(src[l], mm1, mm0)
+#else
+           *dst = src[l];
+#endif
+           if (l && (l + 1 < src_len))
+             {
+#ifdef BUILD_MMX
+               INTERP_256_P2R(a, src[l + 1], mm3, mm2, mm1, mm0)
+#else
+               *dst = INTERP_256(a, src[l + 1], *dst);
+#endif
+             }
+#ifdef BUILD_MMX
+           MOV_R2P(mm1, *dst, mm0)
+#endif
+         }
+       dst++;  yy += gdata->ayx;
+     }
+}
diff --git a/src/lib/engines/common/evas_gradient2_main.c b/src/lib/engines/common/evas_gradient2_main.c
new file mode 100644 (file)
index 0000000..dbd06b9
--- /dev/null
@@ -0,0 +1,578 @@
+#include "evas_common.h"
+#include "evas_blend_private.h"
+#include "evas_private.h"
+#include <math.h>
+
+static void _evas_common_gradient2_stops_free(RGBA_Gradient2 *gr);
+static void _evas_common_gradient2_stops_scale(RGBA_Gradient2 *gr);
+
+static void _evas_common_gradient2_map_argb(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len);
+static void _evas_common_gradient2_map_ahsv(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len);
+
+static  int grad_initialised = 0;
+
+EAPI void
+evas_common_gradient2_init(void)
+{
+   RGBA_Gradient2_Type  *geom;
+
+   if (grad_initialised)
+       return;
+   geom = evas_common_gradient2_type_linear_get();
+   if (geom)
+       geom->init();
+   geom = evas_common_gradient2_type_radial_get();
+   if (geom)
+       geom->init();
+   grad_initialised = 1;
+}
+
+void
+evas_common_gradient2_shutdown(void)
+{
+   RGBA_Gradient2_Type  *geom;
+
+   if (!grad_initialised)
+       return;
+   geom = evas_common_gradient2_type_linear_get();
+   if (geom)
+       geom->shutdown();
+   geom = evas_common_gradient2_type_radial_get();
+   if (geom)
+       geom->shutdown();
+   grad_initialised = 0;
+}
+
+static void
+_evas_common_gradient2_stops_free(RGBA_Gradient2 *gr)
+{
+   if (!gr) return;
+   if (gr->stops.stops)
+     {
+       Evas_Object_List *l;
+
+       while (gr->stops.stops)
+         {
+          l = gr->stops.stops;
+          gr->stops.stops = evas_object_list_remove(gr->stops.stops, gr->stops.stops);
+          free(l);
+         }
+       gr->stops.stops = NULL;
+       gr->stops.nstops = 0;
+     }
+}
+
+EAPI void
+evas_common_gradient2_free(RGBA_Gradient2 *gr)
+{
+   if (!gr) return;
+   gr->references--;
+   if (gr->references > 0) return;
+   evas_common_gradient2_clear(gr);
+   if (gr->stops.cdata) free(gr->stops.cdata);
+   if (gr->stops.adata) free(gr->stops.adata);
+   if (gr->type.geometer && gr->type.gdata)
+       gr->type.geometer->geom_free(gr->type.gdata);
+   if (gr->map.data) free(gr->map.data);
+   free(gr);
+}
+
+EAPI void
+evas_common_gradient2_clear(RGBA_Gradient2 *gr)
+{
+   if (!gr) return;
+
+   _evas_common_gradient2_stops_free(gr);
+   gr->has_alpha = 0;
+}
+
+EAPI void
+evas_common_gradient2_color_np_stop_insert(RGBA_Gradient2 *gr, int r, int g, int b, int a, float pos)
+{
+   RGBA_Gradient2_Color_Np_Stop *gc;
+   Evas_Object_List *l;
+
+   if (!gr) return;
+   if (!gr->stops.stops)
+     {
+       RGBA_Gradient2_Color_Np_Stop *gc1;
+
+       gc = malloc(sizeof(RGBA_Gradient2_Color_Np_Stop));
+       if (!gc) return;
+       gc1 = malloc(sizeof(RGBA_Gradient2_Color_Np_Stop));
+       if (!gc1) { free(gc);  return; }
+       gc->r = gc->g = gc->b = gc->a = 255;  gc->pos = 0.0;  gc->dist = 0;
+       gc1->r = gc1->g = gc1->b = gc1->a = 255;  gc1->pos = 1.0;  gc1->dist = 0;
+
+       gr->stops.stops = evas_object_list_append(gr->stops.stops, gc);
+       gr->stops.stops = evas_object_list_append(gr->stops.stops, gc1);
+       gr->stops.nstops = 2;
+       gr->stops.len = 0;
+     }
+
+   if (r < 0) r = 0;  if (r > 255) r = 255;
+   if (g < 0) g = 0;  if (g > 255) g = 255;
+   if (b < 0) b = 0;  if (b > 255) b = 255;
+   if (a < 0) a = 0;  if (a > 255) a = 255;
+   if (pos < 0.0) pos = 0.0;
+   if (pos > 1.0) pos = 1.0;
+
+   if (pos == 0.0)
+     {
+       gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
+       gc->r = r;  gc->g = g;  gc->b = b;  gc->a = a;  gc->dist = 0;
+        if (a < 255) gr->has_alpha = 1;
+       return;
+     }
+   if (pos == 1.0)
+     {
+       gc = (RGBA_Gradient2_Color_Np_Stop *)(gr->stops.stops->last);
+       gc->r = r;  gc->g = g;  gc->b = b;  gc->a = a;  gc->dist = 0;
+       if (a < 255) gr->has_alpha = 1;
+       return;
+     }
+
+   l = gr->stops.stops->next;
+   while (l)
+     {
+       gc = (RGBA_Gradient2_Color_Np_Stop *)l;
+       if (pos <= gc->pos)
+         {
+           if (pos == gc->pos)
+             {
+               gc->r = r;  gc->g = g;  gc->b = b;  gc->a = a;  gc->dist = 0;
+               if (a < 255) gr->has_alpha = 1;
+               return;
+             }
+           break;
+         }
+       l = l->next;
+     }
+
+   gc = malloc(sizeof(RGBA_Gradient2_Color_Np_Stop));
+   if (!gc) return;
+   gc->r = r;
+   gc->g = g;
+   gc->b = b;
+   gc->a = a;
+   gc->pos = pos;
+   gc->dist = 0;
+
+   gr->stops.stops = evas_object_list_prepend_relative(gr->stops.stops, gc, l);
+   gr->stops.nstops++;
+   if (a < 255)
+       gr->has_alpha = 1;
+}
+
+EAPI void
+evas_common_gradient2_fill_transform_set(RGBA_Gradient2 *gr, Evas_Common_Transform *t)
+{
+   if (!gr) return;
+   if (!t)
+     {
+       gr->fill.transform.mxx = 1;  gr->fill.transform.mxy = 0;  gr->fill.transform.mxz = 0;
+       gr->fill.transform.myx = 0;  gr->fill.transform.myy = 1;  gr->fill.transform.myz = 0;
+       gr->fill.transform.mzx = 1;  gr->fill.transform.mzy = 0;  gr->fill.transform.mzz = 1;
+       return;
+     }
+   gr->fill.transform.mxx = t->mxx;  gr->fill.transform.mxy = t->mxy;  gr->fill.transform.mxz = t->mxz;
+   gr->fill.transform.myx = t->myx;  gr->fill.transform.myy = t->myy;  gr->fill.transform.myz = t->myz;
+   gr->fill.transform.mzx = t->mzx;  gr->fill.transform.mzy = t->mzy;  gr->fill.transform.mzz = t->mzz;
+}
+
+EAPI void
+evas_common_gradient2_fill_spread_set(RGBA_Gradient2 *gr, int spread)
+{
+   if (!gr) return;
+   gr->fill.spread = spread;
+}
+
+EAPI void
+evas_common_gradient2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
+                          int x, int y, int w, int h, RGBA_Gradient2 *gr)
+{
+   Gfx_Func_Gradient2_Fill   gfunc;
+   RGBA_Gfx_Func            bfunc;
+   int             len;
+   int             xin, yin, xoff, yoff;
+   int             clx, cly, clw, clh;
+   DATA32          *pdst, *dst_end, *buf, *map;
+   RGBA_Image      *argb_buf = NULL, *alpha_buf = NULL;
+   DATA8           *mask = NULL;
+   void            *gdata;
+   int             direct_copy = 0, buf_step = 0;
+
+   if (!dst || !dc || !gr || !dst || !dst->image.data)
+       return;
+   if (!gr->map.data || !gr->type.geometer)
+       return;
+   if ((w < 1) || (h < 1))
+       return;
+   clx = 0;  cly = 0;  clw = dst->cache_entry.w;  clh = dst->cache_entry.h;
+   if ((clw < 1) || (clh < 1))  return;
+
+   if (dc->clip.use)
+     RECTS_CLIP_TO_RECT(clx,cly,clw,clh, dc->clip.x,dc->clip.y,dc->clip.w,dc->clip.h);
+   if ((clw < 1) || (clh < 1))  return;
+
+   xin = x;  yin = y;
+   RECTS_CLIP_TO_RECT(x,y,w,h, clx,cly,clw,clh);
+   if ((w < 1) || (h < 1))  return;
+
+   xoff = (x - xin);
+   yoff = (y - yin);
+
+   if (!gr->type.geometer->has_mask(gr, dc->render_op))
+     {
+       if ((dc->render_op == _EVAS_RENDER_FILL) ||
+             (dc->render_op == _EVAS_RENDER_COPY))
+         {
+            direct_copy = 1;  buf_step = dst->cache_entry.w;
+            if (gr->type.geometer->has_alpha(gr, dc->render_op))
+               dst->cache_entry.flags.alpha = 1;
+         }
+       else if ((dc->render_op == _EVAS_RENDER_BLEND) &&
+                 !gr->type.geometer->has_alpha(gr, dc->render_op))
+         {
+            direct_copy = 1;  buf_step = dst->cache_entry.w;
+         }
+     }
+   if (!direct_copy)
+     {
+       argb_buf = evas_common_image_line_buffer_obtain(w);
+       if (!argb_buf)
+          return;
+       argb_buf->cache_entry.flags.alpha = gr->type.geometer->has_alpha(gr, dc->render_op) ? 1 : 0;
+
+       if (gr->type.geometer->has_mask(gr, dc->render_op))
+         {
+           alpha_buf = evas_common_image_alpha_line_buffer_obtain(w);
+           if (!alpha_buf)
+             {
+               evas_common_image_line_buffer_release(argb_buf);
+               return;
+             }
+           bfunc = evas_common_gfx_func_composite_pixel_mask_span_get(argb_buf, dst, w, dc->render_op);
+         }
+       else
+          bfunc = evas_common_gfx_func_composite_pixel_span_get(argb_buf, dst, w, dc->render_op);
+     }
+
+   gfunc = gr->type.geometer->get_fill_func(gr, dc->render_op);
+   gdata = gr->type.gdata;
+   if (!gdata)
+     {
+       if (!direct_copy)
+         {
+           evas_common_image_line_buffer_release(argb_buf);
+           if (alpha_buf)
+               evas_common_image_alpha_line_buffer_release(alpha_buf);
+         }
+       return;
+     }
+
+   map = gr->map.data;
+   len = gr->map.len;
+   pdst = dst->image.data + (y * dst->cache_entry.w) + x;
+   dst_end = pdst + (h * dst->cache_entry.w);
+   if (!direct_copy)
+     {
+       buf = argb_buf->image.data;
+       if (alpha_buf)
+          mask = (DATA8 *)alpha_buf->image.data;
+     }
+   else
+       buf = pdst;
+
+   while (pdst < dst_end)
+     {
+#ifdef EVAS_SLI
+       if ((y % dc->sli.h) == dc->sli.y)
+#endif
+         {
+            gfunc(map, len, buf, mask, w, xoff, yoff, gdata);
+            if (!direct_copy)
+              bfunc(buf, mask, 0, pdst, w);
+         }
+       buf += buf_step;
+       pdst += dst->cache_entry.w;
+       yoff++;
+#ifdef EVAS_SLI
+       y++;
+#endif
+     }
+
+   if (!direct_copy)
+     {
+       evas_common_image_line_buffer_release(argb_buf);
+       if (alpha_buf)
+          evas_common_image_alpha_line_buffer_release(alpha_buf);
+     }
+   evas_common_cpu_end_opt();
+}
+
+static void
+_evas_common_gradient2_stops_scale(RGBA_Gradient2 *gr)
+{
+   Evas_Object_List  *l;
+   RGBA_Gradient2_Color_Np_Stop  *gc, *gc_next;
+   double  scale;
+   int  len;
+
+   if (!gr || !gr->stops.stops) return;
+
+   scale = 1.0;
+   gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
+   l = gr->stops.stops->next;
+   while (l)
+     {
+       double dp;
+
+       gc_next = (RGBA_Gradient2_Color_Np_Stop *)l;
+       dp = gc_next->pos - gc->pos;
+       if (dp > 0.000030517)
+           scale = MIN(scale, dp);
+       gc = gc_next;
+       l = l->next;
+    }
+
+   scale = 2.0 / scale;
+   len = 1;
+   gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
+   l = gr->stops.stops->next;
+   while (l)
+     {
+       int dist;
+
+       gc_next = (RGBA_Gradient2_Color_Np_Stop *)l;
+       dist = 0.5 + (scale * (gc_next->pos - gc->pos));
+       if (dist < 1)
+          dist = 1;
+       len += dist;
+       gc->dist = dist;
+       gc = gc_next;
+       l = l->next;
+     }
+
+   if (len > 65535)
+       len = 65535;
+   gr->stops.len = len;
+}
+
+static void
+_evas_common_gradient2_map_argb(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len)
+{
+   if (!gr || !dc)
+       return;
+   if ((len < 1) || (len > 65535))
+     {
+       if (gr->map.data)
+          free(gr->map.data);
+       gr->map.data = NULL;
+       gr->map.len = 0;
+       return;
+     }
+   if ((len != gr->map.len) || (!gr->map.data))
+       gr->map.data = realloc(gr->map.data, len * sizeof(DATA32));
+   if (!gr->map.data)
+     { gr->map.len = 0; return; }
+   gr->map.len = len;
+   gr->map.has_alpha = gr->has_alpha;
+
+   if (!gr->stops.stops) return;
+
+   _evas_common_gradient2_stops_scale(gr);
+
+     {
+       Evas_Object_List  *lc;
+       RGBA_Gradient2_Color_Np_Stop  *gc, *gc_next;
+       DATA32  *pmap, *map_end;
+       DATA8   *pamap = NULL;
+       int   i, dii;
+       int   r, g, b, a;
+       int   next_r, next_g, next_b, next_a;
+       int   rr, drr, gg, dgg, bb, dbb, aa, daa;
+
+       gr->stops.cdata = realloc(gr->stops.cdata, gr->stops.len * sizeof(DATA32));
+       if (!gr->stops.cdata)  return;
+       pmap = gr->stops.cdata;  map_end = pmap + gr->stops.len;
+
+       if (gr->has_alpha)
+         {
+           gr->stops.adata = realloc(gr->stops.adata, gr->stops.len * sizeof(DATA8));
+           if (!gr->stops.adata)
+             { free(gr->stops.cdata);  gr->stops.cdata = NULL;  return; }
+           pamap = gr->stops.adata;
+         }
+
+       gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
+       r = gc->r;  g = gc->g;  b = gc->b;  a = gc->a;
+       lc = gr->stops.stops->next;
+
+       while (pmap < map_end)
+         {
+           if (lc)
+             {
+               i = gc->dist;
+               dii = 65536 / i;
+               gc_next = (RGBA_Gradient2_Color_Np_Stop *)lc;
+               next_r = gc_next->r;  next_g = gc_next->g;  next_b = gc_next->b;  next_a = gc_next->a;
+               rr = r << 16;  drr = ((next_r - r) * dii);
+               gg = g << 16;  dgg = ((next_g - g) * dii);
+               bb = b << 16;  dbb = ((next_b - b) * dii);
+               aa = a << 16;  daa = ((next_a - a) * dii);
+               while (i--)
+                 {
+                   r = rr >> 16;  r += (rr - (r << 16)) >> 15;
+                   g = gg >> 16;  g += (gg - (g << 16)) >> 15;
+                   b = bb >> 16;  b += (bb - (b << 16)) >> 15;
+                   *pmap++ = 0xff000000 + RGB_JOIN(r,g,b);
+                   if (pamap)
+                     {
+                       a = aa >> 16;  a += (aa - (a << 16)) >> 15;
+                       *pamap++ = a;
+                       aa += daa;
+                     }
+                   rr += drr;  gg += dgg;  bb += dbb;
+                 }
+               gc = gc_next;
+               r = next_r;  g = next_g;  b = next_b;  a = next_a;
+               lc = lc->next;
+              }
+           else
+             {
+               *pmap++ = 0xff000000 + RGB_JOIN(gc->r,gc->g,gc->b);
+               if (pamap) *pamap++ = gc->a;
+             }
+         }
+     }
+
+   if (gr->stops.cdata && gr->stops.adata)
+     {
+       evas_common_scale_rgba_a8_span(gr->stops.cdata, gr->stops.adata, gr->stops.len,
+                                       dc->mul.col, gr->map.data, gr->map.len, 1);
+       return;
+     }
+
+   evas_common_scale_rgba_span(gr->stops.cdata, NULL, gr->stops.len,
+                               dc->mul.col, gr->map.data, gr->map.len, 1);
+   gr->map.has_alpha |= (!!(255 - (dc->mul.col >> 24)));
+}
+
+static void
+_evas_common_gradient2_map_ahsv(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len)
+{
+   if (!gr || !dc)
+       return;
+   if ((len < 1) || (len > 65535))
+     {
+       if (gr->map.data)
+          free(gr->map.data);
+       gr->map.data = NULL;
+       gr->map.len = 0;
+       return;
+     }
+   if ((len != gr->map.len) || (!gr->map.data))
+       gr->map.data = realloc(gr->map.data, len * sizeof(DATA32));
+   if (!gr->map.data)
+     { gr->map.len = 0; return; }
+   gr->map.len = len;
+   gr->map.has_alpha = gr->has_alpha;
+
+   if (!gr->stops.stops) return;
+
+   _evas_common_gradient2_stops_scale(gr);
+
+     {
+       Evas_Object_List  *lc;
+       RGBA_Gradient2_Color_Np_Stop  *gc, *gc_next;
+       DATA32  *pmap, *map_end;
+       DATA8   *pamap = NULL;
+       int   i, dii;
+       int   h, s, v;
+       int   next_h, next_s, next_v;
+       int   hh, dhh, ss, dss, vv, dvv, aa, daa;
+       int   r, g, b, a;
+       int   next_r, next_g, next_b, next_a;
+
+       gr->stops.cdata = realloc(gr->stops.cdata, gr->stops.len * sizeof(DATA32));
+       if (!gr->stops.cdata)  return;
+       pmap = gr->stops.cdata;  map_end = pmap + gr->stops.len;
+
+       if (gr->has_alpha)
+         {
+           gr->stops.adata = realloc(gr->stops.adata, gr->stops.len * sizeof(DATA8));
+           if (!gr->stops.adata)
+             { free(gr->stops.cdata);  gr->stops.cdata = NULL;  return; }
+           pamap = gr->stops.adata;
+         }
+
+       gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
+       r = gc->r;  g = gc->g;  b = gc->b;  a = gc->a;
+       evas_common_convert_color_rgb_to_hsv_int(r, g, b, &h, &s, &v);
+       lc = gr->stops.stops->next;
+
+       while (pmap < map_end)
+         {
+           if (lc)
+             {
+               i = gc->dist;
+               dii = 65536 / i;
+               gc_next = (RGBA_Gradient2_Color_Np_Stop *)lc;
+
+               next_r = gc_next->r;  next_g = gc_next->g;  next_b = gc_next->b;  next_a = gc_next->a;
+               evas_common_convert_color_rgb_to_hsv_int(next_r, next_g, next_b,
+                                                        &next_h, &next_s, &next_v);
+               hh = h << 16;  dhh = ((next_h - h) * dii);
+               ss = s << 16;  dss = ((next_s - s) * dii);
+               vv = v << 16;  dvv = ((next_v - v) * dii);
+               aa = a << 16;  daa = ((next_a - a) * dii);
+               while (i--)
+                 {
+                   h = hh >> 16;  h += (hh - (h << 16)) >> 15;
+                   s = ss >> 16;  s += (ss - (s << 16)) >> 15;
+                   v = vv >> 16;  v += (vv - (v << 16)) >> 15;
+                   evas_common_convert_color_hsv_to_rgb_int(h, s, v, &r, &g, &b);
+                   *pmap++ = 0xff000000 + RGB_JOIN(r,g,b);
+                   if (pamap)
+                     {
+                       a = aa >> 16;  a += (aa - (a << 16)) >> 15;
+                       *pamap++ = a;
+                       aa += daa;
+                     }
+                   hh += dhh;  ss += dss;  vv += dvv;
+                 }
+               gc = gc_next;
+               h = next_h;  s = next_s;  v = next_v;  a = next_a;
+               lc = lc->next;
+              }
+           else
+             {
+               *pmap++ = 0xff000000 + RGB_JOIN(gc->r,gc->g,gc->b);
+               if (pamap) *pamap++ = gc->a;
+             }
+         }
+     }
+
+   if (gr->stops.cdata && gr->stops.adata)
+     {
+       evas_common_scale_hsva_a8_span(gr->stops.cdata, gr->stops.adata, gr->stops.len,
+                                          dc->mul.col, gr->map.data, gr->map.len, 1);
+       return;
+     }
+   evas_common_scale_hsva_span(gr->stops.cdata, NULL, gr->stops.len,
+                               dc->mul.col, gr->map.data, gr->map.len, 1);
+   gr->map.has_alpha |= (!!(255 - (dc->mul.col >> 24)));
+}
+
+EAPI void
+evas_common_gradient2_map(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len)
+{
+   if (!gr || !dc) return;
+   if (dc->interpolation.color_space == _EVAS_COLOR_SPACE_AHSV)
+     {
+       _evas_common_gradient2_map_ahsv(dc, gr, len);
+       return;
+     }
+   _evas_common_gradient2_map_argb(dc, gr, len);
+}
diff --git a/src/lib/engines/common/evas_gradient2_radial.c b/src/lib/engines/common/evas_gradient2_radial.c
new file mode 100644 (file)
index 0000000..7a4601d
--- /dev/null
@@ -0,0 +1,452 @@
+#include "evas_common.h"
+#include "evas_private.h"
+#include <math.h>
+
+
+typedef struct _Radial_Data   Radial_Data;
+
+struct _Radial_Data
+{
+   int    axx, axy, axz;
+   int    ayx, ayy, ayz;
+   float  cx, cy, rx, ry;
+   float  cx0, cy0;
+   int    len;
+};
+
+
+static void 
+radial_init(void);
+
+static void 
+radial_shutdown(void);
+
+static void 
+radial_init_geom(RGBA_Gradient2 *gr);
+
+static void 
+radial_update_geom(RGBA_Gradient2 *gr);
+
+static void 
+radial_free_geom(void *gdata);
+
+static int 
+radial_has_alpha(RGBA_Gradient2 *gr, int op);
+
+static int 
+radial_has_mask(RGBA_Gradient2 *gr, int op);
+
+static int 
+radial_get_map_len(RGBA_Gradient2 *gr);
+
+static Gfx_Func_Gradient2_Fill 
+radial_get_fill_func(RGBA_Gradient2 *gr, int op);
+
+static RGBA_Gradient2_Type  radial = {"radial", radial_init, radial_shutdown,
+                                     radial_init_geom,
+                                     radial_update_geom, radial_free_geom,
+                                     radial_has_alpha, radial_has_mask,
+                                     radial_get_map_len, radial_get_fill_func};
+
+
+EAPI RGBA_Gradient2_Type  *
+evas_common_gradient2_type_radial_get(void)
+{
+    return &radial;
+}
+
+EAPI RGBA_Gradient2 *
+evas_common_gradient2_radial_new(void)
+{
+   RGBA_Gradient2 *gr;
+
+   gr = calloc(1, sizeof(RGBA_Gradient2));
+   if (!gr) return NULL;
+   gr->references = 1;
+   gr->type.id = MAGIC_OBJ_GRADIENT_RADIAL;
+   gr->type.geometer = &radial;
+   radial_init_geom(gr);
+   return gr;
+}
+
+EAPI void
+evas_common_gradient2_radial_fill_set(RGBA_Gradient2 *gr, float cx, float cy, float rx, float ry)
+{
+   Radial_Data *radial_data;
+
+   if (!gr) return;
+   if (gr->type.id != MAGIC_OBJ_GRADIENT_RADIAL) return;
+   if (gr->type.geometer != &radial) return;
+   radial_data = (Radial_Data *)gr->type.gdata;
+   if (!radial_data) return;
+   radial_data->cx = cx;  radial_data->cy = cy;
+   radial_data->rx = rx;  radial_data->ry = ry;
+}
+
+
+/** internal functions **/
+
+static void
+radial_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                          int x, int y, void *params_data);
+
+static void
+radial_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                         int x, int y, void *params_data);
+
+static void
+radial_restrict_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                                int x, int y, void *params_data);
+
+static void
+radial_restrict_masked_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                                int x, int y, void *params_data);
+
+static void
+radial_pad_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                      int x, int y, void *params_data);
+
+
+static void 
+radial_init(void)
+{
+}
+
+static void 
+radial_shutdown(void)
+{
+}
+
+static void 
+radial_free_geom(void *gdata)
+{
+   Radial_Data *data = (Radial_Data *)gdata;
+   if (data) free(data);
+}
+
+static void
+radial_init_geom(RGBA_Gradient2 *gr)
+{
+   Radial_Data   *radial_data;
+
+   if (!gr || (gr->type.geometer != &radial)) return;
+
+   radial_data = (Radial_Data *)gr->type.gdata;
+   if (!radial_data)
+     {
+       radial_data = calloc(1, sizeof(Radial_Data));
+       if (!radial_data)  return;
+       radial_data->cx = radial_data->cy = 0;
+       radial_data->rx = radial_data->ry = 0;
+       radial_data->axx = 65536;  radial_data->axy = 0;  radial_data->axz = 0;
+       radial_data->ayx = 0;  radial_data->ayy = 65536;  radial_data->ayz = 0;
+       radial_data->len = 0;
+    }
+   gr->type.gdata = radial_data;
+}
+
+static void 
+radial_update_geom(RGBA_Gradient2 *gr)
+{
+   Radial_Data   *radial_data;
+   double f, flen;
+   int len;
+   float  fx1, fy1;
+
+   if (!gr || (gr->type.geometer != &radial)) return;
+
+   radial_data = (Radial_Data *)gr->type.gdata;
+   if (!radial_data) return;
+
+   radial_data->len = 0;
+   f = (gr->fill.transform.mxx * gr->fill.transform.myy) - (gr->fill.transform.mxy * gr->fill.transform.myx);
+   if (!f) return;
+
+   f = 1.0 / f;
+   radial_data->cx0 = (((gr->fill.transform.myy * radial_data->cx) - (gr->fill.transform.mxy * radial_data->cy)) * f) - gr->fill.transform.mxz;
+   radial_data->cy0 = ((-(gr->fill.transform.myx * radial_data->cx) + (gr->fill.transform.mxx * radial_data->cy)) * f) - gr->fill.transform.myz;
+
+   fx1 = (((gr->fill.transform.myy * (radial_data->cx + radial_data->rx)) - (gr->fill.transform.mxy * (radial_data->cy))) * f)  - gr->fill.transform.mxz;
+   fy1 = ((-(gr->fill.transform.myx * (radial_data->cx + radial_data->rx)) + (gr->fill.transform.mxx * (radial_data->cy))) * f) - gr->fill.transform.myz;
+
+   flen = hypot(radial_data->cx0 - fx1, radial_data->cy0 - fy1);
+
+   fx1 = (((gr->fill.transform.myy * (radial_data->cx)) - (gr->fill.transform.mxy * (radial_data->cy + radial_data->ry))) * f)  - gr->fill.transform.mxz;
+   fy1 = ((-(gr->fill.transform.myx * (radial_data->cx)) + (gr->fill.transform.mxx * (radial_data->cy + radial_data->ry))) * f) - gr->fill.transform.myz;
+
+   flen = MAX(flen,hypot(radial_data->cx0 - fx1, radial_data->cy0 - fy1));
+   radial_data->len = len = flen;
+   if (!len) return;
+
+   radial_data->axx = (((double)gr->fill.transform.mxx * 65536) * flen) / radial_data->rx;
+   radial_data->axy = (((double)gr->fill.transform.mxy * 65536) * flen) / radial_data->rx;
+   radial_data->axz = (((double)gr->fill.transform.mxz * 65536) * flen) / radial_data->rx;
+   radial_data->ayx = (((double)gr->fill.transform.myx * 65536) * flen) / radial_data->ry;
+   radial_data->ayy = (((double)gr->fill.transform.myy * 65536) * flen) / radial_data->ry;
+   radial_data->ayz = (((double)gr->fill.transform.myz * 65536) * flen) / radial_data->ry;
+}
+
+static int
+radial_has_alpha(RGBA_Gradient2 *gr, int op)
+{
+   Radial_Data   *radial_data;
+
+   if (!gr || (gr->type.geometer != &radial)) return 0;
+   if (gr->has_alpha | gr->map.has_alpha)
+       return 1;
+   if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) || 
+         (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
+       return 0;
+   radial_data = (Radial_Data *)gr->type.gdata;
+   if (!radial_data) return 0;
+   if (gr->fill.spread == _EVAS_TEXTURE_RESTRICT)
+       return 1;
+   return 0;
+}
+
+static int
+radial_has_mask(RGBA_Gradient2 *gr, int op)
+{
+   Radial_Data   *radial_data;
+
+   if (!gr || (gr->type.geometer != &radial)) return 0;
+   if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) || 
+         (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
+     {
+       radial_data = (Radial_Data *)gr->type.gdata;
+       if (!radial_data) return 0;
+       if (gr->fill.spread == _EVAS_TEXTURE_RESTRICT)
+           return 1;
+     }
+   return 0;
+}
+
+static int
+radial_get_map_len(RGBA_Gradient2 *gr)
+{
+   Radial_Data   *radial_data;
+
+   if (!gr || (gr->type.geometer != &radial)) return 0;
+   radial_data = (Radial_Data *)gr->type.gdata;
+   if (!radial_data) return 0;
+   return radial_data->len;
+}
+
+static Gfx_Func_Gradient2_Fill
+radial_get_fill_func(RGBA_Gradient2 *gr, int op)
+{
+   Radial_Data   *radial_data;
+   Gfx_Func_Gradient2_Fill  sfunc = NULL;
+   int masked_op = 0;
+
+   if (!gr || (gr->type.geometer != &radial)) return sfunc;
+   radial_data = (Radial_Data *)gr->type.gdata;
+   if (!radial_data) return sfunc;
+
+   if ( (op == _EVAS_RENDER_COPY) || (op == _EVAS_RENDER_COPY_REL) || 
+         (op == _EVAS_RENDER_MASK) || (op == _EVAS_RENDER_MUL) )
+       masked_op = 1;
+
+   switch (gr->fill.spread)
+     {
+      case _EVAS_TEXTURE_REPEAT:
+       sfunc = radial_repeat_aa;
+      break;
+      case _EVAS_TEXTURE_REFLECT:
+       sfunc = radial_reflect_aa;
+      break;
+      case _EVAS_TEXTURE_RESTRICT:
+       if (masked_op)
+          sfunc = radial_restrict_masked_aa;
+       else
+          sfunc = radial_restrict_aa;
+      break;
+      case _EVAS_TEXTURE_PAD:
+       sfunc = radial_pad_aa;
+      break;
+      default:
+       sfunc = radial_repeat_aa;
+      break;
+     }
+   return sfunc;
+}
+
+
+static void
+radial_repeat_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                 int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Radial_Data  *gdata = (Radial_Data *)params_data;
+   int  xx, yy;
+
+   evas_common_cpu_end_opt();
+   xx = (gdata->axx * (x - gdata->cx0 + 0.5)) + (gdata->axy * (y - gdata->cy0 + 0.5)) + gdata->axz;
+   yy = (gdata->ayx * (x - gdata->cx0 + 0.5)) + (gdata->ayy * (y - gdata->cy0 + 0.5)) + gdata->ayz;
+
+   while (dst < dst_end)
+     {
+       unsigned int  ll = hypot(xx, yy);
+       unsigned int  l = (ll >> 16);
+       int  a = 1 + ((ll & 0xffff) >> 8);
+
+       if (l > (src_len - 1))
+           l = l % src_len;
+       *dst = src[l];
+       if (l + 1 < src_len)
+         {
+           *dst = INTERP_256(a, src[l + 1], *dst);
+         }
+       if (l == (src_len - 1))
+         {
+           *dst = INTERP_256(a, src[0], *dst);
+         }
+       dst++;  xx += gdata->axx;  yy += gdata->ayx;
+     }
+}
+
+
+static void
+radial_reflect_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                  int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Radial_Data  *gdata = (Radial_Data *)params_data;
+   int  xx, yy;
+
+   evas_common_cpu_end_opt();
+   xx = (gdata->axx * (x - gdata->cx0 + 0.5)) + (gdata->axy * (y - gdata->cy0 + 0.5)) + gdata->axz;
+   yy = (gdata->ayx * (x - gdata->cx0 + 0.5)) + (gdata->ayy * (y - gdata->cy0 + 0.5)) + gdata->ayz;
+
+   while (dst < dst_end)
+     {
+       unsigned int  ll = hypot(xx, yy);
+       unsigned int  l = (ll >> 16);
+       int  a = 1 + ((ll & 0xffff) >> 8);
+
+       if (l >= src_len)
+         {
+           int  m = (l % (2 * src_len));
+
+           l = (l % src_len);
+           if (m >= src_len)
+             { l = src_len - l - 1;  a = 257 - a; }
+         }
+       *dst = src[l];
+       if (l + 1 < src_len)
+           *dst = INTERP_256(a, src[l + 1], *dst);
+
+       dst++;  xx += gdata->axx;  yy += gdata->ayx;
+     }
+}
+
+
+static void
+radial_restrict_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                   int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Radial_Data  *gdata = (Radial_Data *)params_data;
+   int  xx, yy;
+
+   evas_common_cpu_end_opt();
+   xx = (gdata->axx * (x - gdata->cx0 + 0.5)) + (gdata->axy * (y - gdata->cy0 + 0.5)) + gdata->axz;
+   yy = (gdata->ayx * (x - gdata->cx0 + 0.5)) + (gdata->ayy * (y - gdata->cy0 + 0.5)) + gdata->ayz;
+
+   while (dst < dst_end)
+     {
+       unsigned int  ll = hypot(xx, yy);
+       unsigned int  l = (ll >> 16);
+
+       *dst = 0;
+       if (l < src_len)
+         {
+           int a = 1 + ((ll & 0xffff) >> 8);
+
+           *dst = src[l];
+           if (l + 1 < src_len)
+               *dst = INTERP_256(a, src[l + 1], *dst);
+           if (l == (src_len - 1))
+             {
+               *dst = INTERP_256(a, src[0], *dst);
+               *dst = MUL_256(257 - a, *dst);
+             }
+         }
+       dst++;  xx += gdata->axx;  yy += gdata->ayx;
+     }
+}
+
+
+static void
+radial_restrict_masked_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+                          int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Radial_Data  *gdata = (Radial_Data *)params_data;
+   int  xx, yy;
+
+   evas_common_cpu_end_opt();
+   xx = (gdata->axx * (x - gdata->cx0 + 0.5)) + (gdata->axy * (y - gdata->cy0 + 0.5)) + gdata->axz;
+   yy = (gdata->ayx * (x - gdata->cx0 + 0.5)) + (gdata->ayy * (y - gdata->cy0 + 0.5)) + gdata->ayz;
+
+   while (dst < dst_end)
+     {
+       unsigned int  ll = hypot(xx, yy);
+       unsigned int  l = (ll >> 16);
+
+       *dst = 0;  *mask = 0;
+       if (l < src_len)
+         {
+           int a = 1 + ((ll & 0xffff) >> 8);
+
+           *dst = src[l];  *mask = 255;
+           if (l + 1 < src_len)
+               *dst = INTERP_256(a, src[l + 1], *dst);
+           if (l == (src_len - 1))
+             {
+               *dst = INTERP_256(a, src[0], *dst);
+               *mask = 256 - a;
+             }
+         }
+       dst++;  mask++;  xx += gdata->axx;  yy += gdata->ayx;
+     }
+}
+
+
+static void
+radial_pad_aa(DATA32 *src, int src_len, DATA32 *dst, DATA8 *mask, int dst_len,
+              int x, int y, void *params_data)
+{
+   DATA32  *dst_end = dst + dst_len;
+   Radial_Data  *gdata = (Radial_Data *)params_data;
+   int  xx, yy;
+
+   evas_common_cpu_end_opt();
+   xx = (gdata->axx * (x - gdata->cx0 + 0.5)) + (gdata->axy * (y - gdata->cy0 + 0.5)) + gdata->axz;
+   yy = (gdata->ayx * (x - gdata->cx0 + 0.5)) + (gdata->ayy * (y - gdata->cy0 + 0.5)) + gdata->ayz;
+
+   while (dst < dst_end)
+     {
+       unsigned int  ll = hypot(xx, yy);
+       unsigned int  l = (ll >> 16);
+
+       *dst = 0;
+       if (l < src_len)
+         {
+           int a = 1 + ((ll & 0xffff) >> 8);
+
+           *dst = src[l];
+           if (l + 1 < src_len)
+               *dst = INTERP_256(a, src[l + 1], src[l]);
+         }
+        if (l == 0)
+          {
+            *dst = src[0];
+          }
+        if (l >= src_len)
+          {
+            *dst = src[src_len - 1];
+          }
+       dst++;  xx += gdata->axx;  yy += gdata->ayx;
+     }
+}
index 5ab156f..2c7e71b 100644 (file)
@@ -437,6 +437,59 @@ evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
    evas_common_pipe_draw_context_copy(dc, op);
 }
 
+/**************** GRAD2 ******************/
+static void
+evas_common_pipe_op_grad2_free(RGBA_Pipe_Op *op)
+{
+   evas_common_gradient2_free(op->op.grad2.grad);
+   evas_common_pipe_op_free(op);
+}
+
+static void
+evas_common_pipe_grad2_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
+{
+   if (info)
+     {
+       RGBA_Draw_Context context;
+       
+       memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
+#ifdef EVAS_SLI
+       evas_common_draw_context_set_sli(&(context), info->y, info->h);
+#else  
+       evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
+#endif 
+       evas_common_gradient2_draw(dst, &(context),
+                                 op->op.grad2.x, op->op.grad2.y,
+                                 op->op.grad2.w, op->op.grad2.h,
+                                 op->op.grad2.grad);
+     }
+   else
+     evas_common_gradient2_draw(dst, &(op->context),
+                              op->op.grad2.x, op->op.grad2.y,
+                              op->op.grad2.w, op->op.grad2.h,
+                              op->op.grad2.grad);
+}
+
+EAPI void
+evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
+                          int x, int y, int w, int h, RGBA_Gradient2 *gr)
+{
+   RGBA_Pipe_Op *op;
+
+   if (!gr) return;
+   dst->pipe = evas_common_pipe_add(dst->pipe, &op);
+   if (!dst->pipe) return;
+   op->op.grad2.x = x;
+   op->op.grad2.y = y;
+   op->op.grad2.w = w;
+   op->op.grad2.h = h;
+   gr->references++;
+   op->op.grad2.grad = gr;
+   op->op_func = evas_common_pipe_grad2_draw_do;
+   op->free_func = evas_common_pipe_op_grad2_free;
+   evas_common_pipe_draw_context_copy(dc, op);
+}
+
 /**************** TEXT ******************/
 static void
 evas_common_pipe_op_text_free(RGBA_Pipe_Op *op)
index fec0d2b..55c1aed 100644 (file)
@@ -13,6 +13,7 @@ EAPI void evas_common_pipe_rectangle_draw(RGBA_Image *dst, RGBA_Draw_Context *dc
 EAPI void evas_common_pipe_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1);
 EAPI void evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points);
 EAPI void evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient *gr);
+EAPI void evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient2 *gr);
 EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text);
 EAPI void evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int smooth, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h);
 
index 9d71e3c..7c8f1aa 100644 (file)
@@ -145,6 +145,9 @@ typedef struct _RGBA_Gradient         RGBA_Gradient;
 typedef struct _RGBA_Gradient_Color_Stop   RGBA_Gradient_Color_Stop;
 typedef struct _RGBA_Gradient_Alpha_Stop   RGBA_Gradient_Alpha_Stop;
 typedef struct _RGBA_Gradient_Type    RGBA_Gradient_Type;
+typedef struct _RGBA_Gradient2         RGBA_Gradient2;
+typedef struct _RGBA_Gradient2_Type    RGBA_Gradient2_Type;
+typedef struct _RGBA_Gradient2_Color_Np_Stop   RGBA_Gradient2_Color_Np_Stop;
 typedef struct _RGBA_Polygon_Point    RGBA_Polygon_Point;
 typedef struct _RGBA_Font             RGBA_Font;
 typedef struct _RGBA_Font_Int         RGBA_Font_Int;
@@ -161,6 +164,8 @@ typedef struct _Tilebuf                 Tilebuf;
 typedef struct _Tilebuf_Tile            Tilebuf_Tile;
 typedef struct _Tilebuf_Rect           Tilebuf_Rect;
 
+typedef struct _Evas_Common_Transform        Evas_Common_Transform;
+
 /*
 typedef struct _Regionbuf             Regionbuf;
 typedef struct _Regionspan            Regionspan;
@@ -177,6 +182,11 @@ typedef void (*Gfx_Func_Gradient_Fill)(DATA32 *src, int src_len,
                                          int x, int y, int axx, int axy, int ayx, int ayy,
                                          void *geom_data);
 
+typedef void (*Gfx_Func_Gradient2_Fill)(DATA32 *src, int src_len,
+                                         DATA32 *dst, DATA8 *mask, int len,
+                                         int x, int y,
+                                         void *geom_data);
+
 #include "../cache/evas_cache.h"
 
 /*****************************************************************************/
@@ -326,6 +336,13 @@ struct _Cutout_Rects
    int               max;
 };
 
+struct _Evas_Common_Transform
+{
+   float  mxx, mxy, mxz;
+   float  myx, myy, myz;
+   float  mzx, mzy, mzz;
+};
+
 struct _RGBA_Draw_Context
 {
    struct {
@@ -379,6 +396,10 @@ struct _RGBA_Pipe_Op
         int                 x, y, w, h;
       } grad;
       struct {
+        RGBA_Gradient2      *grad;
+        int                 x, y, w, h;
+      } grad2;
+      struct {
         RGBA_Font          *font;
         int                 x, y;
         char               *text;
@@ -515,6 +536,63 @@ struct _RGBA_Gradient_Type
    Gfx_Func_Gradient_Fill  (*get_fill_func)(RGBA_Gradient *gr, int render_op, unsigned char aa);
 };
 
+struct _RGBA_Gradient2_Color_Np_Stop
+{
+   Evas_Object_List  _list_data;
+   int               r, g, b, a;
+   float             pos;
+   int               dist;
+};
+
+struct _RGBA_Gradient2
+{
+   struct
+     {
+       DATA32        *data;
+       int            len;
+       Evas_Bool      has_alpha : 1;
+     } map;
+
+   struct {
+       Evas_Object_List *stops;
+       int               nstops;
+       DATA32           *cdata;
+       DATA8            *adata;
+       int               len;
+   }  stops;
+
+   struct
+     {
+       Evas_Common_Transform  transform;
+       int                    spread;
+     } fill;
+   struct
+     {
+        int                 id;
+       RGBA_Gradient2_Type *geometer;
+       void                *gdata;
+     } type;
+
+   int references;
+
+   Evas_Bool has_alpha : 1;
+};
+
+struct _RGBA_Gradient2_Type
+{
+   const char              *name;
+   void                    (*init)(void);
+   void                    (*shutdown)(void);
+   void                    (*geom_init)(RGBA_Gradient2 *gr);
+   void                    (*geom_update)(RGBA_Gradient2 *gr);
+   void                    (*geom_free)(void *gdata);
+   int                     (*has_alpha)(RGBA_Gradient2 *gr, int render_op);
+   int                     (*has_mask)(RGBA_Gradient2 *gr, int render_op);
+   int                     (*get_map_len)(RGBA_Gradient2 *gr);
+   Gfx_Func_Gradient2_Fill  (*get_fill_func)(RGBA_Gradient2 *gr, int render_op);
+};
+
+
 struct _RGBA_Polygon_Point
 {
    Evas_Object_List  _list_data;
index 3ca0962..8330b52 100644 (file)
@@ -52,6 +52,11 @@ typedef struct _Evas_Rectangles             Evas_Rectangles;
 #define MAGIC_OBJ_SMART     0x71777777
 #define MAGIC_OBJ_TEXTBLOCK 0x71777778
 #define MAGIC_SMART         0x72777770
+#define MAGIC_OBJ_GRADIENT_LINEAR  0x72777771
+#define MAGIC_OBJ_GRADIENT_RADIAL  0x72777772
+#define MAGIC_OBJ_SHAPE  0x72777773
+#define MAGIC_OBJ_CONTAINER  0x72777774
+#define MAGIC_OBJ_CUSTOM  0x72777775
 
 #ifdef MAGIC_DEBUG
 #define MAGIC_CHECK_FAILED(o, t, m) \
@@ -484,6 +489,9 @@ struct _Evas_Object_Func
    void (*render_pre) (Evas_Object *obj);
    void (*render_post) (Evas_Object *obj);
 
+   int  (*visual_id_get) (Evas_Object *obj);
+   void *(*engine_data_get) (Evas_Object *obj);
+
    void (*store) (Evas_Object *obj);
    void (*unstore) (Evas_Object *obj);
 
@@ -544,6 +552,29 @@ struct _Evas_Func
    void *(*polygon_points_clear)           (void *data, void *context, void *polygon);
    void (*polygon_draw)                    (void *data, void *context, void *surface, void *polygon);
 
+   void (*gradient2_color_np_stop_insert)   (void *data, void *gradient, int r, int g, int b, int a, float pos);
+   void (*gradient2_clear)                  (void *data, void *gradient);
+   void (*gradient2_fill_transform_set)     (void *data, void *gradient, void *transform);
+   void (*gradient2_fill_spread_set)        (void *data, void *gradient, int spread);
+
+   void *(*gradient2_linear_new)                   (void *data);
+   void (*gradient2_linear_free)                   (void *data, void *linear_gradient);
+   void (*gradient2_linear_fill_set)               (void *data, void *linear_gradient, float x0, float y0, float x1, float y1);
+   int  (*gradient2_linear_is_opaque)              (void *data, void *context, void *linear_gradient, int x, int y, int w, int h);
+   int  (*gradient2_linear_is_visible)             (void *data, void *context, void *linear_gradient, int x, int y, int w, int h);
+   void (*gradient2_linear_render_pre)             (void *data, void *context, void *linear_gradient);
+   void (*gradient2_linear_render_post)            (void *data, void *linear_gradient);
+   void (*gradient2_linear_draw)                   (void *data, void *context, void *surface, void *linear_gradient, int x, int y, int w, int h);
+
+   void *(*gradient2_radial_new)                   (void *data);
+   void (*gradient2_radial_free)                   (void *data, void *radial_gradient);
+   void (*gradient2_radial_fill_set)               (void *data, void *radial_gradient, float cx, float cy, float rx, float ry);
+   int  (*gradient2_radial_is_opaque)              (void *data, void *context, void *radial_gradient, int x, int y, int w, int h);
+   int  (*gradient2_radial_is_visible)             (void *data, void *context, void *radial_gradient, int x, int y, int w, int h);
+   void (*gradient2_radial_render_pre)             (void *data, void *context, void *radial_gradient);
+   void (*gradient2_radial_render_post)            (void *data, void *radial_gradient);
+   void (*gradient2_radial_draw)                   (void *data, void *context, void *surface, void *radial_gradient, int x, int y, int w, int h);
+
    void *(*gradient_new)                   (void *data);
    void (*gradient_free)                   (void *data, void *gradient);
    void (*gradient_color_stop_add)         (void *data, void *gradient, int r, int g, int b, int a, int delta);
index a236a53..4b2450f 100644 (file)
@@ -375,6 +375,113 @@ eng_polygon_draw(void *data, void *context, void *surface, void *polygon)
    evas_gl_common_poly_draw(re->win->gl_context, polygon);
 }
 
+static void
+eng_gradient2_color_np_stop_insert(void *data, void *gradient, int r, int g, int b, int a, float pos)
+{
+}
+
+static void
+eng_gradient2_clear(void *data, void *gradient)
+{
+}
+
+static void
+eng_gradient2_fill_transform_set(void *data, void *gradient, void *transform)
+{
+}
+
+static void
+eng_gradient2_fill_spread_set
+(void *data, void *gradient, int spread)
+{
+}
+
+static void *
+eng_gradient2_linear_new(void *data)
+{
+   return NULL;
+}
+
+static void
+eng_gradient2_linear_free(void *data, void *linear_gradient)
+{
+}
+
+static void
+eng_gradient2_linear_fill_set(void *data, void *linear_gradient, int x0, int y0, int x1, int y1)
+{
+}
+
+static int
+eng_gradient2_linear_is_opaque(void *data, void *context, void *linear_gradient, int x, int y, int w, int h)
+{
+   return 1;
+}
+
+static int
+eng_gradient2_linear_is_visible(void *data, void *context, void *linear_gradient, int x, int y, int w, int h)
+{
+   return 1;
+}
+
+static void
+eng_gradient2_linear_render_pre(void *data, void *context, void *linear_gradient)
+{
+}
+
+static void
+eng_gradient2_linear_render_post(void *data, void *linear_gradient)
+{
+}
+
+static void
+eng_gradient2_linear_draw(void *data, void *context, void *surface, void *linear_gradient, int x, int y, int w, int h)
+{
+}
+
+static void *
+eng_gradient2_radial_new(void *data)
+{
+   return NULL;
+}
+
+static void
+eng_gradient2_radial_free(void *data, void *radial_gradient)
+{
+}
+
+static void
+eng_gradient2_radial_fill_set(void *data, void *radial_gradient, float cx, float cy, float rx, float ry)
+{
+}
+
+static int
+eng_gradient2_radial_is_opaque(void *data, void *context, void *radial_gradient, int x, int y, int w, int h)
+{
+   return 1;
+}
+
+static int
+eng_gradient2_radial_is_visible(void *data, void *context, void *radial_gradient, int x, int y, int w, int h)
+{
+   return 1;
+}
+
+static void
+eng_gradient2_radial_render_pre(void *data, void *context, void *radial_gradient)
+{
+}
+
+static void
+eng_gradient2_radial_render_post(void *data, void *radial_gradient)
+{
+}
+
+static void
+eng_gradient2_radial_draw(void *data, void *context, void *surface, void *radial_gradient, int x, int y, int w, int h)
+{
+}
+
 static void *
 eng_gradient_new(void *data)
 {
@@ -966,6 +1073,28 @@ module_open(Evas_Module *em)
    ORD(polygon_point_add);
    ORD(polygon_points_clear);
    ORD(polygon_draw);
+
+   ORD(gradient2_color_np_stop_insert);
+   ORD(gradient2_clear);
+   ORD(gradient2_fill_transform_set);
+   ORD(gradient2_fill_spread_set);
+   ORD(gradient2_linear_new);
+   ORD(gradient2_linear_free);
+   ORD(gradient2_linear_fill_set);
+   ORD(gradient2_linear_is_opaque);
+   ORD(gradient2_linear_is_visible);
+   ORD(gradient2_linear_render_pre);
+   ORD(gradient2_linear_render_post);
+   ORD(gradient2_linear_draw);
+   ORD(gradient2_radial_new);
+   ORD(gradient2_radial_free);
+   ORD(gradient2_radial_fill_set);
+   ORD(gradient2_radial_is_opaque);
+   ORD(gradient2_radial_is_visible);
+   ORD(gradient2_radial_render_pre);
+   ORD(gradient2_radial_render_post);
+   ORD(gradient2_radial_draw);
+
    ORD(gradient_new);
    ORD(gradient_free);
    ORD(gradient_color_stop_add);
index 49749b8..4242b2a 100644 (file)
@@ -193,6 +193,165 @@ eng_polygon_draw(void *data, void *context, void *surface, void *polygon)
      }
 }
 
+static void
+eng_gradient2_color_np_stop_insert(void *data, void *gradient, int r, int g, int b, int a, float pos)
+{
+   evas_common_gradient2_color_np_stop_insert(gradient, r, g, b, a, pos);
+}
+
+static void
+eng_gradient2_clear(void *data, void *gradient)
+{
+   evas_common_gradient2_clear(gradient);
+}
+
+static void
+eng_gradient2_fill_transform_set(void *data, void *gradient, void *transform)
+{
+   evas_common_gradient2_fill_transform_set(gradient, transform);
+}
+
+static void
+eng_gradient2_fill_spread_set
+(void *data, void *gradient, int spread)
+{
+   evas_common_gradient2_fill_spread_set(gradient, spread);
+}
+
+static void *
+eng_gradient2_linear_new(void *data)
+{
+   return evas_common_gradient2_linear_new();
+}
+
+static void
+eng_gradient2_linear_free(void *data, void *linear_gradient)
+{
+   evas_common_gradient2_free(linear_gradient);
+}
+
+static void
+eng_gradient2_linear_fill_set(void *data, void *linear_gradient, float x0, float y0, float x1, float y1)
+{
+   evas_common_gradient2_linear_fill_set(linear_gradient, x0, y0, x1, y1);
+}
+
+static int
+eng_gradient2_linear_is_opaque(void *data, void *context, void *linear_gradient, int x, int y, int w, int h)
+{
+   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
+   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)linear_gradient;
+
+   if (!dc || !gr || !gr->type.geometer)  return 0;
+   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
+              gr->type.geometer->has_mask(gr, dc->render_op));
+}
+
+static int
+eng_gradient2_linear_is_visible(void *data, void *context, void *linear_gradient, int x, int y, int w, int h)
+{
+   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
+
+   if (!dc || !linear_gradient)  return 0;
+   return 1;
+}
+
+static void
+eng_gradient2_linear_render_pre(void *data, void *context, void *linear_gradient)
+{
+   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
+   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)linear_gradient;
+   int  len;
+
+   if (!dc || !gr || !gr->type.geometer)  return;
+   gr->type.geometer->geom_update(gr);
+   len = gr->type.geometer->get_map_len(gr);
+   evas_common_gradient2_map(dc, gr, len);
+}
+
+static void
+eng_gradient2_linear_render_post(void *data, void *linear_gradient)
+{
+}
+
+static void
+eng_gradient2_linear_draw(void *data, void *context, void *surface, void *linear_gradient, int x, int y, int w, int h)
+{
+#ifdef BUILD_PTHREAD
+   if (cpunum > 1)
+     evas_common_pipe_grad2_draw(surface, context, x, y, w, h, linear_gradient);
+   else
+#endif
+     evas_common_gradient2_draw(surface, context, x, y, w, h, linear_gradient);
+}
+
+static void *
+eng_gradient2_radial_new(void *data)
+{
+   return evas_common_gradient2_radial_new();
+}
+
+static void
+eng_gradient2_radial_free(void *data, void *radial_gradient)
+{
+   evas_common_gradient2_free(radial_gradient);
+}
+
+static void
+eng_gradient2_radial_fill_set(void *data, void *radial_gradient, float cx, float cy, float rx, float ry)
+{
+   evas_common_gradient2_radial_fill_set(radial_gradient, cx, cy, rx, ry);
+}
+
+static int
+eng_gradient2_radial_is_opaque(void *data, void *context, void *radial_gradient, int x, int y, int w, int h)
+{
+   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
+   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)radial_gradient;
+
+   if (!dc || !gr || !gr->type.geometer)  return 0;
+   return !(gr->type.geometer->has_alpha(gr, dc->render_op) |
+              gr->type.geometer->has_mask(gr, dc->render_op));
+}
+
+static int
+eng_gradient2_radial_is_visible(void *data, void *context, void *radial_gradient, int x, int y, int w, int h)
+{
+   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
+
+   if (!dc || !radial_gradient)  return 0;
+   return 1;
+}
+
+static void
+eng_gradient2_radial_render_pre(void *data, void *context, void *radial_gradient)
+{
+   RGBA_Draw_Context *dc = (RGBA_Draw_Context *)context;
+   RGBA_Gradient2 *gr = (RGBA_Gradient2 *)radial_gradient;
+   int  len;
+
+   if (!dc || !gr || !gr->type.geometer)  return;
+   gr->type.geometer->geom_update(gr);
+   len = gr->type.geometer->get_map_len(gr);
+   evas_common_gradient2_map(dc, gr, len);
+}
+
+static void
+eng_gradient2_radial_render_post(void *data, void *radial_gradient)
+{
+}
+
+static void
+eng_gradient2_radial_draw(void *data, void *context, void *surface, void *radial_gradient, int x, int y, int w, int h)
+{
+#ifdef BUILD_PTHREAD
+   if (cpunum > 1)
+     evas_common_pipe_grad2_draw(surface, context, x, y, w, h, radial_gradient);
+   else
+#endif
+     evas_common_gradient2_draw(surface, context, x, y, w, h, radial_gradient);
+}
+
 static void *
 eng_gradient_new(void *data)
 {
@@ -799,6 +958,29 @@ static Evas_Func func =
      eng_polygon_points_clear,
      eng_polygon_draw,
      /* gradient draw funcs */
+     eng_gradient2_color_np_stop_insert,
+     eng_gradient2_clear,
+     eng_gradient2_fill_transform_set,
+     eng_gradient2_fill_spread_set,
+
+     eng_gradient2_linear_new,
+     eng_gradient2_linear_free,
+     eng_gradient2_linear_fill_set,
+     eng_gradient2_linear_is_opaque,
+     eng_gradient2_linear_is_visible,
+     eng_gradient2_linear_render_pre,
+     eng_gradient2_linear_render_post,
+     eng_gradient2_linear_draw,
+
+     eng_gradient2_radial_new,
+     eng_gradient2_radial_free,
+     eng_gradient2_radial_fill_set,
+     eng_gradient2_radial_is_opaque,
+     eng_gradient2_radial_is_visible,
+     eng_gradient2_radial_render_pre,
+     eng_gradient2_radial_render_post,
+     eng_gradient2_radial_draw,
+
      eng_gradient_new,
      eng_gradient_free,
      eng_gradient_color_stop_add,
index 9c50db3..31a96fe 100644 (file)
@@ -339,6 +339,114 @@ eng_polygon_draw(void *data, void *context, void *surface, void *polygon)
    _xre_poly_draw((Xrender_Surface *)surface, (RGBA_Draw_Context *)context, (RGBA_Polygon_Point *)polygon);
 }
 
+
+static void
+eng_gradient2_color_np_stop_insert(void *data, void *gradient, int r, int g, int b, int a, float pos)
+{
+}
+
+static void
+eng_gradient2_clear(void *data, void *gradient)
+{
+}
+
+static void
+eng_gradient2_fill_transform_set(void *data, void *gradient, void *transform)
+{
+}
+
+static void
+eng_gradient2_fill_spread_set
+(void *data, void *gradient, int spread)
+{
+}
+
+static void *
+eng_gradient2_linear_new(void *data)
+{
+   return NULL;
+}
+
+static void
+eng_gradient2_linear_free(void *data, void *linear_gradient)
+{
+}
+
+static void
+eng_gradient2_linear_fill_set(void *data, void *linear_gradient, int x0, int y0, int x1, int y1)
+{
+}
+
+static int
+eng_gradient2_linear_is_opaque(void *data, void *context, void *linear_gradient, int x, int y, int w, int h)
+{
+   return 1;
+}
+
+static int
+eng_gradient2_linear_is_visible(void *data, void *context, void *linear_gradient, int x, int y, int w, int h)
+{
+   return 1;
+}
+
+static void
+eng_gradient2_linear_render_pre(void *data, void *context, void *linear_gradient)
+{
+}
+
+static void
+eng_gradient2_linear_render_post(void *data, void *linear_gradient)
+{
+}
+
+static void
+eng_gradient2_linear_draw(void *data, void *context, void *surface, void *linear_gradient, int x, int y, int w, int h)
+{
+}
+
+static void *
+eng_gradient2_radial_new(void *data)
+{
+   return NULL;
+}
+
+static void
+eng_gradient2_radial_free(void *data, void *radial_gradient)
+{
+}
+
+static void
+eng_gradient2_radial_fill_set(void *data, void *radial_gradient, float cx, float cy, float rx, float ry)
+{
+}
+
+static int
+eng_gradient2_radial_is_opaque(void *data, void *context, void *radial_gradient, int x, int y, int w, int h)
+{
+   return 1;
+}
+
+static int
+eng_gradient2_radial_is_visible(void *data, void *context, void *radial_gradient, int x, int y, int w, int h)
+{
+   return 1;
+}
+
+static void
+eng_gradient2_radial_render_pre(void *data, void *context, void *radial_gradient)
+{
+}
+
+static void
+eng_gradient2_radial_render_post(void *data, void *radial_gradient)
+{
+}
+
+static void
+eng_gradient2_radial_draw(void *data, void *context, void *surface, void *radial_gradient, int x, int y, int w, int h)
+{
+}
+
 static void *
 eng_gradient_new(void *data)
 {
@@ -887,6 +995,28 @@ module_open(Evas_Module *em)
    ORD(rectangle_draw);
    ORD(line_draw);
    ORD(polygon_draw);
+
+   ORD(gradient2_color_np_stop_insert);
+   ORD(gradient2_clear);
+   ORD(gradient2_fill_transform_set);
+   ORD(gradient2_fill_spread_set);
+   ORD(gradient2_linear_new);
+   ORD(gradient2_linear_free);
+   ORD(gradient2_linear_fill_set);
+   ORD(gradient2_linear_is_opaque);
+   ORD(gradient2_linear_is_visible);
+   ORD(gradient2_linear_render_pre);
+   ORD(gradient2_linear_render_post);
+   ORD(gradient2_linear_draw);
+   ORD(gradient2_radial_new);
+   ORD(gradient2_radial_free);
+   ORD(gradient2_radial_fill_set);
+   ORD(gradient2_radial_is_opaque);
+   ORD(gradient2_radial_is_visible);
+   ORD(gradient2_radial_render_pre);
+   ORD(gradient2_radial_render_post);
+   ORD(gradient2_radial_draw);
+
    ORD(gradient_new);
    ORD(gradient_free);
    ORD(gradient_color_stop_add);