move around - flatter.
[profile/ivi/evas.git] / src / lib / canvas / evas_object_gradient.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #include "evas_common.h"
6 #include "evas_private.h"
7 #include "../engines/common/evas_convert_color.h"
8
9 /* private magic number for gradient objects */
10 static const char o_type[] = "gradient";
11
12 /* private struct for gradient object internal data */
13 typedef struct _Evas_Object_Gradient      Evas_Object_Gradient;
14
15 struct _Evas_Object_Gradient
16 {
17    DATA32            magic;
18
19    struct {
20       struct {
21       Evas_Angle     angle;
22       float          offset;
23       int            direction;
24       } map;
25       struct {
26          Evas_Coord  x, y, w, h;
27          Evas_Angle  angle;
28          int         spread;
29       } fill;
30       struct {
31          char       *name;
32          char       *params;
33       } type;
34       unsigned char    gradient_opaque : 1;
35    } cur, prev;
36
37    void             *engine_data;
38
39    unsigned char     changed : 1;
40    unsigned char     gradient_changed : 1;
41    unsigned char     type_changed : 1;
42 };
43
44 /* private methods for gradient objects */
45 static void evas_object_gradient_init(Evas_Object *obj);
46 static void *evas_object_gradient_new(void);
47 static void evas_object_gradient_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
48 static void evas_object_gradient_free(Evas_Object *obj);
49 static void evas_object_gradient_render_pre(Evas_Object *obj);
50 static void evas_object_gradient_render_post(Evas_Object *obj);
51
52 static int evas_object_gradient_is_opaque(Evas_Object *obj);
53 static int evas_object_gradient_was_opaque(Evas_Object *obj);
54
55 static const Evas_Object_Func object_func =
56 {
57    /* methods (compulsory) */
58    evas_object_gradient_free,
59      evas_object_gradient_render,
60      evas_object_gradient_render_pre,
61      evas_object_gradient_render_post,
62    /* these are optional. NULL = nothing */
63      NULL,
64      NULL,
65      NULL,
66      NULL,
67      evas_object_gradient_is_opaque,
68      evas_object_gradient_was_opaque,
69      NULL,
70      NULL,
71      NULL
72 };
73
74 /* the actual api call to add a gradient */
75
76 /**
77  * @defgroup Evas_Object_Gradient_Group Evas Gradient Object Functions
78  *
79  * Functions that work on evas gradient objects.
80  *
81  * The following example shows how
82  */
83
84 /**
85  * Adds a gradient object to the given evas.
86  * @param   e The given evas.
87  * @return  A new evas gradient object if successful.  Otherwise, @c NULL.
88  * @ingroup Evas_Object_Gradient_Group
89  */
90 EAPI Evas_Object *
91 evas_object_gradient_add(Evas *e)
92 {
93    Evas_Object *obj;
94
95    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
96    return NULL;
97    MAGIC_CHECK_END();
98    obj = evas_object_new();
99    evas_object_gradient_init(obj);
100    evas_object_inject(obj, e);
101    if (obj->object_data)
102      {
103         Evas_Object_Gradient *o = (Evas_Object_Gradient *)(obj->object_data);
104
105         o->engine_data = e->engine.func->gradient_new(e->engine.data.output);
106      }
107    evas_object_change(obj);
108    return obj;
109 }
110
111 /**
112  * Adds a color stop to the given evas gradient object.
113  *
114  * The @p delta parameter determines the proportion of the gradient
115  * object that is to be set to the color.  For instance, if red is
116  * added with @p delta set to 2, and green is added with @p
117  * delta set to 1, two-thirds will be red or reddish and one-third
118  * will be green or greenish.
119  *
120  * Colors are added from the top downwards.
121  *
122  * @param   obj      The given evas gradient object.
123  * @param   r        Red component of the given color.
124  * @param   g        Green component of the given color.
125  * @param   b        Blue component of the given color.
126  * @param   a        Alpha component of the given color.
127  * @param   delta    Proportion of the gradient object that is this color.
128  * @ingroup Evas_Object_Gradient_Group
129  */
130 EAPI void
131 evas_object_gradient_color_stop_add(Evas_Object *obj, int r, int g, int b, int a, int delta)
132 {
133    Evas_Object_Gradient *o;
134
135    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
136    return;
137    MAGIC_CHECK_END();
138    o = (Evas_Object_Gradient *)(obj->object_data);
139    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
140    return;
141    MAGIC_CHECK_END();
142    if (o->engine_data)
143       obj->layer->evas->engine.func->gradient_color_stop_add(obj->layer->evas->engine.data.output,
144                                                              o->engine_data,
145                                                              r, g, b, a, delta);
146    o->gradient_changed = 1;
147    o->changed = 1;
148    evas_object_change(obj);
149 }
150
151 /**
152  * Adds an alpha stop to the given evas gradient object.
153  *
154  * The @p delta parameter determines the proportion of the gradient
155  * object that is to be set to the alpha value.
156  *
157  * Alphas are added from the top downwards.
158  *
159  * @param   obj      The given evas gradient object.
160  * @param   a        Alpha value.
161  * @param   delta    Proportion of the gradient object that is this alpha.
162  * @ingroup Evas_Object_Gradient_Group
163  */
164 EAPI void
165 evas_object_gradient_alpha_stop_add(Evas_Object *obj, int a, int delta)
166 {
167    Evas_Object_Gradient *o;
168
169    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
170    return;
171    MAGIC_CHECK_END();
172    o = (Evas_Object_Gradient *)(obj->object_data);
173    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
174    return;
175    MAGIC_CHECK_END();
176    if (o->engine_data)
177       obj->layer->evas->engine.func->gradient_alpha_stop_add(obj->layer->evas->engine.data.output,
178                                                              o->engine_data, a, delta);
179    o->gradient_changed = 1;
180    o->changed = 1;
181    evas_object_change(obj);
182 }
183
184 /**
185  * Deletes all stops set for the given evas gradient object or any set data.
186  * @param   obj The given evas gradient object.
187  * @ingroup Evas_Object_Gradient_Group
188  */
189 EAPI void
190 evas_object_gradient_clear(Evas_Object *obj)
191 {
192    Evas_Object_Gradient *o;
193
194    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
195    return;
196    MAGIC_CHECK_END();
197    o = (Evas_Object_Gradient *)(obj->object_data);
198    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
199    return;
200    MAGIC_CHECK_END();
201    if (o->engine_data)
202       obj->layer->evas->engine.func->gradient_clear(obj->layer->evas->engine.data.output,
203                                                     o->engine_data);
204    o->gradient_changed = 1;
205    o->changed = 1;
206    o->cur.gradient_opaque = 0;
207    evas_object_change(obj);
208 }
209
210 /**
211  * Sets color data for the given evas gradient object.
212  *
213  * If data is so set, any existing gradient stops will be deleted,
214  * The data is not copied, so if it was allocated, do not free it while it's set.
215  *
216  * @param   obj       The given evas gradient object.
217  * @param   data      The color data to be set. Should be in argb32 pixel format.
218  * @param   len       The length of the data pointer - multiple of the pixel size.
219  * @param   has_alpha A flag indicating if the data has alpha or not.
220  * @ingroup Evas_Object_Gradient_Group
221  */
222 EAPI void
223 evas_object_gradient_color_data_set(Evas_Object *obj, void *data, int len, Evas_Bool has_alpha)
224 {
225    Evas_Object_Gradient *o;
226
227    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
228    return;
229    MAGIC_CHECK_END();
230    o = (Evas_Object_Gradient *)(obj->object_data);
231    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
232    return;
233    MAGIC_CHECK_END();
234    if (o->engine_data)
235         obj->layer->evas->engine.func->gradient_color_data_set(obj->layer->evas->engine.data.output,
236                                                                 o->engine_data,
237                                                                 data, len, has_alpha);
238    o->gradient_changed = 1;
239    o->changed = 1;
240    evas_object_change(obj);
241 }
242
243 /**
244  * Sets alpha data for the given evas gradient object.
245  *
246  * If alpha data is so set, any existing gradient stops will be cleared,
247  * The data is not copied, so if it was allocated, do not free it while it's set.
248  *
249  * @param   obj       The given evas gradient object.
250  * @param   data      The alpha data to be set, in a8 format.
251  * @param   len       The length of the data pointer - multiple of the pixel size.
252  * @ingroup Evas_Object_Gradient_Group
253  */
254 EAPI void
255 evas_object_gradient_alpha_data_set(Evas_Object *obj, void *data, int len)
256 {
257    Evas_Object_Gradient *o;
258
259    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
260    return;
261    MAGIC_CHECK_END();
262    o = (Evas_Object_Gradient *)(obj->object_data);
263    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
264    return;
265    MAGIC_CHECK_END();
266    if (o->engine_data)
267         obj->layer->evas->engine.func->gradient_alpha_data_set(obj->layer->evas->engine.data.output,
268                                                                 o->engine_data,
269                                                                 data, len);
270    o->gradient_changed = 1;
271    o->changed = 1;
272    evas_object_change(obj);
273 }
274
275 /**
276  * @defgroup Evas_Object_Gradient_Fill_Group Gradient Object Fill Rectangle Functions
277  *
278  * Functions that deal with what areas of the gradient object are to be
279  * tiled with the gradient.
280  */
281
282 /**
283  * Sets the rectangle on the gradient object that the gradient will be
284  * drawn to.
285  *
286  * Note that the gradient may be tiled around this one rectangle,
287  * according to its spread value - restrict, repeat, or reflect.  To have
288  * only one 'cycle' of the gradient drawn, the spread value must be set
289  * to restrict, or @p x and @p y must be 0 and @p w and @p h need to be
290  * the width and height of the gradient object respectively.
291  *
292  * The default values for the fill parameters is @p x = 0, @p y = 0,
293  * @p w = 32 and @p h = 32.
294  *
295  * @param   obj The given evas gradient object.
296  * @param   x   The X coordinate for the top left corner of the rect.
297  * @param   y   The Y coordinate for the top left corner of the rect.
298  * @param   w   The width of the rect.
299  * @param   h   The height of the rect.
300  * @ingroup Evas_Object_Gradient_Fill_Group
301  */
302 EAPI void
303 evas_object_gradient_fill_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
304 {
305    Evas_Object_Gradient *o;
306
307    if (w < 0) w = -w;
308    if (h < 0) h = -h;
309    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
310    return;
311    MAGIC_CHECK_END();
312    o = (Evas_Object_Gradient *)(obj->object_data);
313    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
314    return;
315    MAGIC_CHECK_END();
316    if ((o->cur.fill.x == x) &&
317        (o->cur.fill.y == y) &&
318        (o->cur.fill.w == w) &&
319        (o->cur.fill.h == h)) return;
320    o->cur.fill.x = x;
321    o->cur.fill.y = y;
322    o->cur.fill.w = w;
323    o->cur.fill.h = h;
324    o->gradient_changed = 1;
325    o->changed = 1;
326    evas_object_change(obj);
327 }
328
329 /**
330  * Retrieves the dimensions of the rectangle on the gradient object that
331  * the gradient will use as its fill rect.
332  *
333  * See @ref evas_object_gradient_fill_set for more details.
334  *
335  * @param   obj The given evas gradient object.
336  * @param   x   Pointer to an Evas_Coord to store the X coordinate in.
337  * @param   y   Pointer to an Evas_Coord to store the Y coordinate in.
338  * @param   w   Pointer to an Evas_Coord to store the width in.
339  * @param   h   Pointer to an Evas_Coord to store the height in.
340  * @ingroup Evas_Object_Gradient_Fill_Group
341  */
342 EAPI void
343 evas_object_gradient_fill_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
344 {
345    Evas_Object_Gradient *o;
346
347    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
348    if (x) *x = 0;
349    if (y) *y = 0;
350    if (w) *w = 0;
351    if (h) *h = 0;
352    return;
353    MAGIC_CHECK_END();
354    o = (Evas_Object_Gradient *)(obj->object_data);
355    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
356    if (x) *x = 0;
357    if (y) *y = 0;
358    if (w) *w = 0;
359    if (h) *h = 0;
360    return;
361    MAGIC_CHECK_END();
362    if (x) *x = o->cur.fill.x;
363    if (y) *y = o->cur.fill.y;
364    if (w) *w = o->cur.fill.w;
365    if (h) *h = o->cur.fill.h;
366    return;
367 }
368
369 /**
370  * Sets the angle at which the given evas gradient object's fill sits clockwise
371  * from vertical.
372  * @param   obj   The given evas gradient object.
373  * @param   angle Angle in degrees.  Can be negative.
374  * @ingroup Evas_Object_Gradient_Group
375  */
376 EAPI void
377 evas_object_gradient_fill_angle_set(Evas_Object *obj, Evas_Angle angle)
378 {
379    Evas_Object_Gradient *o;
380
381    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
382    return;
383    MAGIC_CHECK_END();
384    o = (Evas_Object_Gradient *)(obj->object_data);
385    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
386    return;
387    MAGIC_CHECK_END();
388    if (angle == o->cur.fill.angle) return;
389    o->cur.fill.angle = angle;
390    o->changed = 1;
391    evas_object_change(obj);
392 }
393
394 /**
395  * Retrieves the angle at which the given evas gradient object's fill sits
396  * clockwise from the vertical.
397  * @param   obj The given evas gradient object.
398  * @return  The current angle if successful. @c 0.0 otherwise.
399  * @ingroup Evas_Object_Gradient_Group
400  */
401 EAPI Evas_Angle
402 evas_object_gradient_fill_angle_get(const Evas_Object *obj)
403 {
404    Evas_Object_Gradient *o;
405
406    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
407    return 0.0;
408    MAGIC_CHECK_END();
409    o = (Evas_Object_Gradient *)(obj->object_data);
410    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
411    return 0.0;
412    MAGIC_CHECK_END();
413    return o->cur.fill.angle;
414 }
415
416 /**
417  * Sets the tiling mode for the given evas gradient object's fill.
418  * @param   obj   The given evas gradient object.
419  * @param   spread One of EVAS_TEXTURE_REFLECT, EVAS_TEXTURE_REPEAT,
420  * EVAS_TEXTURE_RESTRICT, EVAS_TEXTURE_RESTRICT_REFLECT, EVAS_TEXTURE_RESTRICT_REPEAT,
421  * or EVAS_TEXTURE_PAD.
422  * @ingroup Evas_Object_Gradient_Group
423  */
424 EAPI void
425 evas_object_gradient_fill_spread_set(Evas_Object *obj, int spread)
426 {
427    Evas_Object_Gradient *o;
428
429    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
430    return;
431    MAGIC_CHECK_END();
432    o = (Evas_Object_Gradient *)(obj->object_data);
433    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
434    return;
435    MAGIC_CHECK_END();
436    if (spread == o->cur.fill.spread) return;
437    o->cur.fill.spread = spread;
438    o->changed = 1;
439    evas_object_change(obj);
440 }
441
442 /**
443  * Retrieves the spread (tiling mode) for the given gradient object's fill.
444  * @param   obj The given evas gradient object.
445  * @return  The current spread mode of the gradient object.
446  * @ingroup Evas_Object_Gradient_Group
447  */
448 EAPI int
449 evas_object_gradient_fill_spread_get(const Evas_Object *obj)
450 {
451    Evas_Object_Gradient *o;
452
453    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
454    return EVAS_TEXTURE_REFLECT;
455    MAGIC_CHECK_END();
456    o = (Evas_Object_Gradient *)(obj->object_data);
457    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
458    return EVAS_TEXTURE_REFLECT;
459    MAGIC_CHECK_END();
460    return o->cur.fill.spread;
461 }
462
463 /**
464  * Sets the angle at which the given evas gradient sits,
465  * relative to whatever intrinsic orientation of the grad type.
466  * Used mostly by 'linear' kinds of gradients.
467  * @param   obj   The given evas gradient object.
468  * @param   angle Angle in degrees.  Can be negative.
469  * @ingroup Evas_Object_Gradient_Group
470  */
471 EAPI void
472 evas_object_gradient_angle_set(Evas_Object *obj, Evas_Angle angle)
473 {
474    Evas_Object_Gradient *o;
475
476    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
477    return;
478    MAGIC_CHECK_END();
479    o = (Evas_Object_Gradient *)(obj->object_data);
480    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
481    return;
482    MAGIC_CHECK_END();
483    if (angle == o->cur.map.angle) return;
484    o->cur.map.angle = angle;
485    o->gradient_changed = 1;
486    o->changed = 1;
487    evas_object_change(obj);
488 }
489
490 /**
491  * Retrieves the angle at which the given evas gradient object sits
492  * rel to its intrinsic orientation.
493  * @param   obj The given evas gradient object.
494  * @return  The current angle if successful. @c 0.0 otherwise.
495  * @ingroup Evas_Object_Gradient_Group
496  */
497 EAPI Evas_Angle
498 evas_object_gradient_angle_get(const Evas_Object *obj)
499 {
500    Evas_Object_Gradient *o;
501
502    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
503    return 0.0;
504    MAGIC_CHECK_END();
505    o = (Evas_Object_Gradient *)(obj->object_data);
506    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
507    return 0.0;
508    MAGIC_CHECK_END();
509    return o->cur.map.angle;
510 }
511
512 /**
513  * Sets the offset of the given evas gradient object's spectrum.
514  * @param   obj   The given evas gradient object.
515  * @param   offset Values can be negative.
516  * @ingroup Evas_Object_Gradient_Group
517  */
518 EAPI void
519 evas_object_gradient_offset_set(Evas_Object *obj, float offset)
520 {
521    Evas_Object_Gradient *o;
522
523    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
524    return;
525    MAGIC_CHECK_END();
526    o = (Evas_Object_Gradient *)(obj->object_data);
527    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
528    return;
529    MAGIC_CHECK_END();
530    if (offset == o->cur.map.offset) return;
531    o->cur.map.offset = offset;
532    o->changed = 1;
533    evas_object_change(obj);
534 }
535
536 /**
537  * Retrieves the spectrum's offset
538  * @param   obj The given evas gradient object.
539  * @return  The current gradient offset if successful. @c 0.0 otherwise.
540  * @ingroup Evas_Object_Gradient_Group
541  */
542 EAPI float
543 evas_object_gradient_offset_get(const Evas_Object *obj)
544 {
545    Evas_Object_Gradient *o;
546
547    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
548    return 0.0;
549    MAGIC_CHECK_END();
550    o = (Evas_Object_Gradient *)(obj->object_data);
551    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
552    return 0.0;
553    MAGIC_CHECK_END();
554    return o->cur.map.offset;
555 }
556
557 /**
558  * Sets the direction of the given evas gradient object's spectrum.
559  * @param   obj   The given evas gradient object.
560  * @param   direction Values are either 1 (the default) or -1.
561  * @ingroup Evas_Object_Gradient_Group
562  */
563 EAPI void
564 evas_object_gradient_direction_set(Evas_Object *obj, int direction)
565 {
566    Evas_Object_Gradient *o;
567
568    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
569    return;
570    MAGIC_CHECK_END();
571    o = (Evas_Object_Gradient *)(obj->object_data);
572    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
573    return;
574    MAGIC_CHECK_END();
575    if (direction == o->cur.map.direction) return;
576    o->cur.map.direction = direction;
577    o->changed = 1;
578    o->gradient_changed = 1;
579    evas_object_change(obj);
580 }
581
582 /**
583  * Retrieves the evas gradient object's spectrum direction
584  * @param   obj The given evas gradient object.
585  * @return  The current gradient direction if successful. @c 1 otherwise.
586  * @ingroup Evas_Object_Gradient_Group
587  */
588 EAPI int
589 evas_object_gradient_direction_get(const Evas_Object *obj)
590 {
591    Evas_Object_Gradient *o;
592
593    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
594    return 0;
595    MAGIC_CHECK_END();
596    o = (Evas_Object_Gradient *)(obj->object_data);
597    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
598    return 0;
599    MAGIC_CHECK_END();
600    return o->cur.map.direction;
601 }
602
603 /**
604  * @defgroup Evas_Object_Gradient_Type_Group Gradient Object Type Functions
605  *
606  * Functions that set or get a gradient's geometric type. Examples are "linear",
607  * "linear.diag", "linear.codiag", "radial", "rectangular", "angular", "sinusoidal", ...
608  * Some types may accept additional parameters to further specify the look.
609  */
610
611 /**
612  * Sets the geometric type displayed by the given gradient object.
613  * @param   obj  The given gradient object.
614  * @param   name Name of the geometric type that the gradient is to be drawn as.
615  * @param   params List of allowable params that the given gradient type allows.
616  * Can be NULL.
617  * @ingroup Evas_Object_Gradient_Type_Group
618  */
619 EAPI void
620 evas_object_gradient_type_set(Evas_Object *obj, const char *name, const char *params)
621 {
622    Evas_Object_Gradient *o;
623
624    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
625    return;
626    MAGIC_CHECK_END();
627    o = (Evas_Object_Gradient *)(obj->object_data);
628    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
629    return;
630    MAGIC_CHECK_END();
631    if (!name || !*name)
632      {
633         name = "linear";
634         params = NULL;
635      }
636    if (params && !*params)
637         params = NULL;
638    if ((o->cur.type.name) && (!strcmp(o->cur.type.name, name)))
639      {
640         if ((!o->cur.type.params) && (!params))
641           return;
642         if ((o->cur.type.params) && (params) && (!strcmp(o->cur.type.params, params)))
643           return;
644         if (o->cur.type.params)
645           {
646             if (o->prev.type.params == o->cur.type.params)
647                 o->prev.type.params = strdup(o->cur.type.params);
648             free(o->cur.type.params);
649             o->cur.type.params = NULL;
650           }
651         if (params)
652           o->cur.type.params = strdup(params);
653         o->changed = 1;
654         o->gradient_changed = 1;
655         o->type_changed = 1;
656         evas_object_change(obj);
657         return;
658      }
659
660    if (o->cur.type.name)
661      {
662         if (o->prev.type.name == o->cur.type.name)
663           o->prev.type.name = strdup(o->cur.type.name);
664         free(o->cur.type.name);
665         o->cur.type.name = NULL;
666      }
667    o->cur.type.name = strdup(name);
668
669    if (o->cur.type.params)
670      {
671         if (o->prev.type.params == o->cur.type.params)
672           o->prev.type.params = strdup(o->cur.type.params);
673         free(o->cur.type.params);
674         o->cur.type.params = NULL;
675      }
676    if (params)
677         o->cur.type.params = strdup(params);
678    o->changed = 1;
679    o->gradient_changed = 1;
680    o->type_changed = 1;
681    evas_object_change(obj);
682 }
683
684 /**
685  * Retrieves the type name and params of the given gradient object.
686  * @param   obj  The given gradient object.
687  * @param   name Pointer to a character pointer to store the pointer to the type
688  *               name in.
689  * @param   params  Pointer to a character pointer to store the pointer to the type
690  *               params string in.
691  * @ingroup Evas_Object_Gradient_Type_Group
692  */
693 EAPI void
694 evas_object_gradient_type_get(const Evas_Object *obj, char **name, char **params)
695 {
696    Evas_Object_Gradient *o;
697
698    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
699    if (name) *name = NULL;
700    if (params) *params = NULL;
701    return;
702    MAGIC_CHECK_END();
703    o = (Evas_Object_Gradient *)(obj->object_data);
704    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
705    if (name) *name = NULL;
706    if (params) *params = NULL;
707    return;
708    MAGIC_CHECK_END();
709    if (name) *name = o->cur.type.name;
710    if (params) *params = o->cur.type.params;
711 }
712
713
714 /*
715   these two functions don't really belong here as they can apply to other
716   objs as well, but for now..
717 */
718
719 /**
720    FIXME: ...
721 **/
722 EAPI void
723 evas_color_hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b)
724 {
725    evas_common_convert_color_hsv_to_rgb(h, s, v, r, g, b);
726 }
727
728 /**
729    FIXME: ...
730 **/
731 EAPI void
732 evas_color_rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v)
733 {
734    evas_common_convert_color_rgb_to_hsv(r, g, b, h, s, v);
735 }
736
737 /**
738    FIXME: ...
739 **/
740 EAPI void
741 evas_color_argb_premul(int a, int *r, int *g, int *b)
742 {
743    evas_common_convert_color_argb_premul(a, r, g, b);
744 }
745
746 /**
747    FIXME: ...
748 **/
749 EAPI void
750 evas_color_argb_unpremul(int a, int *r, int *g, int *b)
751 {
752    evas_common_convert_color_argb_unpremul(a, r, g, b);
753 }
754
755 /**
756    FIXME: ...
757 **/
758 EAPI void
759 evas_data_argb_premul(unsigned int *data, unsigned int len)
760 {
761    if (!data || (len < 1)) return;
762    evas_common_convert_argb_premul(data, len);
763 }
764
765 /**
766    FIXME: ...
767 **/
768 EAPI void
769 evas_data_argb_unpremul(unsigned int *data, unsigned int len)
770 {
771    if (!data || (len < 1)) return;
772    evas_common_convert_argb_unpremul(data, len);
773 }
774
775
776
777 /* all nice and private */
778 static void
779 evas_object_gradient_init(Evas_Object *obj)
780 {
781    /* alloc grad ob, setup methods and default values */
782    obj->object_data = evas_object_gradient_new();
783    /* set up default settings for this kind of object */
784    obj->cur.color.r = 255;
785    obj->cur.color.g = 255;
786    obj->cur.color.b = 255;
787    obj->cur.color.a = 255;
788    obj->cur.geometry.x = 0;
789    obj->cur.geometry.y = 0;
790    obj->cur.geometry.w = 0;
791    obj->cur.geometry.h = 0;
792    obj->cur.layer = 0;
793    obj->cur.anti_alias = 1;
794    obj->cur.interpolation_color_space = EVAS_COLOR_SPACE_ARGB;
795    obj->cur.render_op = EVAS_RENDER_BLEND;
796    /* set up object-specific settings */
797    obj->prev = obj->cur;
798    /* set up methods (compulsory) */
799    obj->func = &object_func;
800    obj->type = o_type;
801 }
802
803 static void *
804 evas_object_gradient_new(void)
805 {
806    Evas_Object_Gradient *o;
807
808    /* alloc obj private data */
809    o = calloc(1, sizeof(Evas_Object_Gradient));
810    if (!o) return NULL;
811    o->magic = MAGIC_OBJ_GRADIENT;
812    o->cur.map.angle = 0.0;
813    o->cur.map.offset = 0.0;
814    o->cur.map.direction = 1;
815    o->cur.fill.x = 0;
816    o->cur.fill.y = 0;
817    o->cur.fill.w = 1;
818    o->cur.fill.h = 1;
819    o->cur.fill.angle = 0.0;
820    o->cur.fill.spread = EVAS_TEXTURE_REFLECT;
821    o->cur.type.name = strdup("linear");
822    o->cur.type.params = NULL;
823    o->cur.gradient_opaque = 0;
824    o->prev = o->cur;
825    o->changed = 1;
826    o->gradient_changed = 1;
827    o->type_changed = 1;
828    return o;
829 }
830
831 static void
832 evas_object_gradient_free(Evas_Object *obj)
833 {
834    Evas_Object_Gradient *o;
835
836    /* frees private object data. very simple here */
837    o = (Evas_Object_Gradient *)(obj->object_data);
838    MAGIC_CHECK(o, Evas_Object_Gradient, MAGIC_OBJ_GRADIENT);
839    return;
840    MAGIC_CHECK_END();
841    /* free obj */
842    if (o->prev.type.name && (o->prev.type.name != o->cur.type.name))
843         free(o->prev.type.name);
844    if (o->prev.type.params && (o->prev.type.params != o->cur.type.params))
845         free(o->prev.type.params);
846    if (o->cur.type.name)
847         free(o->cur.type.name);
848    if (o->cur.type.params)
849         free(o->cur.type.params);
850    if (o->engine_data)
851       obj->layer->evas->engine.func->gradient_free(obj->layer->evas->engine.data.output,
852                                                    o->engine_data);
853    free(o);
854    obj->object_data = NULL; 
855 }
856
857
858 static void
859 evas_object_grad_get_fill_coords(Evas_Object *obj, Evas_Coord fx, Evas_Coord fy, Evas_Coord fw, Evas_Coord fh, Evas_Coord *fx_ret, Evas_Coord *fy_ret, Evas_Coord *fw_ret,
860 Evas_Coord *fh_ret)
861 {
862    Evas_Coord  x, y, w, h;
863
864    x = ((fx * obj->layer->evas->output.w) /
865             (Evas_Coord)obj->layer->evas->viewport.w);
866    w = ((fw * obj->layer->evas->output.w) /
867         (Evas_Coord)obj->layer->evas->viewport.w);
868    y = ((fy * obj->layer->evas->output.h) /
869             (Evas_Coord)obj->layer->evas->viewport.h);
870    h = ((fh * obj->layer->evas->output.h) /
871         (Evas_Coord)obj->layer->evas->viewport.h);
872
873    if (w < 1) w = 1;
874    if (h < 1) h = 1;
875
876    *fx_ret = x;  *fw_ret = w;
877    *fy_ret = y;  *fh_ret = h;
878 }
879
880
881
882 static void
883 evas_object_gradient_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
884 {
885    Evas_Object_Gradient *o;
886
887    /* render object to surface with context, and offxet by x,y */
888    o = (Evas_Object_Gradient *)(obj->object_data);
889    obj->layer->evas->engine.func->context_multiplier_unset(output, context);
890    obj->layer->evas->engine.func->context_anti_alias_set(output, context, obj->cur.anti_alias);
891    obj->layer->evas->engine.func->context_render_op_set(output, context, obj->cur.render_op);
892    if (o->engine_data)
893      {
894         obj->layer->evas->engine.func->gradient_draw(output, context, surface,
895                                                      o->engine_data,
896                                                      obj->cur.geometry.x + x,
897                                                      obj->cur.geometry.y + y,
898                                                      obj->cur.geometry.w,
899                                                      obj->cur.geometry.h);
900 ////                                                 obj->cur.cache.geometry.x + x,
901 ////                                                 obj->cur.cache.geometry.y + y,
902 ////                                                 obj->cur.cache.geometry.w,
903 ////                                                 obj->cur.cache.geometry.h);
904      }
905 }
906
907 static void
908 evas_object_gradient_render_pre(Evas_Object *obj)
909 {
910    Evas_Rectangles rects = { 0, 0, NULL };
911    Evas_Object_Gradient *o;
912    int is_v, was_v;
913
914    /* dont pre-render the obj twice! */
915    if (obj->pre_render_done) return;
916    obj->pre_render_done = 1;
917    /* pre-render phase. this does anything an object needs to do just before */
918    /* rendering. this could mean loading the image data, retrieving it from */
919    /* elsewhere, decoding video etc. */
920    /* then when this is done the object needs to figure if it changed and */
921    /* if so what and where and add the appropriate redraw rectangles */
922    o = (Evas_Object_Gradient *)(obj->object_data);
923    /* if someone is clipping this obj - go calculate the clipper */
924    if (obj->cur.clipper)
925      {
926         if (obj->cur.cache.clip.dirty)
927           evas_object_clip_recalc(obj->cur.clipper);
928         obj->cur.clipper->func->render_pre(obj->cur.clipper);
929      }
930    /* if it changed color */
931    if ((obj->cur.color.r != obj->prev.color.r) ||
932        (obj->cur.color.g != obj->prev.color.g) ||
933        (obj->cur.color.b != obj->prev.color.b) ||
934        (obj->cur.color.a != obj->prev.color.a))
935      { o->gradient_changed = 1;  o->changed = 1; }
936    if ((!o->gradient_changed) && ((obj->cur.cache.clip.r != obj->prev.cache.clip.r) ||
937        (obj->cur.cache.clip.g != obj->prev.cache.clip.g) ||
938        (obj->cur.cache.clip.b != obj->prev.cache.clip.b) ||
939        (obj->cur.cache.clip.a != obj->prev.cache.clip.a)))
940      { o->gradient_changed = 1;  o->changed = 1; }
941    if (!o->gradient_changed && (obj->cur.interpolation_color_space != obj->prev.interpolation_color_space))
942      { o->gradient_changed = 1;  o->changed = 1; }
943    if (!o->changed && (obj->cur.render_op != obj->prev.render_op))
944         o->changed = 1;
945    if (!o->changed && (obj->cur.anti_alias != obj->prev.anti_alias))
946         o->changed = 1;
947    if (o->changed && o->engine_data)
948      {
949         Evas_Coord  fx, fy, fw, fh;
950
951         evas_object_grad_get_fill_coords(obj, o->cur.fill.x, o->cur.fill.y,
952                                          o->cur.fill.w, o->cur.fill.h,
953                                          &fx, &fy, &fw, &fh);
954         obj->layer->evas->engine.func->gradient_fill_set(obj->layer->evas->engine.data.output, o->engine_data,
955                                                          fx, fy, fw, fh);
956         obj->layer->evas->engine.func->gradient_fill_angle_set(obj->layer->evas->engine.data.output, o->engine_data,
957                                                                 o->cur.fill.angle);
958         obj->layer->evas->engine.func->gradient_fill_spread_set(obj->layer->evas->engine.data.output, o->engine_data,
959                                                                 o->cur.fill.spread);
960         obj->layer->evas->engine.func->gradient_angle_set(obj->layer->evas->engine.data.output, o->engine_data,
961                                                           o->cur.map.angle);
962         obj->layer->evas->engine.func->gradient_direction_set(obj->layer->evas->engine.data.output, o->engine_data,
963                                                               o->cur.map.direction);
964         obj->layer->evas->engine.func->gradient_offset_set(obj->layer->evas->engine.data.output, o->engine_data,
965                                                            o->cur.map.offset);
966         if (o->type_changed)
967             obj->layer->evas->engine.func->gradient_type_set(obj->layer->evas->engine.data.output, o->engine_data,
968                                                               o->cur.type.name, o->cur.type.params);
969
970         obj->layer->evas->engine.func->context_anti_alias_set(obj->layer->evas->engine.data.output,
971                                                                 obj->layer->evas->engine.data.context,
972                                                                 obj->cur.anti_alias);
973         obj->layer->evas->engine.func->context_render_op_set(obj->layer->evas->engine.data.output,
974                                                              obj->layer->evas->engine.data.context, obj->cur.render_op);
975         obj->layer->evas->engine.func->context_multiplier_set(obj->layer->evas->engine.data.output,
976                                                                 obj->layer->evas->engine.data.context,
977                                                                 obj->cur.cache.clip.r, obj->cur.cache.clip.g,
978                                                                 obj->cur.cache.clip.b, obj->cur.cache.clip.a);
979         obj->layer->evas->engine.func->context_color_interpolation_set(obj->layer->evas->engine.data.output,
980                                                                         obj->layer->evas->engine.data.context,
981                                                                         obj->cur.interpolation_color_space);
982         if (o->gradient_changed)
983             obj->layer->evas->engine.func->gradient_render_pre(obj->layer->evas->engine.data.output,
984                                                                 obj->layer->evas->engine.data.context,
985                                                                 o->engine_data);
986         o->cur.gradient_opaque = obj->layer->evas->engine.func->gradient_is_opaque(obj->layer->evas->engine.data.output,
987                                                                                    obj->layer->evas->engine.data.context,
988                                                                                    o->engine_data,
989                                                                                    obj->cur.cache.clip.x, obj->cur.cache.clip.y,
990                                                                                    obj->cur.cache.clip.w, obj->cur.cache.clip.h);
991
992         if (obj->cur.cache.clip.a != 255)
993             o->cur.gradient_opaque = 0;
994     }
995    /* now figure what changed and add draw rects */
996    /* if it just became visible or invisible */
997    is_v = evas_object_is_visible(obj);
998    was_v = evas_object_was_visible(obj);
999    if (is_v != was_v)
1000      {
1001         evas_object_render_pre_visible_change(&rects, obj, is_v, was_v);
1002         goto done;
1003      }
1004    /* its not visible - we accounted for it appearing or not so just abort */
1005    if (!is_v) goto done;
1006    /* clipper changed this is in addition to anything else for obj */
1007    evas_object_render_pre_clipper_change(&rects, obj);
1008    /* gradient changed */
1009    if (o->changed || obj->restack)
1010      {
1011         evas_object_render_pre_prev_cur_add(&rects, obj);
1012         goto done;
1013      }
1014    /* if it changed geometry */
1015    if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
1016        (obj->cur.geometry.y != obj->prev.geometry.y) ||
1017        (obj->cur.geometry.w != obj->prev.geometry.w) ||
1018        (obj->cur.geometry.h != obj->prev.geometry.h))
1019      {
1020         evas_object_render_pre_prev_cur_add(&rects, obj);
1021         goto done;
1022      }
1023    /* it obviously didn't change - add a NO obscure - this "unupdates"  this */
1024    /* area so if there were updates for it they get wiped. don't do it if we */
1025    /* arent fully opaque and we are visible */
1026    
1027    if (evas_object_is_visible(obj) &&
1028        evas_object_is_opaque(obj))
1029      obj->layer->evas->engine.func->output_redraws_rect_del(obj->layer->evas->engine.data.output,
1030                                                             obj->cur.cache.clip.x,
1031                                                             obj->cur.cache.clip.y,
1032                                                             obj->cur.cache.clip.w,
1033                                                             obj->cur.cache.clip.h);
1034    
1035    done:
1036    evas_object_render_pre_effect_updates(&rects, obj, is_v, was_v);
1037 }
1038
1039 static void
1040 evas_object_gradient_render_post(Evas_Object *obj)
1041 {
1042    Evas_Object_Gradient *o;
1043
1044    /* this moves the current data to the previous state parts of the object */
1045    /* in whatever way is safest for the object. also if we don't need object */
1046    /* data anymore we can free it if the object deems this is a good idea */
1047    o = (Evas_Object_Gradient *)(obj->object_data);
1048    /* remove those pesky changes */
1049    while (obj->clip.changes)
1050      {
1051         Evas_Rectangle *r;
1052
1053         r = (Evas_Rectangle *)obj->clip.changes->data;
1054         obj->clip.changes = evas_list_remove(obj->clip.changes, r);
1055         free(r);
1056      }
1057    /* move cur to prev safely for object data */
1058    obj->prev = obj->cur;
1059    if (o->prev.type.name && (o->prev.type.name != o->cur.type.name))
1060         free(o->prev.type.name);
1061    if (o->prev.type.params && (o->prev.type.params != o->cur.type.params))
1062         free(o->prev.type.params);
1063    o->prev = o->cur;
1064    o->changed = 0;
1065    o->gradient_changed = 0;
1066    o->type_changed = 0;
1067 }
1068
1069 static int
1070 evas_object_gradient_is_opaque(Evas_Object *obj)
1071 {
1072    Evas_Object_Gradient *o;
1073
1074    /* this returns 1 if the internal object data implies that the object is */
1075    /* currently fully opaque over the entire region it occupies */
1076    o = (Evas_Object_Gradient *)(obj->object_data);
1077    if (!o->engine_data) return 0;
1078    return o->cur.gradient_opaque;
1079  }
1080
1081 static int
1082 evas_object_gradient_was_opaque(Evas_Object *obj)
1083 {
1084    Evas_Object_Gradient *o;
1085
1086    /* this returns 1 if the internal object data implies that the object was */
1087    /* currently fully opaque over the entire region it occupies */
1088    o = (Evas_Object_Gradient *)(obj->object_data);
1089    if (!o->engine_data) return 0;
1090    return o->prev.gradient_opaque;
1091 }