elementary / transit - fixed a wrong word in doxygen.
[framework/uifw/elementary.git] / src / lib / elm_transit.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #define ELM_TRANSIT_CHECK_OR_RETURN(transit, ...) \
5    do { \
6       if (!transit) { \
7          CRITICAL("Elm_Transit " # transit " is NULL!"); \
8          return __VA_ARGS__; \
9       } \
10       if (!EINA_MAGIC_CHECK(transit, ELM_TRANSIT_MAGIC)) { \
11          EINA_MAGIC_FAIL(transit, ELM_TRANSIT_MAGIC); \
12          return __VA_ARGS__; \
13       } \
14       if (transit->deleted){ \
15          ERR("Elm_Transit " # transit " has already been deleted!"); \
16          return __VA_ARGS__; \
17       } \
18    } while (0)
19
20 /**
21  *
22  * @defgroup Transit Transit
23  * @ingroup Elementary
24  *
25  * Transit (see Warning below) is designed to set the various effects for the
26  * Evas_Object such like translation, rotation, etc. For using Effects, Create
27  * transit and insert effects which are interesting.
28  * Once effects are inserted into transit, transit will manage those effects.
29  * (ex deleting).
30  *
31  * Example:
32  * @code
33  * Elm_Transit *trans = elm_transit_add();
34  * elm_transit_object_add(trans, obj);
35  * void *effect_context = elm_transit_effect_translation_context_new(0.0, 0.0,
36  *                                                               280.0, 280.0);
37  * elm_transit_effect_add(transit,
38  *                        elm_transit_effect_translation_op, effect_context,
39  *                        elm_transit_effect_translation_context_free);
40  * elm_transit_duration_set(transit, 5);
41  * elm_transit_auto_reverse_set(transit, EINA_TRUE);
42  * elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
43  * elm_transit_repeat_times_set(transit, -1);
44  * @endcode
45  *
46  * @warning We strongly recomend to use elm_transit just when edje can not do
47  * the trick. Edje has more advantage than Elm_Transit, it has more flexibility and
48  * animations can be manipulated inside the theme.
49  */
50
51 static const char _transit_key[] = "_elm_transit";
52
53 #define FOCAL 2000
54
55 struct _Elm_Transit
56 {
57 #define ELM_TRANSIT_MAGIC 0xd27f190a
58    EINA_MAGIC;
59
60    Ecore_Animator *animator;
61    Eina_List *effect_list;
62    Eina_List *objs;
63    Elm_Transit_Tween_Mode tween_mode;
64    struct {
65       void (*func) (void *data, Elm_Transit *transit);
66       void *arg;
67    } del_data;
68    struct {
69       double delayed;
70       double paused;
71       double duration;
72       double begin;
73       double current;
74    } time;
75    struct {
76       int count;
77       int current;
78       Eina_Bool reverse;
79    } repeat;
80    double progress;
81    unsigned int effects_pending_del;
82    int walking;
83    Eina_Bool auto_reverse : 1;
84    Eina_Bool event_enabled : 1;
85    Eina_Bool deleted : 1;
86 };
87
88 struct _Elm_Transit_Effect
89 {
90    void (*animation_op) (void *data, Elm_Transit *transit, double progress);
91    void (*user_data_free) (void *data, Elm_Transit *transit);
92    void *user_data;
93    Eina_Bool deleted : 1;
94 };
95
96 struct _Elm_Obj_Data
97 {
98    Eina_Bool state;
99    Elm_Transit *transit;
100 };
101
102 typedef struct _Elm_Transit_Effect Elm_Transit_Effect;
103 typedef struct _Elm_Obj_Data Elm_Obj_Data;
104
105 static void
106 _elm_transit_object_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
107 {
108    Elm_Transit *transit = data;
109
110    Elm_Obj_Data *obj_data = evas_object_data_del(obj, _transit_key);
111    evas_object_pass_events_set(obj, obj_data->state);
112    free(obj_data);
113    transit->objs = eina_list_remove(transit->objs, obj);
114    if (!transit->objs) elm_transit_del(transit);
115 }
116
117 static void
118 _elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
119 {
120    Elm_Obj_Data *obj_data = evas_object_data_del(obj, _transit_key);
121
122    evas_object_pass_events_set(obj, obj_data->state);
123    free(obj_data);
124    transit->objs = eina_list_remove(transit->objs, obj);
125    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
126                                   _elm_transit_object_remove_cb);
127 }
128
129 static void
130 _elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect *effect, Eina_List *elist)
131 {
132    if (effect->user_data_free)
133       effect->user_data_free(effect->user_data, transit);
134
135    transit->effect_list = eina_list_remove_list(transit->effect_list, elist);
136    free(effect);
137 }
138
139 static void
140 _remove_dead_effects(Elm_Transit *transit)
141 {
142    Eina_List *elist, *elist_next;
143    Elm_Transit_Effect *effect;
144
145    EINA_LIST_FOREACH_SAFE(transit->effect_list, elist, elist_next, effect)
146      {
147         if (effect->deleted)
148           {
149              _elm_transit_effect_del(transit, effect, elist);
150              transit->effects_pending_del--;
151              if (!transit->effects_pending_del) return;
152           }
153      }
154 }
155
156 static void
157 _elm_transit_del(Elm_Transit *transit)
158 {
159    Eina_List *elist, *elist_next;
160    Elm_Transit_Effect *effect;
161
162    if (transit->animator)
163       ecore_animator_del(transit->animator);
164
165    EINA_LIST_FOREACH_SAFE(transit->effect_list, elist, elist_next, effect)
166       _elm_transit_effect_del(transit, effect, elist);
167
168    while (transit->objs)
169       _elm_transit_object_remove(transit, eina_list_data_get(transit->objs));
170
171    if (transit->del_data.func)
172       transit->del_data.func(transit->del_data.arg, transit);
173
174    EINA_MAGIC_SET(transit, EINA_MAGIC_NONE);
175    free(transit);
176 }
177
178 static void
179 _transit_animate_op(Elm_Transit *transit, double progress)
180 {
181    Eina_List *elist;
182    Elm_Transit_Effect *effect;
183
184    transit->walking++;
185    EINA_LIST_FOREACH(transit->effect_list, elist, effect)
186      {
187         if (transit->deleted) break;
188         if (!effect->deleted)
189            effect->animation_op(effect->user_data, transit, progress);
190      }
191    transit->walking--;
192
193    if (transit->walking) return;
194
195    if (transit->deleted) _elm_transit_del(transit);
196    else if (transit->effects_pending_del) _remove_dead_effects(transit);
197 }
198
199 static Eina_Bool
200 _animator_animate_cb(void *data)
201 {
202    Elm_Transit *transit = data;
203    double elapsed_time, duration;
204
205    transit->time.current = ecore_loop_time_get();
206    elapsed_time = transit->time.current - transit->time.begin;
207    duration = transit->time.duration + transit->time.delayed; 
208
209    if (elapsed_time > duration) 
210       elapsed_time = duration;
211
212    transit->progress = elapsed_time / duration;
213    switch (transit->tween_mode)
214      {
215       case ELM_TRANSIT_TWEEN_MODE_ACCELERATE:
216         transit->progress = 1.0 - sin((ELM_PI / 2.0) + (transit->progress * ELM_PI / 2.0));
217         break;
218       case ELM_TRANSIT_TWEEN_MODE_DECELERATE:
219         transit->progress = sin(transit->progress * ELM_PI / 2.0);
220         break;
221       case ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL:
222         transit->progress = (1.0 - cos(transit->progress * ELM_PI)) / 2.0;
223         break;
224       default:
225         break;
226      }
227
228    /* Reverse? */
229    if (transit->repeat.reverse) transit->progress = 1 - transit->progress;
230
231    if (transit->time.duration > 0) _transit_animate_op(transit, transit->progress);
232
233    /* Not end. Keep going. */
234    if (elapsed_time < duration) return ECORE_CALLBACK_RENEW;
235
236    /* Repeat and reverse and time done! */
237    if ((transit->repeat.current == transit->repeat.count)
238        && (!transit->auto_reverse || transit->repeat.reverse))
239      {
240         elm_transit_del(transit);
241         return ECORE_CALLBACK_CANCEL;
242      }
243
244    /* Repeat Case */
245    if (!transit->auto_reverse || transit->repeat.reverse)
246      {
247         transit->repeat.current++;
248         transit->repeat.reverse = EINA_FALSE;
249      }
250    else transit->repeat.reverse = EINA_TRUE;
251
252    transit->time.begin = ecore_loop_time_get();
253
254    return ECORE_CALLBACK_RENEW;
255 }
256
257 /**
258  * Add new transit.
259  *
260  * @note Is not necessary to delete the transit object, it will be deleted at
261  * the end of its operation.
262  * @note The transit will start playing when the program enter in the main loop, is not
263  * necessary to give a start to the transit.
264  *
265  * @param duration The duration of the transit in seconds. When transit starts
266  * to run, it will last a @p duration time.
267  * @return The transit object.
268  *
269  * @ingroup Transit
270  */
271 EAPI Elm_Transit *
272 elm_transit_add(void)
273 {
274    Elm_Transit *transit = ELM_NEW(Elm_Transit);
275    if (!transit) return NULL;
276
277    EINA_MAGIC_SET(transit, ELM_TRANSIT_MAGIC);
278
279    elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
280
281    return transit;
282 }
283 /**
284  * Stops the animation and delete the @p transit object.
285  *
286  * Call this function if you wants to stop the animation before the duration
287  * time. Make sure the @p transit object is still alive with
288  * elm_transit_del_cb_set() function.
289  * All added effects will be deleted, calling its repective data_free_cb
290  * functions. The function setted by elm_tansit_del_cb_set() will be called.
291  *
292  * @see elm_transit_del_cb_set()
293  *
294  * @param transit The transit object to be deleted.
295  *
296  * @ingroup Transit
297  * @warning Just call this function if you are sure the transit is alive.
298  */
299 EAPI void
300 elm_transit_del(Elm_Transit *transit)
301 {
302    ELM_TRANSIT_CHECK_OR_RETURN(transit);
303
304    if (transit->walking) transit->deleted = EINA_TRUE;
305    else _elm_transit_del(transit);
306 }
307
308 /**
309  * Add a new effect to the transit.
310  *
311  * @note The cb function and the data are the key to the effect. If you try to
312  * add an already added effect, nothing is done.
313  * @note After the first addition of an effect in @p transit, if its
314  * effect list become empty again, the @p transit will be killed by
315  * elm_transit_del(transit) function.
316  *
317  * Exemple:
318  * @code
319  * Elm_Transit *transit = elm_transit_add();
320  * elm_transit_effect_add(transit,
321  *                        elm_transit_effect_blend_op,
322  *                        elm_transit_effect_blend_context_new(),
323  *                        elm_transit_effect_blend_context_free);
324  * @endcode
325  *
326  * @param transit The transit object.
327  * @param cb The operation function. It is called when the animation begins,
328  * it is the function that actually performs the animation. It is called with
329  * the @p data, @p transit and the time progression of the animation (a double
330  * value between 0.0 and 1.0).
331  * @param data The context data of the effect.
332  * @param data_free_cb The function to free the context data, it will be called
333  * at the end of the effect, it must finalize the animation and free the
334  * @p data.
335  *
336  * @ingroup Transit
337  * @warning The transit free the context data at the and of the transition with
338  * the data_free_cb function, do not use the context data in another transit.
339  */
340 EAPI void
341 elm_transit_effect_add(Elm_Transit *transit, void (*cb)(void *data, Elm_Transit *transit, double progress), void *data, void (*data_free_cb)(void *data, Elm_Transit *transit))
342 {
343    ELM_TRANSIT_CHECK_OR_RETURN(transit);
344    EINA_SAFETY_ON_NULL_RETURN(cb);
345    Elm_Transit_Effect *effect;
346    Eina_List *elist;
347
348    EINA_LIST_FOREACH(transit->effect_list, elist, effect)
349      {
350         if ((effect->animation_op == cb) && (effect->user_data == data)) return;
351      }
352
353    effect = ELM_NEW(Elm_Transit_Effect);
354    if (!effect) return;
355
356    effect->user_data_free = data_free_cb;
357    effect->animation_op = cb;
358    effect->user_data = data;
359
360    transit->effect_list = eina_list_append(transit->effect_list, effect);
361 }
362
363 /**
364  * Delete an added effect.
365  *
366  * This function will remove the effect from the @p transit, calling the
367  * data_free_cb to free the @p data.
368  *
369  * @see elm_transit_effect_add()
370  *
371  * @note If the effect is not found, nothing is done.
372  * @note If the effect list become empty, this function will call
373  * elm_transit_del(transit), that is, it will kill the @p transit.
374  *
375  * @param transit The transit object.
376  * @param cb The operation function.
377  * @param data The context data of the effect.
378  *
379  * @ingroup Transit
380  */
381 EAPI void
382 elm_transit_effect_del(Elm_Transit *transit, void (*cb)(void *data, Elm_Transit *transit, double progress), void *data)
383 {
384    ELM_TRANSIT_CHECK_OR_RETURN(transit);
385    EINA_SAFETY_ON_NULL_RETURN(cb);
386    Eina_List *elist, *elist_next;
387    Elm_Transit_Effect *effect;
388
389    EINA_LIST_FOREACH_SAFE(transit->effect_list, elist, elist_next, effect)
390      {
391         if ((effect->animation_op == cb) && (effect->user_data == data))
392           {
393              if (transit->walking)
394                {
395                   effect->deleted = EINA_TRUE;
396                   transit->effects_pending_del++;
397                }
398              else
399                {
400                   _elm_transit_effect_del(transit, effect, elist);
401                   if (!transit->effect_list) elm_transit_del(transit);
402                }
403              return;
404           }
405      }
406 }
407
408 /**
409  * Add new object to apply the effects.
410  *
411  * @note After the first addition of an object in @p transit, if its
412  * object list become empty again, the @p transit will be killed by
413  * elm_transit_del(transit) function.
414  * @note If the @p obj belongs to another transit, the @p obj will be
415  * removed from it and it will only belong to the @p transit. If the old
416  * transit stays without objects, it will die.
417  * @note When you add an object into the @p transit, its state from
418  * evas_object_pass_events_get(obj) is saved, and it is applied when the
419  * transit ends, if you change this state whith evas_object_pass_events_set()
420  * after add the object, this state will change again when @p transit stops to
421  * run.
422  *
423  * @param transit The transit object.
424  * @param obj Object to be animated.
425  *
426  * @ingroup Transit
427  * @warning It is not allowed to add a new object after transit begins to go. 
428  */
429 EAPI void
430 elm_transit_object_add(Elm_Transit *transit, Evas_Object *obj)
431 {
432    ELM_TRANSIT_CHECK_OR_RETURN(transit);
433    EINA_SAFETY_ON_NULL_RETURN(obj);
434    Elm_Obj_Data *obj_data;
435
436    if (transit->animator) return;
437
438    obj_data = evas_object_data_get(obj, _transit_key);
439
440    if (obj_data)
441      {
442         if (obj_data->transit == transit) return;
443         elm_transit_object_remove(obj_data->transit, obj);
444      }
445
446    obj_data = ELM_NEW(Elm_Obj_Data);
447    obj_data->state = evas_object_pass_events_get(obj);
448    obj_data->transit = transit;
449    evas_object_data_set(obj, _transit_key, obj_data);
450
451    transit->objs = eina_list_append(transit->objs, obj);
452
453    if (!transit->event_enabled) 
454       evas_object_pass_events_set(obj, EINA_TRUE);
455
456    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
457                                   _elm_transit_object_remove_cb, transit);
458 }
459
460 /**
461  * Removes an added object from the transit.
462  *
463  * @note If the @p obj is not in the @p transit, nothing is done.
464  * @note If the list become empty, this function will call
465  * elm_transit_del(transit), that is, it will kill the @p transit.
466  *
467  * @param transit The transit object.
468  * @param obj Object to be removed from @p transit.
469  *
470  * @ingroup Transit
471  * @warning It is not allowed to remove objects after transit begins to go. 
472  */
473 EAPI void
474 elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
475 {
476    ELM_TRANSIT_CHECK_OR_RETURN(transit);
477    EINA_SAFETY_ON_NULL_RETURN(obj);
478    Elm_Obj_Data *obj_data;
479   
480    if (transit->animator) return;
481
482    obj_data = evas_object_data_get(obj, _transit_key);
483  
484    if ((!obj_data) || (obj_data->transit != transit)) return;
485
486    _elm_transit_object_remove(transit, obj);
487    if (!transit->objs) elm_transit_del(transit);
488 }
489
490 /**
491  * Get the objects of the transit.
492  *
493  * @param transit The transit object.
494  * @return a Eina_List with the objects from the transit.
495  *
496  * @ingroup Transit
497  */
498 EAPI const Eina_List *
499 elm_transit_objects_get(const Elm_Transit *transit)
500 {
501    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
502    return transit->objs;
503 }
504
505 /**
506  * Set the event enabled when transit is operating.
507  *
508  * If @p enabled is EINA_TRUE, the objects of the transit will receives
509  * events from mouse and keyboard during the animation.
510  * @note When you add an object with elm_transit_object_add(), its state from
511  * evas_object_pass_events_get(obj) is saved, and it is applied when the
512  * transit ends, if you change this state with evas_object_pass_events_set()
513  * after add the object, this state will change again when @p transit stops to
514  * run.
515  *
516  * @param transit The transit object.
517  * @param enabled Disable or enable.
518  *
519  * @ingroup Transit
520  */
521 EAPI void
522 elm_transit_event_enabled_set(Elm_Transit *transit, Eina_Bool enabled)
523 {
524    ELM_TRANSIT_CHECK_OR_RETURN(transit);
525    Evas_Object *obj;
526    Eina_List *elist;
527    Elm_Obj_Data *obj_data;
528
529    if (transit->event_enabled == enabled) return;
530
531    transit->event_enabled = enabled;
532
533    if (enabled)
534      {
535         EINA_LIST_FOREACH(transit->objs, elist, obj)
536           {
537              obj_data = evas_object_data_get(obj, _transit_key);
538              evas_object_pass_events_set(obj, obj_data->state);
539           }
540      }
541    else
542      {
543         EINA_LIST_FOREACH(transit->objs, elist, obj)
544            evas_object_pass_events_set(obj, EINA_TRUE);
545      }
546 }
547
548 /**
549  * Get the value of event enabled status.
550  *
551  * @see elm_transit_event_enabled_set()
552  *
553  * @param transit The Transit object
554  * @return EINA_TRUE, when event is enabled. If @p transit is NULL
555  * EINA_FALSE is returned
556  *
557  * @ingroup Transit
558  */
559 EAPI Eina_Bool
560 elm_transit_event_enabled_get(const Elm_Transit *transit)
561 {
562    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
563
564    return transit->event_enabled;
565 }
566
567
568 /**
569  * Set the event enabled when transit is operating.
570  *
571  * If @p disabled is EINA_TRUE, the objects of the transit will receives
572  * events from mouse and keyboard during the animation.
573  * @note When you add an object with elm_transit_object_add(), its state from
574  * evas_object_pass_events_get(obj) is saved, and it is applied when the
575  * transit ends, if you change this state with evas_object_pass_events_set()
576  * after add the object, this state will change again when @p transit stops to
577  * run.
578  *
579  * @see elm_transit_event_enabled_set()
580  *
581  * @param transit The transit object.
582  * @param disabled Disable or enable.
583  *
584  * @ingroup Transit
585  */
586 EINA_DEPRECATED EAPI void
587 elm_transit_event_block_set(Elm_Transit *transit, Eina_Bool disabled)
588 {
589    elm_transit_event_enabled_set(transit, disabled);
590 }
591
592
593 /**
594  * Get the value of event block enabled  status.
595  *
596  * @see elm_transit_event_enabled_set(), elm_transit_event_enabled_get()
597  *
598  * @param transit The Transit object
599  * @return EINA_TRUE, when event is enabled. If @p transit is NULL
600  * EINA_FALSE is returned
601  *
602  * @ingroup Transit
603  */
604 EINA_DEPRECATED EAPI Eina_Bool
605 elm_transit_event_block_get(const Elm_Transit *transit)
606 {
607    return !elm_transit_event_enabled_get(transit);
608 }
609
610 /**
611  * Set the user-callback function when the transit is deleted.
612  *
613  * @note Using this function twice will overwrite the first function setted.
614  * @note the @p transit object will be deleted after call @p cb function.
615  *
616  * @param transit The transit object.
617  * @param cb Callback function pointer. This function will be called before
618  * the deletion of the transit.
619  * @param data Callback funtion user data. It is the @p op parameter.
620  *
621  * @ingroup Transit
622  */
623 EAPI void
624 elm_transit_del_cb_set(Elm_Transit *transit, void (*cb) (void *data, Elm_Transit *transit), void *data)
625 {
626    ELM_TRANSIT_CHECK_OR_RETURN(transit);
627    transit->del_data.func = cb;
628    transit->del_data.arg = data;
629 }
630
631 /**
632  * Set reverse effect automatically.
633  *
634  * If auto reverse is setted, after running the effects with the progress
635  * parameter from 0 to 1, it will call the effecs again with the progress
636  * from 1 to 0. The transit will last for a time iqual to (2 * duration * repeat),
637  * where the duration was setted with the function elm_transit_add and
638  * the repeat with the function elm_transit_repeat_times_set().
639  *
640  * @param transit The transit object.
641  * @param reverse EINA_TRUE means the auto_reverse is on.
642  *
643  * @ingroup Transit
644  */
645 EAPI void
646 elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse)
647 {
648    ELM_TRANSIT_CHECK_OR_RETURN(transit);
649    transit->auto_reverse = reverse;
650 }
651
652 /**
653  * Get if the auto reverse is on.
654  *
655  * @see elm_transit_auto_reverse_set()
656  *
657  * @param transit The transit object.
658  * @return EINA_TRUE means auto reverse is on. If @p transit is NULL
659  * EINA_FALSE is returned
660  *
661  * @ingroup Transit
662  */
663 EAPI Eina_Bool
664 elm_transit_auto_reverse_get(Elm_Transit *transit)
665 {
666    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
667    return transit->auto_reverse;
668 }
669
670 /**
671  * Set the transit repeat count. Effect will be repeated by repeat count.
672  *
673  * This function sets the number of repetition the transit will run after
674  * the first one, that is, if @p repeat is 1, the transit will run 2 times.
675  * If the @p repeat is a negative number, it will repeat infinite times.
676  *
677  * @note If this function is called during the transit execution, the transit
678  * will run @p repeat times, ignoring the times it already performed.
679  *
680  * @param transit The transit object
681  * @param repeat Repeat count
682  *
683  * @ingroup Transit
684  */
685 EAPI void
686 elm_transit_repeat_times_set(Elm_Transit *transit, int repeat)
687 {
688    ELM_TRANSIT_CHECK_OR_RETURN(transit);
689    transit->repeat.count = repeat;
690    transit->repeat.current = 0;
691 }
692
693 /**
694  * Get the transit repeat count.
695  *
696  * @see elm_transit_repeat_times_set()
697  *
698  * @param transit The Transit object.
699  * @return The repeat count. If @p transit is NULL
700  * 0 is returned
701  *
702  * @ingroup Transit
703  */
704 EAPI int
705 elm_transit_repeat_times_get(Elm_Transit *transit)
706 {
707    ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
708    return transit->repeat.count;
709 }
710
711 /**
712  * Set the transit animation acceleration type.
713  *
714  * This function sets the tween mode of the transit that can be:
715  * ELM_TRANSIT_TWEEN_MODE_LINEAR - The default mode.
716  * ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL - Starts in accelerate mode and ends decelerating.
717  * ELM_TRANSIT_TWEEN_MODE_DECELERATE - The animation will be slowed over time.
718  * ELM_TRANSIT_TWEEN_MODE_ACCELERATE - The animation will accelerate over time.
719  *
720  * @param transit The transit object.
721  * @param tween_mode The tween type.
722  *
723  * @ingroup Transit
724  */
725 EAPI void
726 elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode)
727 {
728    ELM_TRANSIT_CHECK_OR_RETURN(transit);
729
730    transit->tween_mode = tween_mode;
731 }
732
733 /**
734  * Get the transit animation acceleration type.
735  *
736  * @note @p transit can not be NULL
737  *
738  * @param transit The transit object.
739  * @return The tween type. If @p transit is NULL
740  * ELM_TRANSIT_TWEEN_MODE_LINEAR is returned.
741  *
742  * @ingroup Transit
743  */
744 EAPI Elm_Transit_Tween_Mode
745 elm_transit_tween_mode_get(const Elm_Transit *transit)
746 {
747    ELM_TRANSIT_CHECK_OR_RETURN(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
748    return transit->tween_mode;
749 }
750
751 /**
752  * Set the transit animation time
753  *
754  * @note @p transit can not be NULL
755  *
756  * @param transit The transit object.
757  * @param duration The animation time.
758  *
759  * @ingroup Transit
760  */
761 EAPI void
762 elm_transit_duration_set(Elm_Transit *transit, double duration)
763 {
764    ELM_TRANSIT_CHECK_OR_RETURN(transit);
765    if (transit->animator) return;
766    transit->time.duration = duration;
767 }
768
769 /**
770  * Get the transit animation time
771  *
772  * @note @p transit can not be NULL
773  *
774  * @param transit The transit object.
775  *
776  * @return The transit animation time.
777  *
778  * @ingroup Transit
779  */
780 EAPI double 
781 elm_transit_duration_get(const Elm_Transit *transit)
782 {
783    ELM_TRANSIT_CHECK_OR_RETURN(transit, 0.0);
784    return transit->time.duration;
785 }
786
787 /**
788  * Starts the transition. 
789  * Once this API is called, the transit begins to measure the time.
790  *
791  * @note @p transit can not be NULL
792  *
793  * @param transit The transit object.
794  *
795  * @ingroup Transit
796  */
797 EAPI void
798 elm_transit_go(Elm_Transit *transit)
799 {
800    ELM_TRANSIT_CHECK_OR_RETURN(transit);
801
802    if (transit->animator)
803       ecore_animator_del(transit->animator);
804
805    transit->time.paused = 0;
806    transit->time.delayed = 0;
807    transit->time.begin = ecore_loop_time_get();
808    transit->animator = ecore_animator_add(_animator_animate_cb, transit);
809 }
810
811 /**
812  * Pause/Resume the transition. 
813  * If you call elm_transit_go again, paused states will affect no anymore. 
814  *
815  * @note @p transit can not be NULL
816  *
817  * @param transit The transit object.
818  *
819  * @ingroup Transit
820  */
821 EAPI void
822 elm_transit_paused_set(Elm_Transit *transit, Eina_Bool paused)
823 {
824    ELM_TRANSIT_CHECK_OR_RETURN(transit);
825
826    if (!transit->animator) return;
827
828    if (paused)
829      {
830         if (transit->time.paused > 0) 
831            return;
832         ecore_animator_freeze(transit->animator);
833         transit->time.paused = ecore_loop_time_get();
834      }
835    else
836      {
837         if (transit->time.paused == 0) 
838            return;
839         ecore_animator_thaw(transit->animator);
840         transit->time.delayed += (ecore_loop_time_get() - transit->time.paused);
841         transit->time.paused = 0;
842      }
843 }
844
845 /**
846  * Get the value of paused status. 
847  *
848  * @see elm_transit_paused_set()
849  *
850  * @note @p transit can not be NULL
851  *
852  * @param transit The transit object.
853  * @return EINA_TRUE means transition is paused. If @p transit is NULL
854  * EINA_FALSE is returned
855  *
856  * @ingroup Transit
857  */
858 EAPI Eina_Bool
859 elm_transit_paused_get(const Elm_Transit *transit)
860 {
861    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
862
863    if (transit->time.paused == 0) 
864       return EINA_FALSE;
865
866    return EINA_TRUE;
867 }
868
869 /**
870  * Get the time progression of the animation (a double value between 0.0 and 1.0).
871  *
872  * @note @p transit can not be NULL
873  *
874  * @param transit The transit object.
875  *
876  * @return The time progression value. If @p transit is NULL
877  * 0 is returned
878  *
879  * @ingroup Transit
880  */
881 EAPI double
882 elm_transit_progress_value_get(const Elm_Transit *transit)
883 {
884    ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
885
886    return transit->progress;
887 }
888
889 ///////////////////////////////////////////////////////////////////////////////
890 //Resizing FX
891 ///////////////////////////////////////////////////////////////////////////////
892 typedef struct _Elm_Transit_Effect_Resizing Elm_Transit_Effect_Resizing;
893
894 struct _Elm_Transit_Effect_Resizing
895 {
896    struct _size {
897       Evas_Coord w, h;
898    } from, to;
899 };
900
901 static void
902 _transit_effect_resizing_context_free(void *data, Elm_Transit *transit __UNUSED__)
903 {
904    free(data);
905 }
906
907 static void
908 _transit_effect_resizing_op(void *data, Elm_Transit *transit, double progress)
909 {
910    EINA_SAFETY_ON_NULL_RETURN(data);
911    EINA_SAFETY_ON_NULL_RETURN(transit);
912    Evas_Coord w, h;
913    Evas_Object *obj;
914    Eina_List *elist;
915    Elm_Transit_Effect_Resizing *resizing = data;
916
917    w = resizing->from.w + (resizing->to.w * progress);
918    h = resizing->from.h + (resizing->to.h * progress);
919
920    EINA_LIST_FOREACH(transit->objs, elist, obj)
921       evas_object_resize(obj, w, h);
922 }
923
924 static void *
925 _transit_effect_resizing_context_new(Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
926 {
927    Elm_Transit_Effect_Resizing *resizing;
928
929    resizing = ELM_NEW(Elm_Transit_Effect_Resizing);
930    if (!resizing) return NULL;
931
932    resizing->from.w = from_w;
933    resizing->from.h = from_h;
934    resizing->to.w = to_w - from_w;
935    resizing->to.h = to_h - from_h;
936
937    return resizing;
938 }
939
940 /**
941  * Add the Resizing Effect to Elm_Transit.
942  *
943  * @note This API is one of the facades. It creates resizing effect context 
944  * and add it's required APIs to elm_transit_effect_add. 
945  *
946  * @see elm_transit_effect_add()
947  *
948  * @param transit Transit object.
949  * @param from_w Object width size when effect begins.
950  * @param from_h Object height size when effect begins.
951  * @param to_w Object width size when effect ends.
952  * @param to_h Object height size when effect ends.
953  * @return Resizing effect context data.
954  *
955  * @ingroup Transit
956  */
957 EAPI void *
958 elm_transit_effect_resizing_add(Elm_Transit *transit, Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
959 {
960    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
961    void *effect_context = _transit_effect_resizing_context_new(from_w, from_h, to_w, to_h);
962
963    if (!effect_context) return NULL;
964    elm_transit_effect_add(transit, 
965                           _transit_effect_resizing_op, effect_context,
966                           _transit_effect_resizing_context_free);
967    return effect_context;
968 }
969
970 ///////////////////////////////////////////////////////////////////////////////
971 //Translation FX
972 ///////////////////////////////////////////////////////////////////////////////
973 typedef struct _Elm_Transit_Effect_Translation Elm_Transit_Effect_Translation;
974 typedef struct _Elm_Transit_Effect_Translation_Node Elm_Transit_Effect_Translation_Node;
975
976 struct _Elm_Transit_Effect_Translation_Node
977 {
978    Evas_Object *obj;
979    Evas_Coord x, y;
980 };
981
982 struct _Elm_Transit_Effect_Translation
983 {
984    struct _position_variation {
985       Evas_Coord dx, dy;
986    } from, to;
987    Eina_List *nodes;
988 };
989
990 static void
991 _translation_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
992 {
993    Elm_Transit_Effect_Translation *translation = data;
994    Eina_List *elist;
995    Elm_Transit_Effect_Translation_Node *translation_node;
996
997    EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
998      {
999         if (translation_node->obj != obj) continue;
1000         translation->nodes = eina_list_remove_list(translation->nodes, elist);
1001         free(translation_node);
1002         break;
1003      }
1004 }
1005
1006 static Eina_List *
1007 _translation_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Translation *translation)
1008 {
1009    Elm_Transit_Effect_Translation_Node *translation_node;
1010    const Eina_List *elist;
1011    Evas_Object *obj;
1012    Eina_List *data_list = NULL;
1013    const Eina_List *objs = elm_transit_objects_get(transit);
1014
1015    EINA_LIST_FOREACH(objs, elist, obj)
1016      {
1017         translation_node = ELM_NEW(Elm_Transit_Effect_Translation_Node);
1018         if (!translation_node)
1019           {
1020              eina_list_free(data_list);
1021              return NULL;
1022           }
1023         translation_node->obj = obj;
1024         evas_object_geometry_get(obj, &(translation_node->x),
1025                                  &(translation_node->y), NULL, NULL);
1026         data_list = eina_list_append(data_list, translation_node);
1027         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
1028                                        _translation_object_del_cb, translation);
1029      }
1030    return data_list;
1031 }
1032
1033 void
1034 _transit_effect_translation_context_free(void *data, Elm_Transit *transit __UNUSED__)
1035 {
1036    EINA_SAFETY_ON_NULL_RETURN(data);
1037    Elm_Transit_Effect_Translation *translation = data;
1038    Eina_List *elist, *elist_next;
1039    Elm_Transit_Effect_Translation_Node *translation_node;
1040
1041    EINA_LIST_FOREACH_SAFE(translation->nodes,
1042                           elist, elist_next, translation_node)
1043      {
1044         evas_object_event_callback_del(translation_node->obj,
1045                                        EVAS_CALLBACK_DEL, _translation_object_del_cb);
1046         translation->nodes = eina_list_remove_list(translation->nodes, elist);
1047         free(translation_node);
1048      }
1049    free(translation);
1050 }
1051
1052 void
1053 _transit_effect_translation_op(void *data, Elm_Transit *transit, double progress __UNUSED__)
1054 {
1055    EINA_SAFETY_ON_NULL_RETURN(data);
1056    EINA_SAFETY_ON_NULL_RETURN(transit);
1057    Evas_Coord x, y;
1058    Elm_Transit_Effect_Translation *translation = data;
1059    Elm_Transit_Effect_Translation_Node *translation_node;
1060    Eina_List *elist;
1061
1062    if (!translation->nodes)
1063       translation->nodes = _translation_nodes_build(transit, translation);
1064
1065    EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
1066      {
1067         x = translation_node->x + translation->from.dx
1068            + (translation->to.dx * progress);
1069         y = translation_node->y + translation->from.dy
1070            + (translation->to.dy * progress);
1071         evas_object_move(translation_node->obj, x, y);
1072      }
1073 }
1074
1075 static void *
1076 _transit_effect_translation_context_new(Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
1077 {
1078    Elm_Transit_Effect_Translation *translation;
1079
1080    translation = ELM_NEW(Elm_Transit_Effect_Translation);
1081    if (!translation) return NULL;
1082
1083    translation->from.dx = from_dx;
1084    translation->from.dy = from_dy;
1085    translation->to.dx = to_dx - from_dx;
1086    translation->to.dy = to_dy - from_dy;
1087
1088    return translation;
1089 }
1090
1091 /**
1092  * Add the Translation Effect to Elm_Transit.
1093  *
1094  * @note This API is one of the facades. It creates translation effect context 
1095  * and add it's required APIs to elm_transit_effect_add. 
1096  *
1097  * @see elm_transit_effect_add()
1098  *
1099  * @param transit Transit object.
1100  * @param from_dx X Position variation when effect begins.
1101  * @param from_dy Y Position variation when effect begins.
1102  * @param to_dx X Position variation when effect ends.
1103  * @param to_dy Y Position variation when effect ends.
1104  * @return Translation effect context data.
1105  *
1106  * @ingroup Transit
1107  * @warning Is higher recommended just create a transit with this effect when
1108  * the window that the objects of the transit belongs has already been created.
1109  * This is because this effect needs the geometry information about the objects,
1110  * and if the window was not created yet, it can get a wrong information.
1111  */
1112 EAPI void *
1113 elm_transit_effect_translation_add(Elm_Transit *transit, Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
1114 {
1115    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1116    void *effect_context = _transit_effect_translation_context_new(from_dx, from_dy, to_dx, to_dy);
1117
1118    if (!effect_context) return NULL;
1119    elm_transit_effect_add(transit, 
1120                           _transit_effect_translation_op, effect_context,
1121                           _transit_effect_translation_context_free);
1122    return effect_context;
1123 }
1124
1125
1126 ///////////////////////////////////////////////////////////////////////////////
1127 //Zoom FX
1128 ///////////////////////////////////////////////////////////////////////////////
1129 typedef struct _Elm_Transit_Effect_Zoom Elm_Transit_Effect_Zoom;
1130
1131 struct _Elm_Transit_Effect_Zoom
1132 {
1133    float from, to;
1134 };
1135
1136 void
1137 _transit_effect_zoom_context_free(void *data, Elm_Transit *transit __UNUSED__)
1138 {
1139    free(data);
1140 }
1141
1142 static void
1143 _transit_effect_zoom_op(void *data, Elm_Transit *transit , double progress)
1144 {
1145    EINA_SAFETY_ON_NULL_RETURN(data);
1146    EINA_SAFETY_ON_NULL_RETURN(transit);
1147    Evas_Object *obj;
1148    Eina_List *elist;
1149    Elm_Transit_Effect_Zoom *zoom = data;
1150    Evas_Map *map;
1151    Evas_Coord x, y, w, h;
1152
1153    map = evas_map_new(4);
1154    if (!map) return;
1155
1156    EINA_LIST_FOREACH(transit->objs, elist, obj)
1157      {
1158         evas_object_geometry_get(obj, &x, &y, &w, &h);
1159         evas_map_util_points_populate_from_object_full(map, obj, zoom->from +
1160                                                        (progress * zoom->to));
1161         evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, FOCAL);
1162         evas_object_map_set(obj, map);
1163         evas_object_map_enable_set(obj, EINA_TRUE);
1164      }
1165    evas_map_free(map);
1166 }
1167
1168 static void *
1169 _transit_effect_zoom_context_new(float from_rate, float to_rate)
1170 {
1171    Elm_Transit_Effect_Zoom *zoom;
1172
1173    zoom = ELM_NEW(Elm_Transit_Effect_Zoom);
1174    if (!zoom) return NULL;
1175
1176    zoom->from = (FOCAL - (from_rate * FOCAL)) * (1 / from_rate);
1177    zoom->to = ((FOCAL - (to_rate * FOCAL)) * (1 / to_rate)) - zoom->from;
1178
1179    return zoom;
1180 }
1181
1182 /**
1183  * Add the Zoom Effect to Elm_Transit.
1184  *
1185  * @note This API is one of the facades. It creates zoom effect context 
1186  * and add it's required APIs to elm_transit_effect_add. 
1187  *
1188  * @see elm_transit_effect_add()
1189  *
1190  * @param transit Transit object.
1191  * @param from_rate Scale rate when effect begins (1 is current rate).
1192  * @param to_rate Scale rate when effect ends.
1193  * @return Zoom effect context data.
1194  *
1195  * @ingroup Transit
1196  * @warning Is higher recommended just create a transit with this effect when
1197  * the window that the objects of the transit belongs has already been created.
1198  * This is because this effect needs the geometry information about the objects,
1199  * and if the window was not created yet, it can get a wrong information.
1200  */
1201 EAPI void *
1202 elm_transit_effect_zoom_add(Elm_Transit *transit, float from_rate, float to_rate)
1203 {
1204    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1205    void *effect_context = _transit_effect_zoom_context_new(from_rate, to_rate);
1206
1207    if (!effect_context) return NULL;
1208    elm_transit_effect_add(transit, 
1209                           _transit_effect_zoom_op, effect_context,
1210                           _transit_effect_zoom_context_free);
1211    return effect_context;
1212 }
1213
1214
1215 ///////////////////////////////////////////////////////////////////////////////
1216 //Flip FX
1217 ///////////////////////////////////////////////////////////////////////////////
1218 typedef struct _Elm_Transit_Effect_Flip Elm_Transit_Effect_Flip;
1219
1220 struct _Elm_Transit_Effect_Flip
1221 {
1222    Elm_Transit_Effect_Flip_Axis axis;
1223    Eina_Bool cw : 1;
1224 };
1225
1226 static void
1227 _transit_effect_flip_context_free(void *data, Elm_Transit *transit)
1228 {
1229    EINA_SAFETY_ON_NULL_RETURN(data);
1230    EINA_SAFETY_ON_NULL_RETURN(transit);
1231    Evas_Object *front, *back;
1232    int i;
1233    int count = eina_list_count(transit->objs);
1234
1235    for (i = 0; i < (count - 1); i += 2)
1236      {
1237         front = eina_list_nth(transit->objs, i);
1238         back = eina_list_nth(transit->objs, i+1);
1239         evas_object_map_enable_set(front, EINA_FALSE);
1240         evas_object_map_enable_set(back, EINA_FALSE);
1241      }
1242    free(data);
1243 }
1244
1245 static void
1246 _transit_effect_flip_op(void *data, Elm_Transit *transit, double progress)
1247 {
1248    EINA_SAFETY_ON_NULL_RETURN(data);
1249    EINA_SAFETY_ON_NULL_RETURN(transit);
1250    Evas_Object *obj, *front, *back;
1251    int count, i;
1252    Elm_Transit_Effect_Flip *flip = data;
1253    Evas_Map *map;
1254    float degree;
1255    Evas_Coord x, y, w, h;
1256
1257    map = evas_map_new(4);
1258    if (!map) return;
1259
1260    if (flip->cw) degree = (float)(progress * 180);
1261    else degree = (float)(progress * -180);
1262
1263    count = eina_list_count(transit->objs);
1264    for (i = 0; i < (count - 1); i += 2)
1265      {
1266         Evas_Coord half_w, half_h;
1267
1268         front = eina_list_nth(transit->objs, i);
1269         back = eina_list_nth(transit->objs, i+1);
1270
1271         if ((degree < 90) && (degree > -90))
1272           {
1273              obj = front;
1274              if (front != back) 
1275                {
1276                   evas_object_hide(back);
1277                   evas_object_show(front);
1278                }
1279           }
1280         else
1281           {
1282              obj = back;
1283              if (front != back)
1284                {
1285                   evas_object_hide(front);
1286                   evas_object_show(back);
1287                }
1288           }
1289
1290         evas_map_util_points_populate_from_object_full(map, obj, 0);
1291         evas_object_geometry_get(obj, &x, &y, &w, &h);
1292         half_w = (w / 2);
1293         half_h = (h / 2);
1294
1295         if (flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1296           {
1297              if ((degree >= 90) || (degree <= -90))
1298                {
1299                   evas_map_point_image_uv_set(map, 0, w, 0);
1300                   evas_map_point_image_uv_set(map, 1, 0, 0);
1301                   evas_map_point_image_uv_set(map, 2, 0, h);
1302                   evas_map_point_image_uv_set(map, 3, w, h);
1303                }
1304              evas_map_util_3d_rotate(map, 0, degree,
1305                                      0, x + half_w, y + half_h, 0);
1306           }
1307         else
1308           {
1309              if ((degree >= 90) || (degree <= -90))
1310                {
1311                   evas_map_point_image_uv_set(map, 0, 0, h);
1312                   evas_map_point_image_uv_set(map, 1, w, h);
1313                   evas_map_point_image_uv_set(map, 2, w, 0);
1314                   evas_map_point_image_uv_set(map, 3, 0, 0);
1315                }
1316              evas_map_util_3d_rotate(map, degree,
1317                                      0, 0, x + half_w, y + half_h, 0);
1318           }
1319         evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, FOCAL);
1320         evas_object_map_enable_set(front, EINA_TRUE);
1321         evas_object_map_enable_set(back, EINA_TRUE);
1322         evas_object_map_set(obj, map);
1323      }
1324    evas_map_free(map);
1325 }
1326
1327 static void *
1328 _transit_effect_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1329 {
1330    Elm_Transit_Effect_Flip *flip;
1331
1332    flip = ELM_NEW(Elm_Transit_Effect_Flip);
1333    if (!flip) return NULL;
1334
1335    flip->cw = cw;
1336    flip->axis = axis;
1337
1338    return flip;
1339 }
1340
1341 /**
1342  * Add the Flip Effect to Elm_Transit.
1343  *
1344  * @note This API is one of the facades. It creates flip effect context 
1345  * and add it's required APIs to elm_transit_effect_add. 
1346  * @note This effect is applied to each pair of objects in the order they are listed
1347  * in the transit list of objects. The first object in the pair will be the
1348  * "front" object and the second will be the "back" object.
1349  * 
1350  * @see elm_transit_effect_add()
1351  *
1352  * @param transit Transit object.
1353  * @param axis Flipping Axis(X or Y).
1354  * @param cw Flipping Direction. EINA_TRUE is clock-wise.
1355  * @return Flip effect context data.
1356  *
1357  * @ingroup Transit
1358  * @warning Is higher recommended just create a transit with this effect when
1359  * the window that the objects of the transit belongs has already been created.
1360  * This is because this effect needs the geometry information about the objects,
1361  * and if the window was not created yet, it can get a wrong information.
1362  */
1363 EAPI void *
1364 elm_transit_effect_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1365 {
1366    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1367    void *effect_context = _transit_effect_flip_context_new(axis, cw);
1368
1369    if (!effect_context) return NULL;
1370    elm_transit_effect_add(transit, 
1371                           _transit_effect_flip_op, effect_context,
1372                           _transit_effect_flip_context_free);
1373    return effect_context;
1374 }
1375
1376 ///////////////////////////////////////////////////////////////////////////////
1377 //ResizableFlip FX
1378 ///////////////////////////////////////////////////////////////////////////////
1379 typedef struct _Elm_Transit_Effect_Resizable_Flip Elm_Transit_Effect_ResizableFlip;
1380 typedef struct _Elm_Transit_Effect_Resizable_Flip_Node Elm_Transit_Effect_ResizableFlip_Node;
1381
1382 struct _Elm_Transit_Effect_Resizable_Flip_Node
1383 {
1384    Evas_Object *front;
1385    Evas_Object *back;
1386    struct _vector2d {
1387       float x, y;
1388    } from_pos, from_size, to_pos, to_size;
1389 };
1390
1391 struct _Elm_Transit_Effect_Resizable_Flip
1392 {
1393    Eina_List *nodes;
1394    Eina_Bool cw : 1;
1395    Elm_Transit_Effect_Flip_Axis axis;
1396 };
1397
1398 static void
1399 _resizable_flip_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1400 {
1401    Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
1402    Eina_List *elist;
1403    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1404
1405    EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1406      {
1407         if (resizable_flip_node->front == obj)
1408            evas_object_event_callback_del(resizable_flip_node->back,
1409                                           EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1410         else if (resizable_flip_node->back == obj)
1411            evas_object_event_callback_del(resizable_flip_node->front,
1412                                           EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1413         else continue;
1414
1415         resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1416                                                       elist);
1417         free(resizable_flip_node);
1418         break;
1419      }
1420 }
1421
1422 static Eina_List *
1423 _resizable_flip_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_ResizableFlip *resizable_flip)
1424 {
1425    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1426    Eina_List *data_list = NULL;
1427    Evas_Coord front_x, front_y, front_w, front_h;
1428    Evas_Coord back_x, back_y, back_w, back_h;
1429    int i, count;
1430
1431    count = eina_list_count(transit->objs);
1432    for (i = 0; i < (count - 1); i += 2)
1433      {
1434         resizable_flip_node = ELM_NEW(Elm_Transit_Effect_ResizableFlip_Node);
1435         if (!resizable_flip_node)
1436           {
1437              eina_list_free(data_list);
1438              return NULL;
1439           }
1440
1441         resizable_flip_node->front = eina_list_nth(transit->objs, i);
1442         resizable_flip_node->back = eina_list_nth(transit->objs, i+1);
1443
1444         evas_object_geometry_get(resizable_flip_node->front,
1445                                  &front_x, &front_y, &front_w, &front_h);
1446         evas_object_geometry_get(resizable_flip_node->back,
1447                                  &back_x, &back_y, &back_w, &back_h);
1448
1449         resizable_flip_node->from_pos.x = front_x;
1450         resizable_flip_node->from_pos.y = front_y;
1451         resizable_flip_node->to_pos.x = back_x - front_x;
1452         resizable_flip_node->to_pos.y = back_y - front_y;
1453
1454         resizable_flip_node->from_size.x = front_w;
1455         resizable_flip_node->from_size.y = front_h;
1456         resizable_flip_node->to_size.x = back_w - front_w;
1457         resizable_flip_node->to_size.y = back_h - front_h;
1458
1459         data_list = eina_list_append(data_list, resizable_flip_node);
1460
1461         evas_object_event_callback_add(resizable_flip_node->back,
1462                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1463         evas_object_event_callback_add(resizable_flip_node->front,
1464                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1465      }
1466
1467    return data_list;
1468 }
1469
1470 static void
1471 _set_image_uv_by_axis_y(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
1472 {
1473    if ((degree >= 90) || (degree <= -90))
1474      {
1475         evas_map_point_image_uv_set(map, 0,
1476                                     (flip->from_size.x * 2) + flip->to_size.x,
1477                                     0);
1478         evas_map_point_image_uv_set(map, 1, 0, 0);
1479         evas_map_point_image_uv_set(map, 2, 0,
1480                                     (flip->from_size.y * 2) + flip->to_size.y);
1481         evas_map_point_image_uv_set(map, 3,
1482                                     (flip->from_size.x * 2) + flip->to_size.x,
1483                                     (flip->from_size.y * 2) + flip->to_size.y);
1484      }
1485    else
1486      {
1487         evas_map_point_image_uv_set(map, 0, 0, 0);
1488         evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1489         evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1490                                     flip->from_size.y);
1491         evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1492      }
1493 }
1494
1495 static void
1496 _set_image_uv_by_axis_x(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, float degree)
1497 {
1498    if ((degree >= 90) || (degree <= -90))
1499      {
1500         evas_map_point_image_uv_set(map, 0, 0,
1501                                     (flip->from_size.y * 2) + flip->to_size.y);
1502         evas_map_point_image_uv_set(map, 1,
1503                                     (flip->from_size.x * 2) + flip->to_size.x,
1504                                     (flip->from_size.y * 2) + flip->to_size.y);
1505         evas_map_point_image_uv_set(map, 2,
1506                                     (flip->from_size.x * 2) + flip->to_size.x,
1507                                     0);
1508         evas_map_point_image_uv_set(map, 3, 0, 0);
1509      }
1510    else
1511      {
1512         evas_map_point_image_uv_set(map, 0, 0, 0);
1513         evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1514         evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1515                                     flip->from_size.y);
1516         evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1517      }
1518 }
1519
1520 void
1521 _transit_effect_resizable_flip_context_free(void *data, Elm_Transit *transit __UNUSED__)
1522 {
1523    EINA_SAFETY_ON_NULL_RETURN(data);
1524
1525    Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
1526    Eina_List *elist, *elist_next;
1527    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1528
1529    EINA_LIST_FOREACH_SAFE(resizable_flip->nodes,
1530                           elist, elist_next, resizable_flip_node)
1531      {
1532         evas_object_map_enable_set(resizable_flip_node->front, EINA_FALSE);
1533         evas_object_map_enable_set(resizable_flip_node->back, EINA_FALSE);
1534
1535         resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1536                                                       elist);
1537
1538         evas_object_event_callback_del(resizable_flip_node->back,
1539                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1540         evas_object_event_callback_del(resizable_flip_node->front,
1541                                        EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1542         free(resizable_flip_node);
1543      }
1544    free(resizable_flip);
1545 }
1546
1547 void
1548 _transit_effect_resizable_flip_op(void *data, Elm_Transit *transit __UNUSED__, double progress)
1549 {
1550    EINA_SAFETY_ON_NULL_RETURN(data);
1551    Evas_Map *map;
1552    Evas_Object *obj;
1553    float x, y, w, h;
1554    float degree;
1555    Evas_Coord half_w, half_h;
1556    Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
1557    Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1558    Eina_List *elist;
1559
1560    map = evas_map_new(4);
1561    if (!map) return;
1562
1563    if (resizable_flip->cw) degree = (float)(progress * 180);
1564    else degree = (float)(progress * -180);
1565
1566    if (!resizable_flip->nodes)
1567       resizable_flip->nodes = _resizable_flip_nodes_build(transit,
1568                                                           resizable_flip);
1569
1570    EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1571      {
1572         if ((degree < 90) && (degree > -90))
1573           {
1574              obj = resizable_flip_node->front;
1575              if (resizable_flip_node->front != resizable_flip_node->back)
1576                {
1577                   evas_object_hide(resizable_flip_node->back);
1578                   evas_object_show(resizable_flip_node->front);
1579                }
1580           }
1581         else
1582           {
1583              obj = resizable_flip_node->back;
1584              if (resizable_flip_node->front != resizable_flip_node->back)
1585                {
1586                   evas_object_hide(resizable_flip_node->front);
1587                   evas_object_show(resizable_flip_node->back);
1588                }
1589           }
1590
1591         x = resizable_flip_node->from_pos.x +
1592            (resizable_flip_node->to_pos.x * progress);
1593         y = resizable_flip_node->from_pos.y +
1594            (resizable_flip_node->to_pos.y * progress);
1595         w = resizable_flip_node->from_size.x +
1596            (resizable_flip_node->to_size.x * progress);
1597         h = resizable_flip_node->from_size.y +
1598            (resizable_flip_node->to_size.y * progress);
1599         evas_map_point_coord_set(map, 0, x, y, 0);
1600         evas_map_point_coord_set(map, 1, x + w, y, 0);
1601         evas_map_point_coord_set(map, 2, x + w, y + h, 0);
1602         evas_map_point_coord_set(map, 3, x, y + h, 0);
1603
1604         half_w = (Evas_Coord)(w / 2);
1605         half_h = (Evas_Coord)(h / 2);
1606
1607         if (resizable_flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1608           {
1609              _set_image_uv_by_axis_y(map, resizable_flip_node, degree);
1610              evas_map_util_3d_rotate(map, 0, degree,
1611                                      0, x + half_w, y + half_h, 0);
1612           }
1613         else
1614           {
1615              _set_image_uv_by_axis_x(map, resizable_flip_node, degree);
1616              evas_map_util_3d_rotate(map, degree, 0,
1617                                      0, x + half_w, y + half_h, 0);
1618           }
1619
1620         evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, FOCAL);
1621         evas_object_map_enable_set(resizable_flip_node->front, EINA_TRUE);
1622         evas_object_map_enable_set(resizable_flip_node->back, EINA_TRUE);
1623         evas_object_map_set(obj, map);
1624      }
1625    evas_map_free(map);
1626 }
1627
1628 static void *
1629 _transit_effect_resizable_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1630 {
1631    Elm_Transit_Effect_ResizableFlip *resizable_flip;
1632
1633    resizable_flip = ELM_NEW(Elm_Transit_Effect_ResizableFlip);
1634    if (!resizable_flip) return NULL;
1635
1636    resizable_flip->cw = cw;
1637    resizable_flip->axis = axis;
1638
1639    return resizable_flip;
1640 }
1641
1642 /**
1643  * Add the Resizable Flip Effect to Elm_Transit.
1644  *
1645  * @note This API is one of the facades. It creates resizable flip effect context 
1646  * and add it's required APIs to elm_transit_effect_add. 
1647  * @note This effect is applied to each pair of objects in the order they are listed
1648  * in the transit list of objects. The first object in the pair will be the
1649  * "front" object and the second will be the "back" object.
1650  * 
1651  * @see elm_transit_effect_add()
1652  *
1653  * @param transit Transit object.
1654  * @param axis Flipping Axis(X or Y).
1655  * @param cw Flipping Direction. EINA_TRUE is clock-wise.
1656  * @return Resizable flip effect context data.
1657  *
1658  * @ingroup Transit
1659  * @warning Is higher recommended just create a transit with this effect when
1660  * the window that the objects of the transit belongs has already been created.
1661  * This is because this effect needs the geometry information about the objects,
1662  * and if the window was not created yet, it can get a wrong information.
1663  */
1664 EAPI void *
1665 elm_transit_effect_resizable_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1666 {
1667    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1668    void *effect_context = _transit_effect_resizable_flip_context_new(axis, cw);
1669
1670    if (!effect_context) return NULL;
1671    elm_transit_effect_add(transit, 
1672                           _transit_effect_resizable_flip_op, effect_context,
1673                           _transit_effect_resizable_flip_context_free);
1674    return effect_context;
1675 }
1676
1677
1678 ///////////////////////////////////////////////////////////////////////////////
1679 //Wipe FX
1680 ///////////////////////////////////////////////////////////////////////////////
1681 typedef struct _Elm_Transit_Effect_Wipe Elm_Transit_Effect_Wipe;
1682
1683 struct _Elm_Transit_Effect_Wipe
1684 {
1685    Elm_Transit_Effect_Wipe_Type type;
1686    Elm_Transit_Effect_Wipe_Dir dir;
1687 };
1688
1689 static void
1690 _elm_fx_wipe_hide(Evas_Map * map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1691 {
1692    float w2, h2;
1693
1694    switch (dir)
1695      {
1696       case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1697          w2 = w - (w * progress);
1698          h2 = (y + h);
1699          evas_map_point_image_uv_set(map, 0, 0, 0);
1700          evas_map_point_image_uv_set(map, 1, w2, 0);
1701          evas_map_point_image_uv_set(map, 2, w2, h);
1702          evas_map_point_image_uv_set(map, 3, 0, h);
1703          evas_map_point_coord_set(map, 0, x, y, 0);
1704          evas_map_point_coord_set(map, 1, x + w2, y, 0);
1705          evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1706          evas_map_point_coord_set(map, 3, x, h2, 0);
1707          break;
1708       case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1709          w2 = (w * progress);
1710          h2 = (y + h);
1711          evas_map_point_image_uv_set(map, 0, w2, 0);
1712          evas_map_point_image_uv_set(map, 1, w, 0);
1713          evas_map_point_image_uv_set(map, 2, w, h);
1714          evas_map_point_image_uv_set(map, 3, w2, h);
1715          evas_map_point_coord_set(map, 0, x + w2, y, 0);
1716          evas_map_point_coord_set(map, 1, x + w, y, 0);
1717          evas_map_point_coord_set(map, 2, x + w, h2, 0);
1718          evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1719          break;
1720       case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1721          w2 = (x + w);
1722          h2 = h - (h * progress);
1723          evas_map_point_image_uv_set(map, 0, 0, 0);
1724          evas_map_point_image_uv_set(map, 1, w, 0);
1725          evas_map_point_image_uv_set(map, 2, w, h2);
1726          evas_map_point_image_uv_set(map, 3, 0, h2);
1727          evas_map_point_coord_set(map, 0, x, y, 0);
1728          evas_map_point_coord_set(map, 1, w2, y, 0);
1729          evas_map_point_coord_set(map, 2, w2, y+h2, 0);
1730          evas_map_point_coord_set(map, 3, x, y+h2, 0);
1731          break;
1732       case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
1733          w2 = (x + w);
1734          h2 = (h * progress);
1735          evas_map_point_image_uv_set(map, 0, 0, h2);
1736          evas_map_point_image_uv_set(map, 1, w, h2);
1737          evas_map_point_image_uv_set(map, 2, w, h);
1738          evas_map_point_image_uv_set(map, 3, 0, h);
1739          evas_map_point_coord_set(map, 0, x, y + h2, 0);
1740          evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1741          evas_map_point_coord_set(map, 2, w2, y + h, 0);
1742          evas_map_point_coord_set(map, 3, x, y + h, 0);
1743          break;
1744       default:
1745          break;
1746      }
1747    evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, FOCAL);
1748 }
1749
1750 static void
1751 _elm_fx_wipe_show(Evas_Map *map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1752 {
1753    float w2, h2;
1754
1755    switch (dir)
1756      {
1757       case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1758          w2 = (w - (w * progress));
1759          h2 = (y + h);
1760          evas_map_point_image_uv_set(map, 0, w2, 0);
1761          evas_map_point_image_uv_set(map, 1, w, 0);
1762          evas_map_point_image_uv_set(map, 2, w, h);
1763          evas_map_point_image_uv_set(map, 3, w2, h);
1764          evas_map_point_coord_set(map, 0, x + w2, y, 0);
1765          evas_map_point_coord_set(map, 1, w, y, 0);
1766          evas_map_point_coord_set(map, 2, w, h2, 0);
1767          evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1768          break;
1769       case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1770          w2 = (w * progress);
1771          h2 = (y + h);
1772          evas_map_point_image_uv_set(map, 0, 0, 0);
1773          evas_map_point_image_uv_set(map, 1, w2, 0);
1774          evas_map_point_image_uv_set(map, 2, w2, h);
1775          evas_map_point_image_uv_set(map, 3, 0, h);
1776          evas_map_point_coord_set(map, 0, x, y, 0);
1777          evas_map_point_coord_set(map, 1, x + w2, y, 0);
1778          evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1779          evas_map_point_coord_set(map, 3, x, h2, 0);
1780          break;
1781       case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1782          w2 = (x + w);
1783          h2 = (h - (h * progress));
1784          evas_map_point_image_uv_set(map, 0, 0, h2);
1785          evas_map_point_image_uv_set(map, 1, w, h2);
1786          evas_map_point_image_uv_set(map, 2, w, h);
1787          evas_map_point_image_uv_set(map, 3, 0, h);
1788          evas_map_point_coord_set(map, 0, x, y + h2, 0);
1789          evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1790          evas_map_point_coord_set(map, 2, w2, y + h, 0);
1791          evas_map_point_coord_set(map, 3, x, y + h, 0);
1792          break;
1793       case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
1794          w2 = (x + w);
1795          h2 = (h * progress);
1796          evas_map_point_image_uv_set(map, 0, 0, 0);
1797          evas_map_point_image_uv_set(map, 1, w, 0);
1798          evas_map_point_image_uv_set(map, 2, w, h2);
1799          evas_map_point_image_uv_set(map, 3, 0, h2);
1800          evas_map_point_coord_set(map, 0, x, y, 0);
1801          evas_map_point_coord_set(map, 1, w2, y, 0);
1802          evas_map_point_coord_set(map, 2, w2, y + h2, 0);
1803          evas_map_point_coord_set(map, 3, x, y + h2, 0);
1804          break;
1805       default:
1806          break;
1807      }
1808    evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, FOCAL);
1809 }
1810
1811 static void
1812 _transit_effect_wipe_context_free(void *data, Elm_Transit *transit)
1813 {
1814    EINA_SAFETY_ON_NULL_RETURN(data);
1815    EINA_SAFETY_ON_NULL_RETURN(transit);
1816    Eina_List *elist;
1817    Evas_Object *obj;
1818    Elm_Transit_Effect_Wipe *wipe = data;
1819    Eina_Bool reverse = elm_transit_auto_reverse_get(transit);
1820
1821    EINA_LIST_FOREACH(transit->objs, elist, obj)
1822      {
1823         if ((wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW && !reverse)
1824             || (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE && reverse))
1825            evas_object_show(obj);
1826         else evas_object_hide(obj);
1827         evas_object_map_enable_set(obj, EINA_FALSE);
1828      }
1829
1830    free(wipe);
1831 }
1832
1833 static void
1834 _transit_effect_wipe_op(void *data, Elm_Transit *transit, double progress)
1835 {
1836    EINA_SAFETY_ON_NULL_RETURN(data);
1837    EINA_SAFETY_ON_NULL_RETURN(transit);
1838    Elm_Transit_Effect_Wipe *wipe = data;
1839    Evas_Map *map;
1840    Evas_Coord _x, _y, _w, _h;
1841    Eina_List *elist;
1842    Evas_Object *obj;
1843
1844    map = evas_map_new(4);
1845    if (!map) return;
1846
1847    EINA_LIST_FOREACH(transit->objs, elist, obj)
1848      {
1849         evas_object_geometry_get(obj, &_x, &_y, &_w, &_h);
1850
1851         if (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW)
1852            _elm_fx_wipe_show(map, wipe->dir, _x, _y, _w, _h, (float)progress);
1853         else
1854            _elm_fx_wipe_hide(map, wipe->dir, _x, _y, _w, _h, (float)progress);
1855
1856         evas_object_map_enable_set(obj, EINA_TRUE);
1857         evas_object_map_set(obj, map);
1858      }
1859    evas_map_free(map);
1860 }
1861
1862 static void *
1863 _transit_effect_wipe_context_new(Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
1864 {
1865    Elm_Transit_Effect_Wipe *wipe;
1866
1867    wipe = ELM_NEW(Elm_Transit_Effect_Wipe);
1868    if (!wipe) return NULL;
1869
1870    wipe->type = type;
1871    wipe->dir = dir;
1872
1873    return wipe;
1874 }
1875
1876 /**
1877  * Add the Wipe Effect to Elm_Transit.
1878  *
1879  * @note This API is one of the facades. It creates wipe effect context 
1880  * and add it's required APIs to elm_transit_effect_add. 
1881  * 
1882  * @see elm_transit_effect_add()
1883  *
1884  * @param transit Transit object.
1885  * @param type Wipe type. Hide or show.
1886  * @param dir Wipe Direction.
1887  * @return Wipe effect context data.
1888  *
1889  * @ingroup Transit
1890  * @warning Is higher recommended just create a transit with this effect when
1891  * the window that the objects of the transit belongs has already been created.
1892  * This is because this effect needs the geometry information about the objects,
1893  * and if the window was not created yet, it can get a wrong information.
1894  */
1895 EAPI void *
1896 elm_transit_effect_wipe_add(Elm_Transit *transit, Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
1897 {
1898    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1899    void *effect_context = _transit_effect_wipe_context_new(type, dir);
1900
1901    if (!effect_context) return NULL;
1902    elm_transit_effect_add(transit, 
1903                           _transit_effect_wipe_op, effect_context,
1904                           _transit_effect_wipe_context_free);
1905    return effect_context;
1906 }
1907
1908
1909 ///////////////////////////////////////////////////////////////////////////////
1910 //Color FX
1911 ///////////////////////////////////////////////////////////////////////////////
1912 typedef struct _Elm_Transit_Effect_Color Elm_Transit_Effect_Color;
1913
1914 struct _Elm_Transit_Effect_Color
1915 {
1916    struct _unsigned_color {
1917       unsigned int r, g, b, a;
1918    } from;
1919    struct _signed_color {
1920       int r, g, b, a;
1921    } to;
1922 };
1923
1924 static void
1925 _transit_effect_color_context_free(void *data, Elm_Transit *transit __UNUSED__)
1926 {
1927    free(data);
1928 }
1929
1930 static void
1931 _transit_effect_color_op(void *data, Elm_Transit *transit, double progress)
1932 {
1933    EINA_SAFETY_ON_NULL_RETURN(data);
1934    EINA_SAFETY_ON_NULL_RETURN(transit);
1935    Elm_Transit_Effect_Color *color = data;
1936    Evas_Object *obj;
1937    Eina_List *elist;
1938    unsigned int r, g, b, a;
1939
1940    r = (color->from.r + (int)((float)color->to.r * progress));
1941    g = (color->from.g + (int)((float)color->to.g * progress));
1942    b = (color->from.b + (int)((float)color->to.b * progress));
1943    a = (color->from.a + (int)((float)color->to.a * progress));
1944
1945    EINA_LIST_FOREACH(transit->objs, elist, obj)
1946       evas_object_color_set(obj, r, g, b, a);
1947 }
1948
1949 static void *
1950 _transit_effect_color_context_new(unsigned int from_r, unsigned int from_g, unsigned int from_b, unsigned int from_a, unsigned int to_r, unsigned int to_g, unsigned int to_b, unsigned int to_a)
1951 {
1952    Elm_Transit_Effect_Color *color;
1953
1954    color = ELM_NEW(Elm_Transit_Effect_Color);
1955    if (!color) return NULL;
1956
1957    color->from.r = from_r;
1958    color->from.g = from_g;
1959    color->from.b = from_b;
1960    color->from.a = from_a;
1961    color->to.r = to_r - from_r;
1962    color->to.g = to_g - from_g;
1963    color->to.b = to_b - from_b;
1964    color->to.a = to_a - from_a;
1965
1966    return color;
1967 }
1968
1969 /**
1970  * Add the Color Effect to Elm_Transit.
1971  *
1972  * @note This API is one of the facades. It creates color effect context 
1973  * and add it's required APIs to elm_transit_effect_add. 
1974  * 
1975  * @see elm_transit_effect_add()
1976  *
1977  * @param transit        Transit object.
1978  * @param  from_r        RGB R when effect begins.
1979  * @param  from_g        RGB G when effect begins.
1980  * @param  from_b        RGB B when effect begins.
1981  * @param  from_a        RGB A when effect begins.
1982  * @param  to_r          RGB R when effect ends.
1983  * @param  to_g          RGB G when effect ends.
1984  * @param  to_b          RGB B when effect ends.
1985  * @param  to_a          RGB A when effect ends.
1986  * @return               Color effect context data.
1987  *
1988  * @ingroup Transit
1989  */
1990 EAPI void *
1991 elm_transit_effect_color_add(Elm_Transit *transit, unsigned int from_r, unsigned int from_g, unsigned int from_b, unsigned int from_a, unsigned int to_r, unsigned int to_g, unsigned int to_b, unsigned int to_a)
1992 {
1993    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1994    void *effect_context = _transit_effect_color_context_new(from_r, from_g, from_b, from_a, to_r, to_g, to_b, to_a);
1995
1996    if (!effect_context) return NULL;
1997    elm_transit_effect_add(transit, 
1998                           _transit_effect_color_op, effect_context,
1999                           _transit_effect_color_context_free);
2000    return effect_context;
2001 }
2002
2003 ///////////////////////////////////////////////////////////////////////////////
2004 //Fade FX
2005 ///////////////////////////////////////////////////////////////////////////////
2006 typedef struct _Elm_Transit_Effect_Fade Elm_Transit_Effect_Fade;
2007 typedef struct _Elm_Transit_Effect_Fade_Node Elm_Transit_Effect_Fade_Node;
2008
2009 struct _Elm_Transit_Effect_Fade_Node
2010 {
2011    Evas_Object *before;
2012    Evas_Object *after;
2013    struct _signed_color before_color, after_color;
2014    int before_alpha;
2015    int after_alpha;
2016    Eina_Bool inversed : 1;
2017 };
2018
2019 struct _Elm_Transit_Effect_Fade
2020 {
2021    Eina_List *nodes;
2022 };
2023
2024 static void
2025 _fade_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2026 {
2027    Elm_Transit_Effect_Fade *fade = data;
2028    Eina_List *elist;
2029    Elm_Transit_Effect_Fade_Node *fade_node;
2030
2031    EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
2032      {
2033         if (fade_node->before == obj)
2034            evas_object_event_callback_del(fade_node->after,
2035                                           EVAS_CALLBACK_DEL, _fade_object_del_cb);
2036         else if (fade_node->after == obj)
2037            evas_object_event_callback_del(fade_node->before,
2038                                           EVAS_CALLBACK_DEL, _fade_object_del_cb);
2039         else continue;
2040
2041         fade->nodes = eina_list_remove_list(fade->nodes, elist);
2042         free(fade_node);
2043         break;
2044      }
2045 }
2046
2047 static Eina_List *
2048 _fade_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Fade *fade_data)
2049 {
2050    Elm_Transit_Effect_Fade_Node *fade;
2051    Eina_List *data_list = NULL;
2052    int i, count;
2053
2054    count = eina_list_count(transit->objs);
2055    for (i = 0; i < (count - 1); i += 2)
2056      {
2057         fade = ELM_NEW(Elm_Transit_Effect_Fade_Node);
2058         if (!fade)
2059           {
2060              eina_list_free(data_list);
2061              return NULL;
2062           }
2063
2064         fade->before = eina_list_nth(transit->objs, i);
2065         fade->after = eina_list_nth(transit->objs, i+1);
2066
2067         evas_object_color_get(fade->before,
2068                               &fade->before_color.r, &fade->before_color.g,
2069                               &fade->before_color.b, &fade->before_color.a);
2070         evas_object_color_get(fade->after,
2071                               &fade->after_color.r, &fade->after_color.g,
2072                               &fade->after_color.b, &fade->after_color.a);
2073
2074         fade->before_alpha = (255 - fade->before_color.a);
2075         fade->after_alpha = (255 - fade->after_color.a);
2076
2077         data_list = eina_list_append(data_list, fade);
2078
2079         evas_object_event_callback_add(fade->before,
2080                                        EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
2081         evas_object_event_callback_add(fade->after,
2082                                        EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
2083      }
2084    return data_list;
2085 }
2086
2087 static void
2088 _transit_effect_fade_context_free(void *data, Elm_Transit *transit __UNUSED__)
2089 {
2090    EINA_SAFETY_ON_NULL_RETURN(data);
2091    Elm_Transit_Effect_Fade *fade = data;
2092    Elm_Transit_Effect_Fade_Node *fade_node;
2093    Eina_List *elist, *elist_next;
2094
2095    EINA_LIST_FOREACH_SAFE(fade->nodes, elist, elist_next, fade_node)
2096      {
2097         evas_object_color_set(fade_node->before, fade_node->before_color.r,
2098                               fade_node->before_color.g,
2099                               fade_node->before_color.b,
2100                               fade_node->before_color.a);
2101         evas_object_color_set(fade_node->after, fade_node->after_color.r,
2102                               fade_node->after_color.g,
2103                               fade_node->after_color.b,
2104                               fade_node->after_color.a);
2105
2106         fade->nodes = eina_list_remove_list(fade->nodes, elist);
2107         evas_object_event_callback_del(fade_node->before,
2108                                        EVAS_CALLBACK_DEL, _fade_object_del_cb);
2109         evas_object_event_callback_del(fade_node->after,
2110                                        EVAS_CALLBACK_DEL, _fade_object_del_cb);
2111         free(fade_node);
2112      }
2113
2114    free(fade);
2115 }
2116
2117 static void
2118 _transit_effect_fade_op(void *data, Elm_Transit *transit __UNUSED__, double progress)
2119 {
2120    EINA_SAFETY_ON_NULL_RETURN(data);
2121    Elm_Transit_Effect_Fade *fade = data;
2122    Eina_List *elist;
2123    Elm_Transit_Effect_Fade_Node *fade_node;
2124    float _progress;
2125
2126    if (!fade->nodes)
2127       fade->nodes = _fade_nodes_build(transit, fade);
2128
2129    EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
2130      {
2131         if (progress < 0.5)
2132           {
2133              if (!fade_node->inversed)
2134                {
2135                   evas_object_hide(fade_node->after);
2136                   evas_object_show(fade_node->before);
2137                   fade_node->inversed = EINA_TRUE;
2138                }
2139
2140              _progress = (1 - (progress * 2));
2141
2142              evas_object_color_set(fade_node->before,
2143                                    fade_node->before_color.r * _progress,
2144                                    fade_node->before_color.g * _progress,
2145                                    fade_node->before_color.b * _progress,
2146                                    fade_node->before_color.a +
2147                                    fade_node->before_alpha * (1 - _progress));
2148           }
2149         else
2150           {
2151              if (fade_node->inversed)
2152                {
2153                   evas_object_hide(fade_node->before);
2154                   evas_object_show(fade_node->after);
2155                   fade_node->inversed = EINA_FALSE;
2156                }
2157
2158              _progress = ((progress - 0.5) * 2);
2159
2160              evas_object_color_set(fade_node->after,
2161                                    fade_node->after_color.r * _progress,
2162                                    fade_node->after_color.g * _progress,
2163                                    fade_node->after_color.b * _progress,
2164                                    fade_node->after_color.a +
2165                                    fade_node->after_alpha * (1 - _progress));
2166           }
2167      }
2168 }
2169
2170 static void *
2171 _transit_effect_fade_context_new(void)
2172 {
2173    Elm_Transit_Effect_Fade *fade;
2174    fade = ELM_NEW(Elm_Transit_Effect_Fade);
2175    if (!fade) return NULL;
2176    return fade;
2177 }
2178
2179 /**
2180  * Add the Fade Effect to Elm_Transit.
2181  *
2182  * @note This API is one of the facades. It creates fade effect context 
2183  * and add it's required APIs to elm_transit_effect_add. 
2184  * @note This effect is applied to each pair of objects in the order they are listed
2185  * in the transit list of objects. The first object in the pair will be the
2186  * "before" object and the second will be the "after" object.
2187  * 
2188  * @see elm_transit_effect_add()
2189  *
2190  * @param transit Transit object.
2191  * @return Fade effect context data.
2192  * 
2193  * @ingroup Transit
2194  * @warning Is higher recommended just create a transit with this effect when
2195  * the window that the objects of the transit belongs has already been created.
2196  * This is because this effect needs the color information about the objects,
2197  * and if the window was not created yet, it can get a wrong information.
2198  */
2199 EAPI void *
2200 elm_transit_effect_fade_add(Elm_Transit *transit)
2201 {
2202    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2203
2204    void *effect_context = _transit_effect_fade_context_new();
2205    if (!effect_context) return NULL;
2206    elm_transit_effect_add(transit, 
2207                           _transit_effect_fade_op, effect_context,
2208                           _transit_effect_fade_context_free);
2209    return effect_context;
2210 }
2211
2212
2213 ///////////////////////////////////////////////////////////////////////////////
2214 //Blend FX
2215 ///////////////////////////////////////////////////////////////////////////////
2216 typedef struct _Elm_Transit_Effect_Blend Elm_Transit_Effect_Blend;
2217 typedef struct _Elm_Transit_Effect_Blend_Node Elm_Transit_Effect_Blend_Node;
2218
2219 struct _Elm_Transit_Effect_Blend_Node
2220 {
2221    Evas_Object *before;
2222    Evas_Object *after;
2223    struct _signed_color from, to;
2224 };
2225
2226 struct _Elm_Transit_Effect_Blend
2227 {
2228    Eina_List *nodes;
2229 };
2230
2231 static void
2232 _blend_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2233 {
2234    Elm_Transit_Effect_Blend *blend = data;
2235    Eina_List *elist;
2236    Elm_Transit_Effect_Blend_Node *blend_node;
2237
2238    EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
2239      {
2240         if (blend_node->after == obj)
2241            evas_object_event_callback_del(blend_node->before,
2242                                           EVAS_CALLBACK_DEL, _blend_object_del_cb);
2243         else if (blend_node->before == obj)
2244            evas_object_event_callback_del(blend_node->after,
2245                                           EVAS_CALLBACK_DEL, _blend_object_del_cb);
2246         else continue;
2247
2248         blend->nodes = eina_list_remove_list(blend->nodes, elist);
2249         free(blend_node);
2250         break;
2251      }
2252 }
2253
2254 static Eina_List *
2255 _blend_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Blend *blend)
2256 {
2257    Elm_Transit_Effect_Blend_Node *blend_node;
2258    Eina_List *data_list = NULL;
2259    int i, count;
2260
2261    count = eina_list_count(transit->objs);
2262    for (i = 0; i < (count - 1); i += 2)
2263      {
2264         blend_node = ELM_NEW(Elm_Transit_Effect_Blend_Node);
2265         if (!blend_node)
2266           {
2267              eina_list_free(data_list);
2268              return NULL;
2269           }
2270
2271         blend_node->before = eina_list_nth(transit->objs, i);
2272         blend_node->after = eina_list_nth(transit->objs, i + 1);
2273         evas_object_show(blend_node->before);
2274         evas_object_show(blend_node->after);
2275
2276         evas_object_color_get(blend_node->before, &blend_node->from.r,
2277                               &blend_node->from.g, &blend_node->from.b,
2278                               &blend_node->from.a);
2279         evas_object_color_get(blend_node->after, &blend_node->to.r,
2280                               &blend_node->to.g, &blend_node->to.b,
2281                               &blend_node->to.a);
2282
2283         data_list = eina_list_append(data_list, blend_node);
2284
2285         evas_object_event_callback_add(blend_node->before,
2286                                        EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
2287         evas_object_event_callback_add(blend_node->after,
2288                                        EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
2289      }
2290    return data_list;
2291 }
2292
2293 void
2294 _transit_effect_blend_context_free(void *data, Elm_Transit *transit __UNUSED__)
2295 {
2296    EINA_SAFETY_ON_NULL_RETURN(data);
2297    Elm_Transit_Effect_Blend *blend = data;
2298    Elm_Transit_Effect_Blend_Node *blend_node;
2299    Eina_List *elist, *elist_next;
2300
2301    EINA_LIST_FOREACH_SAFE(blend->nodes, elist, elist_next, blend_node)
2302      {
2303         evas_object_color_set(blend_node->before,
2304                               blend_node->from.r, blend_node->from.g,
2305                               blend_node->from.b, blend_node->from.a);
2306         evas_object_color_set(blend_node->after, blend_node->to.r,
2307                               blend_node->to.g, blend_node->to.b,
2308                               blend_node->to.a);
2309
2310         if (elm_transit_auto_reverse_get(transit))
2311            evas_object_hide(blend_node->after);
2312         else
2313            evas_object_hide(blend_node->before);
2314
2315         blend->nodes = eina_list_remove_list(blend->nodes, elist);
2316
2317         evas_object_event_callback_del(blend_node->before,
2318                                        EVAS_CALLBACK_DEL, _blend_object_del_cb);
2319         evas_object_event_callback_del(blend_node->after,
2320                                        EVAS_CALLBACK_DEL, _blend_object_del_cb);
2321         free(blend_node);
2322      }
2323    free(data);
2324 }
2325
2326 void
2327 _transit_effect_blend_op(void *data, Elm_Transit *transit, double progress)
2328 {
2329    EINA_SAFETY_ON_NULL_RETURN(data);
2330    EINA_SAFETY_ON_NULL_RETURN(transit);
2331    Elm_Transit_Effect_Blend *blend = data;
2332    Elm_Transit_Effect_Blend_Node *blend_node;
2333    Eina_List *elist;
2334
2335    if (!blend->nodes) blend->nodes = _blend_nodes_build(transit, blend);
2336
2337    EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
2338      {
2339         evas_object_color_set(blend_node->before,
2340                               (int)(blend_node->from.r * (1 - progress)),
2341                               (int)(blend_node->from.g * (1 - progress)),
2342                               (int)(blend_node->from.b * (1 - progress)),
2343                               (int)(blend_node->from.a * (1 - progress)));
2344         evas_object_color_set(blend_node->after,
2345                               (int)(blend_node->to.r * progress),
2346                               (int)(blend_node->to.g * progress),
2347                               (int)(blend_node->to.b * progress),
2348                               (int)(blend_node->to.a * progress));
2349      }
2350 }
2351
2352 static void *
2353 _transit_effect_blend_context_new(void)
2354 {
2355    Elm_Transit_Effect_Blend *blend;
2356
2357    blend = ELM_NEW(Elm_Transit_Effect_Blend);
2358    if (!blend) return NULL;
2359    return blend;
2360 }
2361
2362 /**
2363  * Add the Blend Effect to Elm_Transit.
2364  *
2365  * @note This API is one of the facades. It creates blend effect context 
2366  * and add it's required APIs to elm_transit_effect_add. 
2367  * @note This effect is applied to each pair of objects in the order they are listed
2368  * in the transit list of objects. The first object in the pair will be the
2369  * "before" object and the second will be the "after" object.
2370  * 
2371  * @see elm_transit_effect_add()
2372  *
2373  * @param transit Transit object.
2374  * @return Blend effect context data.
2375  * 
2376  * @ingroup Transit
2377  * @warning Is higher recommended just create a transit with this effect when
2378  * the window that the objects of the transit belongs has already been created.
2379  * This is because this effect needs the color information about the objects,
2380  * and if the window was not created yet, it can get a wrong information.
2381  */
2382 EAPI void *
2383 elm_transit_effect_blend_add(Elm_Transit *transit)
2384 {
2385    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2386    void *effect_context = _transit_effect_blend_context_new();
2387
2388    if (!effect_context) return NULL;
2389    elm_transit_effect_add(transit, 
2390                           _transit_effect_blend_op, effect_context,
2391                           _transit_effect_blend_context_free);
2392    return effect_context;
2393 }
2394
2395
2396 ///////////////////////////////////////////////////////////////////////////////
2397 //Rotation FX
2398 ///////////////////////////////////////////////////////////////////////////////
2399 typedef struct _Elm_Transit_Effect_Rotation Elm_Transit_Effect_Rotation;
2400
2401 struct _Elm_Transit_Effect_Rotation
2402 {
2403    float from, to;
2404 };
2405
2406 static void
2407 _transit_effect_rotation_context_free(void *data, Elm_Transit *transit __UNUSED__)
2408 {
2409    free(data);
2410 }
2411
2412 static void
2413 _transit_effect_rotation_op(void *data, Elm_Transit *transit, double progress)
2414 {
2415    EINA_SAFETY_ON_NULL_RETURN(data);
2416    EINA_SAFETY_ON_NULL_RETURN(transit);
2417    Elm_Transit_Effect_Rotation *rotation = data;
2418    Evas_Map *map;
2419    Evas_Coord x, y, w, h;
2420    float degree;
2421    float half_w, half_h;
2422    Eina_List *elist;
2423    Evas_Object *obj;
2424
2425    map = evas_map_new(4);
2426    if (!map) return;
2427
2428    EINA_LIST_FOREACH(transit->objs, elist, obj)
2429      {
2430         evas_map_util_points_populate_from_object_full(map, obj, 0);
2431         degree = rotation->from + (float)(progress * rotation->to);
2432
2433         evas_object_geometry_get(obj, &x, &y, &w, &h);
2434
2435         half_w = (float)w * 0.5;
2436         half_h = (float)h * 0.5;
2437
2438         evas_map_util_3d_rotate(map, 0, 0, degree, x + half_w, y + half_h, 0);
2439         evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, FOCAL);
2440         evas_object_map_enable_set(obj, EINA_TRUE);
2441         evas_object_map_set(obj, map);
2442      }
2443    evas_map_free(map);
2444 }
2445
2446 static void *
2447 _transit_effect_rotation_context_new(float from_degree, float to_degree)
2448 {
2449    Elm_Transit_Effect_Rotation *rotation;
2450
2451    rotation = ELM_NEW(Elm_Transit_Effect_Rotation);
2452    if (!rotation) return NULL;
2453
2454    rotation->from = from_degree;
2455    rotation->to = to_degree - from_degree;
2456
2457    return rotation;
2458 }
2459
2460 /**
2461  * Add the Rotation Effect to Elm_Transit.
2462  *
2463  * @note This API is one of the facades. It creates rotation effect context 
2464  * and add it's required APIs to elm_transit_effect_add. 
2465  * 
2466  * @see elm_transit_effect_add()
2467  *
2468  * @param transit Transit object.
2469  * @param from_degree Degree when effect begins.
2470  * @param to_degree Degree when effect is ends.
2471  * @return Rotation effect context data.
2472  * 
2473  * @ingroup Transit
2474  * @warning Is higher recommended just create a transit with this effect when
2475  * the window that the objects of the transit belongs has already been created.
2476  * This is because this effect needs the geometry information about the objects,
2477  * and if the window was not created yet, it can get a wrong information.
2478  */
2479 EAPI void *
2480 elm_transit_effect_rotation_add(Elm_Transit *transit, float from_degree, float to_degree)
2481 {
2482    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2483    void *effect_context = _transit_effect_rotation_context_new(from_degree, to_degree);
2484
2485    if (!effect_context) return NULL;
2486    elm_transit_effect_add(transit, 
2487                           _transit_effect_rotation_op, effect_context,
2488                           _transit_effect_rotation_context_free);
2489    return effect_context;
2490 }
2491
2492
2493 ///////////////////////////////////////////////////////////////////////////////
2494 // ImageAnimation FX
2495 ///////////////////////////////////////////////////////////////////////////////
2496 typedef struct _Elm_Transit_Effect_Image_Animation Elm_Transit_Effect_Image_Animation;
2497
2498 struct _Elm_Transit_Effect_Image_Animation
2499 {
2500    Eina_List *images;
2501 };
2502
2503 static void
2504 _transit_effect_image_animation_context_free(void *data, Elm_Transit *transit __UNUSED__)
2505 {
2506    EINA_SAFETY_ON_NULL_RETURN(data);
2507    Elm_Transit_Effect_Image_Animation *image_animation = data;
2508    const char *image;
2509    Eina_List *elist, *elist_next;
2510
2511    EINA_LIST_FOREACH_SAFE(image_animation->images, elist, elist_next, image)
2512      {
2513         image_animation->images =
2514            eina_list_remove_list(image_animation->images, elist);
2515         eina_stringshare_del(image);
2516      }
2517
2518    free(data);
2519 }
2520
2521 static void
2522 _transit_effect_image_animation_op(void *data, Elm_Transit *transit, double progress)
2523 {
2524    EINA_SAFETY_ON_NULL_RETURN(data);
2525    EINA_SAFETY_ON_NULL_RETURN(transit);
2526    Eina_List *elist;
2527    Evas_Object *obj;
2528    const char *type;
2529    Elm_Transit_Effect_Image_Animation *image_animation = data;
2530    unsigned int count = 0;
2531    int len;
2532
2533    type = eina_stringshare_add("icon");
2534    len = eina_list_count(image_animation->images);
2535
2536    if (!len) count = floor(progress * len);
2537    else count = floor(progress * (len - 1));
2538
2539    EINA_LIST_FOREACH(transit->objs, elist, obj)
2540      {
2541         if (elm_widget_type_check(obj, type))
2542            elm_icon_file_set(obj,
2543                              eina_list_nth(image_animation->images, count), NULL);
2544      }
2545
2546    eina_stringshare_del(type);
2547 }
2548
2549 static void *
2550 _transit_effect_image_animation_context_new(Eina_List *images)
2551 {
2552    Elm_Transit_Effect_Image_Animation *image_animation;
2553    image_animation = ELM_NEW(Elm_Transit_Effect_Image_Animation);
2554
2555    if (!image_animation) return NULL;
2556    image_animation->images = images;
2557    return image_animation;
2558 }
2559
2560 /**
2561  * Add the ImageAnimation Effect to Elm_Transit.
2562  *
2563  * @note This API is one of the facades. It creates image animation effect context 
2564  * and add it's required APIs to elm_transit_effect_add. 
2565  * The @p images parameter is a list images paths. This list and
2566  * its contents will be deleted at the end of the effect by
2567  * elm_transit_effect_image_animation_context_free() function.
2568  *
2569  * Example:
2570  * @code
2571  * char buf[PATH_MAX];
2572  * Eina_List *images = NULL;
2573  * Elm_Transit *transi = elm_transit_add();
2574  *
2575  * snprintf(buf, sizeof(buf), "%s/images/icon_11.png", PACKAGE_DATA_DIR);
2576  * images = eina_list_append(images, eina_stringshare_add(buf));
2577  *
2578  * snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
2579  * images = eina_list_append(images, eina_stringshare_add(buf));
2580  * elm_transit_effect_image_animation_add(transi, images);
2581  *
2582  * @endcode
2583  * 
2584  * @see elm_transit_effect_add()
2585  *
2586  * @param transit Transit object.
2587  * @param images Eina_List of images file paths. This list and
2588  * its contents will be deleted at the end of the effect by
2589  * elm_transit_effect_image_animation_context_free() function.
2590  * @return Image Animation effect context data.
2591  * 
2592  * @ingroup Transit
2593  */
2594 EAPI void *
2595 elm_transit_effect_image_animation_add(Elm_Transit *transit, Eina_List *images)
2596 {
2597    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2598    void *effect_context = _transit_effect_image_animation_context_new(images);
2599
2600    if (!effect_context) return NULL;
2601    elm_transit_effect_add(transit, 
2602                           _transit_effect_image_animation_op, effect_context,
2603                           _transit_effect_image_animation_context_free);
2604    return effect_context;
2605 }