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