From: raster Date: Tue, 26 Aug 2008 05:45:04 +0000 (+0000) Subject: jose has some new gradient work - these are his patches. nice work joseg! yes X-Git-Tag: accepted/2.0/20130306.225542~242^2~2818 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7205b9dcf4b3df7f0e83d6bc90f7e6975ddb60c0;p=profile%2Fivi%2Fevas.git jose has some new gradient work - these are his patches. nice work joseg! yes - 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 --- diff --git a/src/lib/Evas.h b/src/lib/Evas.h index 910f392..9ce19df 100644 --- a/src/lib/Evas.h +++ b/src/lib/Evas.h @@ -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); diff --git a/src/lib/canvas/Makefile.am b/src/lib/canvas/Makefile.am index db66ba6..c11f1fc 100644 --- a/src/lib/canvas/Makefile.am +++ b/src/lib/canvas/Makefile.am @@ -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 index 0000000..366cbba --- /dev/null +++ b/src/lib/canvas/evas_object_gradient2.c @@ -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 index 0000000..fd7ffff --- /dev/null +++ b/src/lib/canvas/evas_object_gradient2_linear.c @@ -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 index 0000000..324762e --- /dev/null +++ b/src/lib/canvas/evas_object_gradient2_radial.c @@ -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; +} diff --git a/src/lib/canvas/evas_object_image.c b/src/lib/canvas/evas_object_image.c index 487350c..aa8f72e 100644 --- a/src/lib/canvas/evas_object_image.c +++ b/src/lib/canvas/evas_object_image.c @@ -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) { diff --git a/src/lib/canvas/evas_object_line.c b/src/lib/canvas/evas_object_line.c index 15bf61c..1f6ff0b 100644 --- a/src/lib/canvas/evas_object_line.c +++ b/src/lib/canvas/evas_object_line.c @@ -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) { diff --git a/src/lib/canvas/evas_object_polygon.c b/src/lib/canvas/evas_object_polygon.c index d327a61..35ac120 100644 --- a/src/lib/canvas/evas_object_polygon.c +++ b/src/lib/canvas/evas_object_polygon.c @@ -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) { diff --git a/src/lib/canvas/evas_object_rectangle.c b/src/lib/canvas/evas_object_rectangle.c index 306877b..6264609 100644 --- a/src/lib/canvas/evas_object_rectangle.c +++ b/src/lib/canvas/evas_object_rectangle.c @@ -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) diff --git a/src/lib/canvas/evas_object_smart.c b/src/lib/canvas/evas_object_smart.c index aaffd3e..cc67630 100644 --- a/src/lib/canvas/evas_object_smart.c +++ b/src/lib/canvas/evas_object_smart.c @@ -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; +} diff --git a/src/lib/canvas/evas_object_text.c b/src/lib/canvas/evas_object_text.c index 55a9648..3f9d39d 100644 --- a/src/lib/canvas/evas_object_text.c +++ b/src/lib/canvas/evas_object_text.c @@ -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) { diff --git a/src/lib/canvas/evas_object_textblock.c b/src/lib/canvas/evas_object_textblock.c index baeaa8d..93ac7d8 100644 --- a/src/lib/canvas/evas_object_textblock.c +++ b/src/lib/canvas/evas_object_textblock.c @@ -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) { diff --git a/src/lib/engines/common/Makefile.am b/src/lib/engines/common/Makefile.am index 516caf9..643bc42 100644 --- a/src/lib/engines/common/Makefile.am +++ b/src/lib/engines/common/Makefile.am @@ -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 \ diff --git a/src/lib/engines/common/evas_gradient.h b/src/lib/engines/common/evas_gradient.h index d32d356..50e2cb8 100644 --- a/src/lib/engines/common/evas_gradient.h +++ b/src/lib/engines/common/evas_gradient.h @@ -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 index 0000000..3a829fa --- /dev/null +++ b/src/lib/engines/common/evas_gradient2_linear.c @@ -0,0 +1,723 @@ +#include "evas_common.h" +#include "evas_private.h" +#include + +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 index 0000000..dbd06b9 --- /dev/null +++ b/src/lib/engines/common/evas_gradient2_main.c @@ -0,0 +1,578 @@ +#include "evas_common.h" +#include "evas_blend_private.h" +#include "evas_private.h" +#include + +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 index 0000000..7a4601d --- /dev/null +++ b/src/lib/engines/common/evas_gradient2_radial.c @@ -0,0 +1,452 @@ +#include "evas_common.h" +#include "evas_private.h" +#include + + +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; + } +} diff --git a/src/lib/engines/common/evas_pipe.c b/src/lib/engines/common/evas_pipe.c index 5ab156f..2c7e71b 100644 --- a/src/lib/engines/common/evas_pipe.c +++ b/src/lib/engines/common/evas_pipe.c @@ -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) diff --git a/src/lib/engines/common/evas_pipe.h b/src/lib/engines/common/evas_pipe.h index fec0d2b..55c1aed 100644 --- a/src/lib/engines/common/evas_pipe.h +++ b/src/lib/engines/common/evas_pipe.h @@ -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); diff --git a/src/lib/include/evas_common.h b/src/lib/include/evas_common.h index 9d71e3c..7c8f1aa 100644 --- a/src/lib/include/evas_common.h +++ b/src/lib/include/evas_common.h @@ -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; diff --git a/src/lib/include/evas_private.h b/src/lib/include/evas_private.h index 3ca0962..8330b52 100644 --- a/src/lib/include/evas_private.h +++ b/src/lib/include/evas_private.h @@ -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); diff --git a/src/modules/engines/gl_x11/evas_engine.c b/src/modules/engines/gl_x11/evas_engine.c index a236a53..4b2450f 100644 --- a/src/modules/engines/gl_x11/evas_engine.c +++ b/src/modules/engines/gl_x11/evas_engine.c @@ -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); diff --git a/src/modules/engines/software_generic/evas_engine.c b/src/modules/engines/software_generic/evas_engine.c index 49749b8..4242b2a 100644 --- a/src/modules/engines/software_generic/evas_engine.c +++ b/src/modules/engines/software_generic/evas_engine.c @@ -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, diff --git a/src/modules/engines/xrender_x11/evas_engine.c b/src/modules/engines/xrender_x11/evas_engine.c index 9c50db3..31a96fe 100644 --- a/src/modules/engines/xrender_x11/evas_engine.c +++ b/src/modules/engines/xrender_x11/evas_engine.c @@ -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);