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