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