[elm_transit.c] fixed resizing_op bug
[framework/uifw/elementary.git] / src / lib / elm_transit.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #define ELM_TRANSIT_CHECK_OR_RETURN(transit, ...) \
5    do { \
6       if (!transit) { \
7          CRITICAL("Elm_Transit " # transit " is NULL!"); \
8          return __VA_ARGS__; \
9       } \
10       if (!EINA_MAGIC_CHECK(transit, ELM_TRANSIT_MAGIC)) { \
11          EINA_MAGIC_FAIL(transit, ELM_TRANSIT_MAGIC); \
12          return __VA_ARGS__; \
13       } \
14       if (transit->deleted){ \
15          ERR("Elm_Transit " # transit " has already been deleted!"); \
16          return __VA_ARGS__; \
17       } \
18    } while (0)
19
20
21 /**
22  *
23  * @defgroup Transit Transit
24  * @ingroup Elementary
25  *
26  * Transit (see Warning below) is designed to set the various effects for the
27  * Evas_Object such like translation, rotation, etc. For using Effects, Create
28  * transit and insert effects which are interesting.
29  * Once effects are inserted into transit, transit will manage those effects.
30  * (ex deleting).
31  *
32  * @warning We strongly recomend to use elm_transit just when edje can not do
33  * the trick. Edje has more advantage than Elm_Transit, it has more flexibility and
34  * animations can be manipulated inside the theme.
35  */
36
37 struct _transit
38 {
39 #define ELM_TRANSIT_MAGIC 0xd27f190a
40    EINA_MAGIC;
41
42         Evas_Object *parent;
43    Elm_Animator *animator;
44    Eina_List *effect_list;
45         Elm_Transit_Tween_Mode tween_mode;
46         Evas_Object *block_rect;
47    void (*completion_op) (void *data, Elm_Transit *transit);
48    void *completion_arg;
49    Eina_Bool deleted:1;
50 };
51
52 struct _effect
53 {
54    void (*animation_op) (void *data, Elm_Animator *animator, double frame);
55    void (*begin_op) (void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt);
56    void (*end_op) (void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt);
57    void (*del_op) (void* data);
58    unsigned int shared_cnt;
59    void *user_data;
60 };
61
62 static Evas_Object *_create_block_rect(Evas_Object *parent);
63 static void _transit_animate_cb(void *data, Elm_Animator *animator, 
64                                 double frame);
65 static void _transit_fx_begin(Elm_Transit *transit);
66 static void _transit_fx_end(Elm_Transit *transit);
67 static void _transit_complete_cb(void *data);
68 static void _transit_fx_del(Elm_Effect *effect);
69
70
71 //NEW
72 static void _elm_transit_del(Elm_Transit *transit);
73
74
75 static void
76 _elm_transit_del(Elm_Transit *transit)
77 {
78         if (elm_animator_operating_get(transit->animator))
79      {
80         transit->deleted = EINA_TRUE;
81                   return;
82      }
83
84    if (transit->block_rect)
85       evas_object_del(transit->block_rect);
86
87    elm_animator_del(transit->animator);
88    elm_transit_fx_clear(transit);
89         
90         EINA_MAGIC_SET(transit, EINA_MAGIC_NONE);
91    free(transit);
92 }
93
94 static Evas_Object *
95 _create_block_rect(Evas_Object *parent)
96 {
97    Evas_Object *rect;
98
99    Evas_Coord w, h;
100
101    rect = evas_object_rectangle_add(evas_object_evas_get(parent));
102    evas_output_size_get(evas_object_evas_get(parent), &w, &h);
103    evas_object_resize(rect, w, h);
104    evas_object_color_set(rect, 0, 0, 0, 0);
105    return rect;
106 }
107
108 static void
109 _transit_animate_cb(void *data, Elm_Animator *animator, double frame)
110 {
111    Eina_List *elist;
112
113    Elm_Effect *effect;
114
115    Elm_Transit *transit = data;
116
117    EINA_LIST_FOREACH(transit->effect_list, elist, effect)
118    {
119       effect->animation_op(effect->user_data, animator, frame);
120    }
121 }
122
123 static void
124 _transit_fx_begin(Elm_Transit *transit)
125 {
126    Eina_List *elist;
127
128    Elm_Effect *effect;
129
130    Eina_Bool auto_reverse;
131
132    unsigned int repeat_cnt;
133
134    auto_reverse = elm_animator_auto_reverse_get(transit->animator);
135    repeat_cnt = elm_animator_repeat_get(transit->animator);
136
137    EINA_LIST_FOREACH(transit->effect_list, elist, effect)
138    {
139       if (effect->begin_op)
140          effect->begin_op(effect->user_data, auto_reverse, repeat_cnt);
141    }
142 }
143
144 static void
145 _transit_fx_end(Elm_Transit *transit)
146 {
147    Eina_List *elist;
148
149    Elm_Effect *effect;
150
151    Eina_Bool auto_reverse;
152
153    unsigned int repeat_cnt;
154
155    auto_reverse = elm_animator_auto_reverse_get(transit->animator);
156    repeat_cnt = elm_animator_repeat_get(transit->animator);
157
158    EINA_LIST_FOREACH(transit->effect_list, elist, effect)
159    {
160       if (effect->end_op)
161          effect->end_op(effect->user_data, auto_reverse, repeat_cnt);
162    }
163 }
164
165 static void
166 _transit_complete_cb(void *data)
167 {
168    Elm_Transit *transit = (Elm_Transit *) data;
169
170    evas_render(evas_object_evas_get(transit->parent));
171
172    _transit_fx_end(transit);
173
174    if (transit->block_rect)
175       evas_object_hide(transit->block_rect);
176
177    if (transit->completion_op)
178       transit->completion_op(transit->completion_arg, transit);
179
180    if (transit->deleted)
181      {
182         transit->deleted = EINA_FALSE;
183         elm_transit_del(transit);
184      }
185 }
186
187 static void
188 _transit_fx_del(Elm_Effect *effect)
189 {
190    if (!effect)
191       return;
192
193    --effect->shared_cnt;
194
195    if (effect->shared_cnt > 0)
196       return;
197
198    if(effect->del_op)
199            (*effect->del_op)(effect->user_data);
200
201    if (effect->user_data)
202       free(effect->user_data);
203    free(effect);
204 }
205
206 /**
207  * Set the event blocked when transit is operating.  
208  *
209  * @param[in] transit Transit object
210  * @param[in] disabled Disable or enable
211  *
212  * @ingroup Transit 
213  */
214 EAPI void
215 elm_transit_event_block_disabled_set(Elm_Transit *transit, Eina_Bool disabled)
216 {
217    ELM_TRANSIT_CHECK_OR_RETURN(transit);
218
219    if (disabled)
220      {
221         if (transit->block_rect)
222           {
223              evas_object_del(transit->block_rect);
224              transit->block_rect = NULL;
225           }
226      }
227    else
228      {
229         if (!transit->block_rect)
230            transit->block_rect = _create_block_rect(transit->parent);
231      }
232 }
233
234 /**
235  * Get the value of event blocked status.
236  *
237  * @see elm_transit_event_block_set()
238  *
239  * @param[in] transit The Transit object
240  * @return EINA_TRUE, when event block is enabled. If @p transit is NULL
241  * EINA_FALSE is returned
242  *
243  * @ingroup Transit
244  */
245 EAPI Eina_Bool
246 elm_transit_event_block_disabled_get(const Elm_Transit *transit)
247 {
248         ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
249    
250         return transit->block_rect ? EINA_TRUE : EINA_FALSE;
251 }
252
253 /**
254  * Remove effect from transit.  
255  *
256  * @param[in] transit   Transit
257  * @param[in] effect Effect to be removed
258  * @return EINA_TRUE, if the effect is removed
259  * @warning If removed effect does not inserted in any transit, it will be deleted. 
260  *
261  * @ingroup Transit 
262  */
263 EAPI Eina_Bool
264 elm_transit_fx_remove(Elm_Transit *transit, Elm_Effect *effect)
265 {
266         ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
267
268         Eina_List *elist;
269
270    Elm_Effect *_effect;
271
272    EINA_LIST_FOREACH(transit->effect_list, elist, _effect)
273    {
274       if (_effect == effect)
275         {
276            transit->effect_list =
277               eina_list_remove(transit->effect_list, _effect);
278            _transit_fx_del(_effect);
279            return EINA_TRUE;
280         }
281    }
282    return EINA_FALSE;
283 }
284
285 /**
286  * Remove all current inserted effects. 
287  *
288  * @param[in] transit   Transit 
289  *
290  * @ingroup Transit 
291  */
292 EAPI void
293 elm_transit_fx_clear(Elm_Transit *transit)
294 {
295         ELM_TRANSIT_CHECK_OR_RETURN(transit);
296
297         Eina_List *elist;
298
299    Elm_Effect *effect;
300
301    EINA_LIST_FOREACH(transit->effect_list, elist, effect)
302    {
303       transit->effect_list = eina_list_remove(transit->effect_list, effect);
304       _transit_fx_del(effect);
305    }
306 }
307
308 /**
309  * Get the list of current inseted effects. 
310  *
311  * @param[in] transit   Transit
312  * @return Effect list 
313  *
314  * @ingroup Transit 
315  */
316 EAPI const Eina_List *
317 elm_transit_fx_get(Elm_Transit *transit)
318 {
319    ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
320
321    return transit->effect_list;
322 }
323
324 /**
325  * Set the user-callback function when the transit operation is done. 
326  *
327  * @param[in] transit   Transit
328  * @param[in] op Callback function pointer
329  * @param[in] data Callback funtion user data
330  *
331  * @ingroup Transit 
332  */
333 EAPI void
334 elm_transit_completion_callback_set(Elm_Transit *transit,
335                                     void (*op) (void *data,
336                                                 Elm_Transit *transit),
337                                     void *data)
338 {
339    ELM_TRANSIT_CHECK_OR_RETURN(transit);
340
341         transit->completion_op = op;
342    transit->completion_arg = data;
343 }
344
345
346
347
348
349 /**
350  * Delete transit. 
351  *
352  * @param[in] transit   Transit to be deleted
353  *
354  * @ingroup Transit 
355  */
356 EAPI void
357 elm_transit_del(Elm_Transit *transit)
358 {
359         ELM_TRANSIT_CHECK_OR_RETURN(transit);
360
361         _elm_transit_del(transit);
362 //      if (transit->walking) transit->deleted = EINA_TRUE;
363 //   else _elm_transit_del(transit);
364 }
365
366 /**
367  * Set the transit animation acceleration style. 
368  *
369  * @param transit       Transit
370  * @param cs Curve style(Please refer elm_animator_curve_style_set)
371  *
372  * @ingroup Transit 
373  */
374 EAPI void
375 elm_transit_curve_style_set(Elm_Transit *transit, Elm_Animator_Curve_Style cs)
376 {
377    ELM_TRANSIT_CHECK_OR_RETURN(transit);
378    elm_animator_curve_style_set(transit->animator, cs);
379 }
380
381 /**
382  * Set the transit animation acceleration type.
383  *
384  * This function sets the tween mode of the transit that can be:
385  * ELM_TRANSIT_TWEEN_MODE_LINEAR - The default mode.
386  * ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL - Starts in accelerate mode and ends decelerating.
387  * ELM_TRANSIT_TWEEN_MODE_DECELERATE - The animation will be slowed over time.
388  * ELM_TRANSIT_TWEEN_MODE_ACCELERATE - The animation will accelerate over time.
389  *
390  * @param[in] transit The transit object.
391  * @param[in] tween_mode The tween type.
392  *
393  * @ingroup Transit
394  */
395 EAPI void
396 elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode)
397 {
398    ELM_TRANSIT_CHECK_OR_RETURN(transit);
399
400    transit->tween_mode = tween_mode;
401
402         switch(tween_mode) 
403         {
404                 case ELM_TRANSIT_TWEEN_MODE_LINEAR:
405                         elm_animator_curve_style_set(transit->animator, ELM_ANIMATOR_CURVE_LINEAR);
406                         break;
407                 case ELM_TRANSIT_TWEEN_MODE_SINUSODIAL:
408                         elm_animator_curve_style_set(transit->animator, ELM_ANIMATOR_CURVE_IN_OUT);
409                         break;
410                 case ELM_TRANSIT_TWEEN_MODE_DECELERATE:
411                         elm_animator_curve_style_set(transit->animator, ELM_ANIMATOR_CURVE_OUT);
412                         break;
413                 case ELM_TRANSIT_TWEEN_MODE_ACCELERATE:
414                         elm_animator_curve_style_set(transit->animator, ELM_ANIMATOR_CURVE_IN);
415                         break;
416                 default:
417                         break;
418         }
419
420 }
421
422 /**
423  * Get the transit animation acceleration type.
424  *
425  * @note @p transit can not be NULL
426  *
427  * @param[in] transit The transit object.
428  * @return The tween type. If @p transit is NULL
429  * ELM_TRANSIT_TWEEN_MODE_LINEAR is returned.
430  *
431  * @ingroup Transit
432  */
433 EAPI Elm_Transit_Tween_Mode
434 elm_transit_tween_mode_get(const Elm_Transit *transit)
435 {
436    ELM_TRANSIT_CHECK_OR_RETURN(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
437
438    return transit->tween_mode;
439 }
440
441 /**
442  * Add new transit. 
443  *
444  * @param[in] parent Parent object
445  * @return transit 
446  *
447  * @ingroup Transit 
448  */
449 EAPI Elm_Transit *
450 elm_transit_add(Evas_Object *parent)
451 {
452    Elm_Transit *transit = ELM_NEW(Elm_Transit);
453
454    if (!transit) return NULL;
455
456    EINA_MAGIC_SET(transit, ELM_TRANSIT_MAGIC);
457
458    //elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
459
460    //transit->time.duration = duration;
461
462         //transit->time.begin = ecore_loop_time_get();
463    
464         //transit->animator = ecore_animator_add(_animator_animate_cb, transit);
465
466         transit->animator = elm_animator_add(parent);
467
468    if (!transit->animator)
469      {
470         free(transit);
471         return NULL;
472      }
473
474    transit->parent = parent;
475    elm_animator_operation_callback_set(transit->animator, _transit_animate_cb,
476                                        transit);
477    elm_animator_completion_callback_set(transit->animator, _transit_complete_cb,
478                                         transit);
479    elm_transit_event_block_disabled_set(transit, EINA_FALSE);
480 /*
481         if(parent)
482         {
483                 evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL, _transit_parent_del, 
484                                                          transit);
485         }
486 */
487    return transit;
488 }
489
490 /**
491  * Set reverse effect automatically.  
492  *
493  * @param[in] transit Transit  
494  * @param[in] reverse EINA_TRUE is reverse.
495  *
496  * @ingroup Transit 
497  */
498 EAPI void
499 elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse)
500 {
501    ELM_TRANSIT_CHECK_OR_RETURN(transit);
502    elm_animator_auto_reverse_set(transit->animator, reverse);
503 }
504
505 /**
506  * Insert an effect into the transit. 
507  *
508  * @param[in] transit Transit
509  * @param[in] effect Effect to be inserted
510  * @return EINA_TRUE is success
511  *
512  * @ingroup Transit 
513  */
514 //EAPI void 
515 //elm_transit_effect_add(Elm_Transit *transit, void (*cb)(void *data, Elm_Transit *transit, double progress), void *data, void (*data_free_cb)(void *data, Elm_Transit *transit))
516 EAPI Eina_Bool
517 elm_transit_fx_insert(Elm_Transit *transit, Elm_Effect *effect)
518 {
519    ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
520         
521    Elm_Effect *_effect;
522
523         Eina_List *elist;
524
525    EINA_LIST_FOREACH(transit->effect_list, elist, _effect)
526    {
527       if (_effect == effect)
528          return EINA_FALSE;
529    }
530
531    ++effect->shared_cnt;
532    transit->effect_list = eina_list_append(transit->effect_list, effect);
533
534    return EINA_TRUE;
535 }
536
537 /**
538  * Set the transit repeat count. Effect will be repeated by repeat count.
539  *
540  * @param[in] transit Transit 
541  * @param[in] repeat Repeat count 
542  *
543  * @ingroup Transit 
544  */
545 EAPI void
546 elm_transit_repeat_set(Elm_Transit *transit, unsigned int repeat)
547 {
548         ELM_TRANSIT_CHECK_OR_RETURN(transit);
549         elm_animator_repeat_set(transit->animator, repeat);
550 }
551
552 /**
553  * Stop the current transit, if the transit is operating. 
554  *
555  * @param[in] transit Transit 
556  *
557  * @ingroup Transit 
558  */
559 EAPI void
560 elm_transit_stop(Elm_Transit *transit)
561 {
562         ELM_TRANSIT_CHECK_OR_RETURN(transit);
563    elm_animator_stop(transit->animator);
564 }
565
566 /**
567  * Run the all the inserted effects.  
568  *
569  * @param[in] transit Transit
570  * @param[in] duration Transit time in seconds
571  *
572  * @ingroup Transit 
573  */
574 EAPI void
575 elm_transit_run(Elm_Transit *transit, double duration)
576 {
577         ELM_TRANSIT_CHECK_OR_RETURN(transit);
578    _transit_fx_begin(transit);
579    elm_animator_duration_set(transit->animator, duration);
580
581    //Block to Top
582    if (transit->block_rect)
583       evas_object_show(transit->block_rect);
584
585    elm_animator_animate(transit->animator);
586
587    //If failed to animate.  
588    if (!elm_animator_operating_get(transit->animator))
589      {
590         if (transit->block_rect)
591            evas_object_hide(transit->block_rect);
592         _transit_fx_end(transit);
593      }
594 }
595
596 /**
597  * Pause the transit
598  *
599  * @param[in]  transit Transit
600  *
601  * @ingroup Transit
602  */
603 EAPI void
604 elm_transit_pause(Elm_Transit *transit)
605 {
606         ELM_TRANSIT_CHECK_OR_RETURN(transit);
607
608         elm_animator_pause(transit->animator);
609 }
610
611 /**
612  * Resume the transit
613  *
614  * @param[in]  transit Transit
615  *
616  * @ingroup Transit
617  */
618 EAPI void
619 elm_transit_resume(Elm_Transit *transit)
620 {
621         ELM_TRANSIT_CHECK_OR_RETURN(transit);
622
623         elm_animator_resume(transit->animator);
624 }
625
626
627
628 /////////////////////////////////////////////////////////////////////////////////////
629 //Resizing FX
630 /////////////////////////////////////////////////////////////////////////////////////
631 typedef struct _resizing Elm_Fx_Resizing;
632 static void _elm_fx_resizing_op(void *data, Elm_Animator *animator, 
633                                 double frame);
634 static void _elm_fx_resizing_begin(void *data, Eina_Bool auto_reverse, 
635                                 unsigned int repeat_cnt);
636
637 struct _resizing
638 {
639    Evas_Object *obj;
640    struct _size
641    {
642       Evas_Coord w, h;
643    } from, to;
644 };
645
646 static void
647 _elm_fx_resizing_begin(void *data, Eina_Bool auto_reverse,
648                        unsigned int repeat_cnt)
649 {
650    Elm_Fx_Resizing *resizing = data;
651
652    evas_object_show(resizing->obj);
653    evas_object_resize(resizing->obj, resizing->from.w, resizing->from.h);
654 }
655
656 static void
657 _elm_fx_resizing_op(void *data, Elm_Animator *animator, double frame)
658 {
659    Evas_Coord w, h;
660
661    Elm_Fx_Resizing *resizing = data;
662
663    w = resizing->from.w + (Evas_Coord) ((float)resizing->to.w * (float)frame);
664    h = resizing->from.h + (Evas_Coord) ((float)resizing->to.h * (float)frame);
665    evas_object_resize(resizing->obj, w, h);
666 }
667
668 /**
669  * Add Resizing effect.  
670  *
671  * @param[in] obj Evas_Object that effect is applying to
672  * @param[in] from_w Object width size when effect begins
673  * @param[in] from_h Object height size when effect begins
674  * @param[in] to_w Object width size when effect ends
675  * @param[in] to_h Object height size when effect ends
676  * @return Resizing effect 
677  *
678  * @ingroup Transit 
679  */
680 EAPI Elm_Effect *
681 elm_fx_resizing_add(Evas_Object *obj, Evas_Coord from_w, Evas_Coord from_h,
682                     Evas_Coord to_w, Evas_Coord to_h)
683 {
684    Elm_Effect *effect;
685
686    Elm_Fx_Resizing *resizing;
687
688    if (!obj)
689       return NULL;
690
691    effect = calloc(1, sizeof(Elm_Effect));
692    if (!effect)
693       return NULL;
694
695    resizing = calloc(1, sizeof(Elm_Fx_Resizing));
696    if (!resizing)
697      {
698         free(effect);
699         return NULL;
700      }
701
702    resizing->obj = obj;
703    resizing->from.w = from_w;
704    resizing->from.h = from_h;
705    resizing->to.w = to_w - from_w;
706    resizing->to.h = to_h - from_h;
707
708    effect->begin_op = _elm_fx_resizing_begin;
709    effect->animation_op = _elm_fx_resizing_op;
710    effect->user_data = resizing;
711
712    return effect;
713 }
714
715 /////////////////////////////////////////////////////////////////////////////////////
716 //Translation FX
717 /////////////////////////////////////////////////////////////////////////////////////
718 typedef struct _translation Elm_Fx_Translation;
719 static void _elm_fx_translation_op(void *data, Elm_Animator *animator, 
720                                 double frame);
721 static void _elm_fx_translation_begin(void *data, Eina_Bool auto_reverse, 
722                                 unsigned int repeat_cnt);
723 static void _elm_fx_translation_end(void *data, Eina_Bool auto_reverse, 
724                                 unsigned int repeat_cnt);
725
726 struct _translation
727 {
728    Evas_Object *obj;
729    struct _point
730    {
731       Evas_Coord x, y;
732    } from, to;
733 };
734
735 static void
736 _elm_fx_translation_begin(void *data, Eina_Bool auto_reverse,
737                           unsigned int repeat_cnt)
738 {
739    Elm_Fx_Translation *translation = data;
740
741    evas_object_show(translation->obj);
742    evas_object_move(translation->obj, translation->from.x, translation->from.y);
743 }
744
745 static void
746 _elm_fx_translation_end(void *data, Eina_Bool auto_reverse,
747                         unsigned int repeat_cnt)
748 {
749    Elm_Fx_Translation *translation = data;
750
751    evas_object_move(translation->obj, translation->from.x + translation->to.x,
752                     translation->from.y + translation->to.y);
753 }
754
755 static void
756 _elm_fx_translation_op(void *data, Elm_Animator *animator, double frame)
757 {
758    Evas_Coord x, y;
759
760    Elm_Fx_Translation *translation = data;
761
762    x = translation->from.x +
763       (Evas_Coord) ((float)translation->to.x * (float)frame);
764    y = translation->from.y +
765       (Evas_Coord) ((float)translation->to.y * (float)frame);
766    evas_object_move(translation->obj, x, y);
767 }
768
769 /**
770  * Add Translation effect.  
771  *
772  * @param[in] obj Evas_Object that effect is applying to
773  * @param[in] from_x Position X when effect begins
774  * @param[in] from_y Position Y when effect begins
775  * @param[in] to_x Position X when effect ends
776  * @param[in] to_y Position Y when effect ends
777  * @return Translation effect 
778  *
779  * @ingroup Transit 
780  */
781 EAPI Elm_Effect *
782 elm_fx_translation_add(Evas_Object *obj, Evas_Coord from_x, Evas_Coord from_y,
783                        Evas_Coord to_x, Evas_Coord to_y)
784 {
785    Elm_Effect *effect;
786
787    Elm_Fx_Translation *translation;
788
789    if (!obj)
790       return NULL;
791
792    effect = calloc(1, sizeof(Elm_Effect));
793    if (!effect)
794       return NULL;
795
796    translation = calloc(1, sizeof(Elm_Fx_Translation));
797
798    if (!translation)
799      {
800         free(effect);
801         return NULL;
802      }
803
804    translation->obj = obj;
805    translation->from.x = from_x;
806    translation->from.y = from_y;
807    translation->to.x = to_x - from_x;
808    translation->to.y = to_y - from_y;
809
810    effect->begin_op = _elm_fx_translation_begin;
811    effect->end_op = _elm_fx_translation_end;
812    effect->animation_op = _elm_fx_translation_op;
813    effect->user_data = translation;
814
815    return effect;
816 }
817
818 /////////////////////////////////////////////////////////////////////////////////////
819 //Zoom FX
820 /////////////////////////////////////////////////////////////////////////////////////
821 typedef struct _zoom Elm_Fx_Zoom;
822 static void _elm_fx_zoom_op(void *data, Elm_Animator * animator, 
823                                 double frame);
824 static void _elm_fx_zoom_begin(void *data, Eina_Bool reverse, 
825                                 unsigned int repeat);
826 static void _elm_fx_zoom_end(void *data, Eina_Bool reverse, 
827                                 unsigned int repeat);
828
829 struct _zoom
830 {
831    Evas_Object *obj;
832    float from, to;
833 };
834
835 static void
836 _elm_fx_zoom_begin(void *data, Eina_Bool reverse, unsigned int repeat)
837 {
838    Elm_Fx_Zoom *zoom = data;
839
840    evas_object_show(zoom->obj);
841    _elm_fx_zoom_op(data, NULL, 0);
842 }
843
844 static void
845 _elm_fx_zoom_end(void *data, Eina_Bool reverse, unsigned int repeat)
846 {
847    Elm_Fx_Zoom *zoom = data;
848
849    evas_object_map_enable_set(zoom->obj, EINA_FALSE);
850 }
851
852 static void
853 _elm_fx_zoom_op(void *data, Elm_Animator *animator, double frame)
854 {
855    Elm_Fx_Zoom *zoom;
856
857    Evas_Map *map;
858
859    Evas_Coord x, y, w, h;
860
861    map = evas_map_new(4);
862    if (!map)
863       return;
864
865    zoom = data;
866    evas_object_geometry_get(zoom->obj, &x, &y, &w, &h);
867    evas_map_smooth_set(map, EINA_TRUE);
868    evas_map_util_points_populate_from_object_full(map, zoom->obj,
869                                                   zoom->from +
870                                                   (frame * zoom->to));
871    evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, 10000);
872    evas_object_map_set(zoom->obj, map);
873    evas_object_map_enable_set(zoom->obj, EINA_TRUE);
874    evas_map_free(map);
875 }
876
877 /**
878  * Add Zoom effect.  
879  *
880  * @param[in] obj Evas_Object that effect is applying to
881  * @param[in] from_rate Scale rate when effect begins (1 is current rate) 
882  * @param[in] to_rate Scale rate when effect ends
883  * @return Zoom effect 
884  *
885  * @ingroup Transit 
886  */
887 EAPI Elm_Effect *
888 elm_fx_zoom_add(Evas_Object *obj, float from_rate, float to_rate)
889 {
890    Elm_Effect *effect;
891
892    Elm_Fx_Zoom *zoom;
893
894    if (!obj)
895       return NULL;
896
897    effect = calloc(1, sizeof(Elm_Effect));
898    if (!effect)
899       return NULL;
900
901    zoom = calloc(1, sizeof(Elm_Fx_Zoom));
902    if (!zoom)
903      {
904         free(effect);
905         return NULL;
906      }
907
908    zoom->obj = obj;
909    zoom->from = (10000 - (from_rate * 10000)) * (1 / from_rate);
910    zoom->to = ((10000 - (to_rate * 10000)) * (1 / to_rate)) - zoom->from;
911    effect->begin_op = _elm_fx_zoom_begin;
912    effect->end_op = _elm_fx_zoom_end;
913    effect->animation_op = _elm_fx_zoom_op;
914    effect->user_data = zoom;
915
916    return effect;
917
918 }
919
920 /////////////////////////////////////////////////////////////////////////////////////
921 //Flip FX
922 /////////////////////////////////////////////////////////////////////////////////////
923 typedef struct _flip Elm_Fx_Flip;
924 static void _elm_fx_flip_op(void *data, Elm_Animator *animator, 
925                                 double frame);
926 static void _elm_fx_flip_end(void *data, Eina_Bool auto_reverse, 
927                                 unsigned int repeat_cnt);
928
929 struct _flip
930 {
931    Evas_Object *front;
932    Evas_Object *back;
933    Elm_Fx_Flip_Axis axis;
934    Eina_Bool cw:1;
935 };
936
937 static void
938 _elm_fx_flip_end(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
939 {
940    Elm_Fx_Flip *flip = data;
941
942    evas_object_map_enable_set(flip->front, EINA_FALSE);
943    evas_object_map_enable_set(flip->back, EINA_FALSE);
944 }
945
946 static void
947 _elm_fx_flip_op(void *data, Elm_Animator *animator, double frame)
948 {
949    Elm_Fx_Flip *flip;
950
951    Evas_Map *map;
952
953    float degree;
954
955    Evas_Object *obj;
956
957    Evas_Coord x, y, w, h;
958
959    map = evas_map_new(4);
960    if (!map)
961       return;
962
963    flip = data;
964
965    if (flip->cw)
966       degree = (float)(frame * 180);
967    else
968       degree = (float)(frame * -180);
969
970    if (degree < 90 && degree > -90)
971      {
972         obj = flip->front;
973         if(flip->back != flip->front) {
974                 evas_object_hide(flip->back);
975                 evas_object_show(flip->front);
976         }
977      }
978    else
979      {
980         obj = flip->back;
981         if(flip->back != flip->front) {
982                 evas_object_hide(flip->front);
983                 evas_object_show(flip->back);
984         }
985      }
986
987    evas_map_smooth_set(map, EINA_TRUE);
988    evas_map_util_points_populate_from_object_full(map, obj, 0);
989    evas_object_geometry_get(obj, &x, &y, &w, &h);
990    Evas_Coord half_w = (w / 2);
991
992    Evas_Coord half_h = (h / 2);
993
994    if (flip->axis == ELM_FX_FLIP_AXIS_Y)
995      {
996         if ((degree >= 90) || (degree <= -90))
997           {
998              evas_map_point_image_uv_set(map, 0, w, 0);
999              evas_map_point_image_uv_set(map, 1, 0, 0);
1000              evas_map_point_image_uv_set(map, 2, 0, h);
1001              evas_map_point_image_uv_set(map, 3, w, h);
1002           }
1003         evas_map_util_3d_rotate(map, 0, degree, 0, x + half_w, y + half_h, 0);
1004      }
1005    else
1006      {
1007         if ((degree >= 90) || (degree <= -90))
1008           {
1009              evas_map_point_image_uv_set(map, 0, 0, h);
1010              evas_map_point_image_uv_set(map, 1, w, h);
1011              evas_map_point_image_uv_set(map, 2, w, 0);
1012              evas_map_point_image_uv_set(map, 3, 0, 0);
1013           }
1014         evas_map_util_3d_rotate(map, degree, 0, 0, x + half_w, y + half_h, 0);
1015      }
1016    evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, 10000);
1017    evas_object_map_enable_set(flip->front, EINA_TRUE);
1018    evas_object_map_enable_set(flip->back, EINA_TRUE);
1019    evas_object_map_set(obj, map);
1020    evas_map_free(map);
1021 }
1022
1023 /**
1024  * Add Flip effect.  
1025  *
1026  * @param[in] front Front surface object 
1027  * @param[in] back Back surface object
1028  * @param[in] axis Flipping Axis(X or Y)
1029  * @param[in] cw Flipping Direction. EINA_TRUE is clock-wise 
1030  * @return Flip effect 
1031  * 
1032  * @ingroup Transit 
1033  */
1034 EAPI Elm_Effect *
1035 elm_fx_flip_add(Evas_Object *front, Evas_Object *back, Elm_Fx_Flip_Axis axis,
1036                 Eina_Bool cw)
1037 {
1038    Elm_Effect *effect;
1039
1040    Elm_Fx_Flip *flip;
1041
1042    if ((!front) || (!back))
1043       return NULL;
1044
1045    effect = calloc(1, sizeof(Elm_Effect));
1046    if (!effect)
1047       return NULL;
1048
1049    flip = calloc(1, sizeof(Elm_Fx_Flip));
1050
1051    if (!flip)
1052      {
1053         free(effect);
1054         return NULL;
1055      }
1056
1057    flip->front = front;
1058    flip->back = back;
1059    flip->cw = cw;
1060    flip->axis = axis;
1061    effect->end_op = _elm_fx_flip_end;
1062    effect->animation_op = _elm_fx_flip_op;
1063    effect->user_data = flip;
1064
1065    return effect;
1066 }
1067
1068 /////////////////////////////////////////////////////////////////////////////////////
1069 //ResizableFlip FX
1070 /////////////////////////////////////////////////////////////////////////////////////
1071 typedef struct _resizable_flip Elm_Fx_ResizableFlip;
1072 static void _elm_fx_resizable_flip_begin(void *data, Eina_Bool reverse, 
1073                                 unsigned int repeat);
1074 static void _elm_fx_resizable_flip_end(void *data, Eina_Bool auto_reverse, 
1075                                 unsigned int repeat_cnt);
1076 static void _elm_fx_resizable_flip_op(void *data, Elm_Animator *animator,
1077                                       double frame);
1078 static void _set_image_uv_by_axis_y(Evas_Map *map, Elm_Fx_ResizableFlip *flip, 
1079                                 float degree);
1080 static void _set_image_uv_by_axis_x(Evas_Map *map, Elm_Fx_ResizableFlip *flip, 
1081                                 float degree);
1082
1083 struct _resizable_flip
1084 {
1085    Evas_Object *front;
1086    Evas_Object *back;
1087    Elm_Fx_Flip_Axis axis;
1088    struct _vector2d
1089    {
1090       float x, y;
1091    } from_pos, from_size, to_pos, to_size;
1092    Eina_Bool cw:1;
1093 };
1094
1095 static void
1096 _elm_fx_resizable_flip_begin(void *data, Eina_Bool reverse, unsigned int repeat)
1097 {
1098    Elm_Fx_ResizableFlip *resizable_flip = data;
1099
1100    evas_object_show(resizable_flip->front);
1101    _elm_fx_resizable_flip_op(data, NULL, 0);
1102 }
1103
1104 static void
1105 _elm_fx_resizable_flip_end(void *data, Eina_Bool auto_reverse,
1106                            unsigned int repeat_cnt)
1107 {
1108    Elm_Fx_ResizableFlip *resizable_flip = data;
1109
1110    evas_object_map_enable_set(resizable_flip->front, EINA_FALSE);
1111    evas_object_map_enable_set(resizable_flip->back, EINA_FALSE);
1112 }
1113
1114 static void
1115 _set_image_uv_by_axis_y(Evas_Map *map, Elm_Fx_ResizableFlip *flip,
1116                         float degree)
1117 {
1118    if ((degree >= 90) || (degree <= -90))
1119      {
1120         evas_map_point_image_uv_set(map, 0,
1121                                     (flip->from_size.x * 2) + flip->to_size.x,
1122                                     0);
1123         evas_map_point_image_uv_set(map, 1, 0, 0);
1124         evas_map_point_image_uv_set(map, 2, 0,
1125                                     (flip->from_size.y * 2) + flip->to_size.y);
1126         evas_map_point_image_uv_set(map, 3,
1127                                     (flip->from_size.x * 2) + flip->to_size.x,
1128                                     (flip->from_size.y * 2) + flip->to_size.y);
1129      }
1130    else
1131      {
1132         evas_map_point_image_uv_set(map, 0, 0, 0);
1133         evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1134         evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1135                                     flip->from_size.y);
1136         evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1137      }
1138 }
1139
1140 static void
1141 _set_image_uv_by_axis_x(Evas_Map *map, Elm_Fx_ResizableFlip *flip,
1142                         float degree)
1143 {
1144    if ((degree >= 90) || (degree <= -90))
1145      {
1146         evas_map_point_image_uv_set(map, 0, 0,
1147                                     (flip->from_size.y * 2) + flip->to_size.y);
1148         evas_map_point_image_uv_set(map, 1,
1149                                     (flip->from_size.x * 2) + flip->to_size.x,
1150                                     (flip->from_size.y * 2) + flip->to_size.y);
1151         evas_map_point_image_uv_set(map, 2,
1152                                     (flip->from_size.x * 2) + flip->to_size.x,
1153                                     0);
1154         evas_map_point_image_uv_set(map, 3, 0, 0);
1155      }
1156    else
1157      {
1158         evas_map_point_image_uv_set(map, 0, 0, 0);
1159         evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1160         evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1161                                     flip->from_size.y);
1162         evas_map_point_image_uv_set(map, 3, 0, flip->to_size.y);
1163      }
1164 }
1165
1166 static void
1167 _elm_fx_resizable_flip_op(void *data, Elm_Animator *animator, double frame)
1168 {
1169    Elm_Fx_ResizableFlip *resizable_flip;
1170
1171    Evas_Map *map;
1172
1173    float degree;
1174
1175    Evas_Object *obj;
1176
1177    float x, y, w, h;
1178
1179    Evas_Coord half_w, half_h;
1180
1181    map = evas_map_new(4);
1182    if (!map)
1183       return;
1184
1185    resizable_flip = data;
1186
1187    if (resizable_flip->cw)
1188       degree = (float)(frame * 180);
1189    else
1190       degree = (float)(frame * -180);
1191
1192    if ((degree < 90) && (degree > -90))
1193      {
1194         obj = resizable_flip->front;
1195         if(resizable_flip->back != resizable_flip->front) {
1196                 evas_object_hide(resizable_flip->back);
1197                 evas_object_show(resizable_flip->front);
1198      }
1199           }
1200    else
1201      {
1202         obj = resizable_flip->back;
1203         if(resizable_flip->back != resizable_flip->front) {
1204                 evas_object_hide(resizable_flip->front);
1205                 evas_object_show(resizable_flip->back);
1206                 }
1207     }
1208    evas_map_smooth_set(map, EINA_TRUE);
1209
1210    x = resizable_flip->from_pos.x + (resizable_flip->to_pos.x * frame);
1211    y = resizable_flip->from_pos.y + (resizable_flip->to_pos.y * frame);
1212    w = resizable_flip->from_size.x + (resizable_flip->to_size.x * frame);
1213    h = resizable_flip->from_size.y + (resizable_flip->to_size.y * frame);
1214    evas_map_point_coord_set(map, 0, x, y, 0);
1215    evas_map_point_coord_set(map, 1, x + w, y, 0);
1216    evas_map_point_coord_set(map, 2, x + w, y + h, 0);
1217    evas_map_point_coord_set(map, 3, x, y + h, 0);
1218
1219    half_w = (Evas_Coord) (w / 2);
1220    half_h = (Evas_Coord) (h / 2);
1221
1222    if (resizable_flip->axis == ELM_FX_FLIP_AXIS_Y)
1223      {
1224         _set_image_uv_by_axis_y(map, resizable_flip, degree);
1225         evas_map_util_3d_rotate(map, 0, degree, 0, x + half_w, y + half_h, 0);
1226      }
1227    else
1228      {
1229         _set_image_uv_by_axis_x(map, resizable_flip, degree);
1230         evas_map_util_3d_rotate(map, degree, 0, 0, x + half_w, y + half_h, 0);
1231      }
1232
1233    evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, 10000);
1234    evas_object_map_enable_set(resizable_flip->front, EINA_TRUE);
1235    evas_object_map_enable_set(resizable_flip->back, EINA_TRUE);
1236    evas_object_map_set(obj, map);
1237    evas_map_free(map);
1238 }
1239
1240 /**
1241  * Add ResizbleFlip effect. the size of each surface objects are interpolated automatically.
1242  *
1243  * @param[in] front Front surface object 
1244  * @param[in] back Back surface object
1245  * @param[in] axis Flipping Axis.(X or Y)  
1246  * @param[in] cw Flipping Direction. EINA_TRUE is clock-wise
1247  * @return Flip effect 
1248  *
1249  * @ingroup Transit 
1250  */
1251 EAPI Elm_Effect *
1252 elm_fx_resizable_flip_add(Evas_Object *front, Evas_Object *back,
1253                           Elm_Fx_Flip_Axis axis, Eina_Bool cw)
1254 {
1255    Elm_Fx_ResizableFlip *resizable_flip;
1256
1257    Elm_Effect *effect;
1258
1259    Evas_Coord front_x, front_y, front_w, front_h;
1260
1261    Evas_Coord back_x, back_y, back_w, back_h;
1262
1263    if (!front || !back)
1264       return NULL;
1265
1266    effect = calloc(1, sizeof(Elm_Effect));
1267    if (!effect)
1268       return NULL;
1269
1270    resizable_flip = calloc(1, sizeof(Elm_Fx_ResizableFlip));
1271
1272    if (!resizable_flip)
1273      {
1274         free(effect);
1275         return NULL;
1276      }
1277
1278    resizable_flip->front = front;
1279    resizable_flip->back = back;
1280    resizable_flip->cw = cw;
1281    resizable_flip->axis = axis;
1282
1283    evas_object_geometry_get(resizable_flip->front, &front_x, &front_y, &front_w,
1284                             &front_h);
1285    evas_object_geometry_get(resizable_flip->back, &back_x, &back_y, &back_w,
1286                             &back_h);
1287
1288    resizable_flip->from_pos.x = front_x;
1289    resizable_flip->from_pos.y = front_y;
1290    resizable_flip->to_pos.x = back_x - front_x;
1291    resizable_flip->to_pos.y = back_y - front_y;
1292
1293    resizable_flip->from_size.x = front_w;
1294    resizable_flip->from_size.y = front_h;
1295    resizable_flip->to_size.x = back_w - front_w;
1296    resizable_flip->to_size.y = back_h - front_h;
1297
1298    effect->begin_op = _elm_fx_resizable_flip_begin;
1299    effect->end_op = _elm_fx_resizable_flip_end;
1300    effect->animation_op = _elm_fx_resizable_flip_op;
1301    effect->user_data = resizable_flip;
1302
1303    return effect;
1304 }
1305
1306 /////////////////////////////////////////////////////////////////////////////////////
1307 //Wipe FX
1308 /////////////////////////////////////////////////////////////////////////////////////
1309 typedef struct _wipe Elm_Fx_Wipe;
1310 static void _elm_fx_wipe_op(void *data, Elm_Animator *animator, 
1311                                 double frame);
1312 static void _elm_fx_wipe_begin(void *data, Eina_Bool auto_repeat, 
1313                                 unsigned int repeat_cnt);
1314 static void _elm_fx_wipe_end(void *data, Eina_Bool auto_repeat, 
1315                                 unsigned int repeat_cnt);
1316 static void _elm_fx_wipe_hide(Evas_Map * map, Elm_Fx_Wipe_Dir dir, 
1317                                 float x, float y, float w, float h, float frame);
1318 static void _elm_fx_wipe_show(Evas_Map *map, Elm_Fx_Wipe_Dir dir, 
1319                                 float x, float y, float w, float h, float frame);
1320
1321 struct _wipe
1322 {
1323    Evas_Object *obj;
1324    Elm_Fx_Wipe_Type type;
1325    Elm_Fx_Wipe_Dir dir;
1326 };
1327
1328 static void
1329 _elm_fx_wipe_begin(void *data, Eina_Bool auto_repeat, unsigned int repeat_cnt)
1330 {
1331    Elm_Fx_Wipe *wipe = data;
1332
1333    evas_object_show(wipe->obj);
1334    _elm_fx_wipe_op(data, NULL, 0);
1335 }
1336
1337 static void
1338 _elm_fx_wipe_end(void *data, Eina_Bool auto_repeat, unsigned int repeat_cnt)
1339 {
1340    Elm_Fx_Wipe *wipe = data;
1341
1342    evas_object_map_enable_set(wipe->obj, EINA_FALSE);
1343 }
1344
1345 static void
1346 _elm_fx_wipe_hide(Evas_Map * map, Elm_Fx_Wipe_Dir dir, float x, float y,
1347                   float w, float h, float frame)
1348 {
1349    float w2, h2;
1350
1351    switch (dir)
1352      {
1353    case ELM_FX_WIPE_DIR_UP:
1354         w2 = (x + w);
1355         h2 = h-(h * frame);
1356         evas_map_point_image_uv_set(map, 0, 0, 0);
1357         evas_map_point_image_uv_set(map, 1, w, 0);
1358         evas_map_point_image_uv_set(map, 2, w, h2);
1359         evas_map_point_image_uv_set(map, 3, 0, h2);
1360         evas_map_point_coord_set(map, 0, x, y, 0);
1361         evas_map_point_coord_set(map, 1, w2, y, 0);
1362         evas_map_point_coord_set(map, 2, w2, y+h2, 0);
1363         evas_map_point_coord_set(map, 3, x, y+h2, 0);
1364         break;
1365         case ELM_FX_WIPE_DIR_LEFT:
1366         w2 = w - (w * frame);
1367         h2 = (y + h);
1368         evas_map_point_image_uv_set(map, 0, 0, 0);
1369         evas_map_point_image_uv_set(map, 1, w2, 0);
1370         evas_map_point_image_uv_set(map, 2, w2, h);
1371         evas_map_point_image_uv_set(map, 3, 0, h);
1372         evas_map_point_coord_set(map, 0, x, y, 0);
1373         evas_map_point_coord_set(map, 1, x + w2, y, 0);
1374         evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1375         evas_map_point_coord_set(map, 3, x, h2, 0);
1376         break;
1377      case ELM_FX_WIPE_DIR_RIGHT:
1378         w2 = (w * frame);
1379         h2 = (y + h);
1380         evas_map_point_image_uv_set(map, 0, w2, 0);
1381         evas_map_point_image_uv_set(map, 1, w, 0);
1382         evas_map_point_image_uv_set(map, 2, w, h);
1383         evas_map_point_image_uv_set(map, 3, w2, h);
1384         evas_map_point_coord_set(map, 0, x + w2, y, 0);
1385         evas_map_point_coord_set(map, 1, x + w, y, 0);
1386         evas_map_point_coord_set(map, 2, x + w, h2, 0);
1387         evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1388         break;
1389      case ELM_FX_WIPE_DIR_DOWN:
1390         w2 = (x + w);
1391         h2 = (h * frame);
1392         evas_map_point_image_uv_set(map, 0, 0, h2);
1393         evas_map_point_image_uv_set(map, 1, w, h2);
1394         evas_map_point_image_uv_set(map, 2, w, h);
1395         evas_map_point_image_uv_set(map, 3, 0, h);
1396         evas_map_point_coord_set(map, 0, x, y + h2, 0);
1397         evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1398         evas_map_point_coord_set(map, 2, w2, y + h, 0);
1399         evas_map_point_coord_set(map, 3, x, y + h, 0);
1400         break;
1401      default:
1402         break;
1403      }
1404
1405    evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, 10000);
1406 }
1407
1408 static void
1409 _elm_fx_wipe_show(Evas_Map *map, Elm_Fx_Wipe_Dir dir, float x, float y,
1410                   float w, float h, float frame)
1411 {
1412    float w2, h2;
1413
1414    switch (dir)
1415      {
1416           case ELM_FX_WIPE_DIR_UP:
1417         w2 = (x + w);
1418         h2 = (h - (h * frame));
1419         evas_map_point_image_uv_set(map, 0, 0, h2);
1420         evas_map_point_image_uv_set(map, 1, w, h2);
1421         evas_map_point_image_uv_set(map, 2, w, h);
1422         evas_map_point_image_uv_set(map, 3, 0, h);
1423         evas_map_point_coord_set(map, 0, x, y + h2, 0);
1424         evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1425         evas_map_point_coord_set(map, 2, w2, y + h, 0);
1426         evas_map_point_coord_set(map, 3, x, y + h, 0);
1427         break;
1428      case ELM_FX_WIPE_DIR_LEFT:
1429         w2 = (w - (w * frame));
1430         h2 = (y + h);
1431         evas_map_point_image_uv_set(map, 0, w2, 0);
1432         evas_map_point_image_uv_set(map, 1, w, 0);
1433         evas_map_point_image_uv_set(map, 2, w, h);
1434         evas_map_point_image_uv_set(map, 3, w2, h);
1435         evas_map_point_coord_set(map, 0, x + w2, y, 0);
1436         evas_map_point_coord_set(map, 1, x + w, y, 0);
1437         evas_map_point_coord_set(map, 2, x +w, h2, 0);
1438         evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1439         break;
1440      case ELM_FX_WIPE_DIR_RIGHT:
1441         w2 = (w * frame);
1442         h2 = (y + h);
1443         evas_map_point_image_uv_set(map, 0, 0, 0);
1444         evas_map_point_image_uv_set(map, 1, w2, 0);
1445         evas_map_point_image_uv_set(map, 2, w2, h);
1446         evas_map_point_image_uv_set(map, 3, 0, h);
1447         evas_map_point_coord_set(map, 0, x, y, 0);
1448         evas_map_point_coord_set(map, 1, x + w2, y, 0);
1449         evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1450         evas_map_point_coord_set(map, 3, x, h2, 0);
1451         break;
1452      case ELM_FX_WIPE_DIR_DOWN:
1453         w2 = (x + w);
1454         h2 = (h * frame);
1455         evas_map_point_image_uv_set(map, 0, 0, 0);
1456         evas_map_point_image_uv_set(map, 1, w, 0);
1457         evas_map_point_image_uv_set(map, 2, w, h2);
1458         evas_map_point_image_uv_set(map, 3, 0, h2);
1459         evas_map_point_coord_set(map, 0, x, y, 0);
1460         evas_map_point_coord_set(map, 1, w2, y, 0);
1461         evas_map_point_coord_set(map, 2, w2, y + h2, 0);
1462         evas_map_point_coord_set(map, 3, x, y + h2, 0);
1463         break;
1464      default:
1465         break;
1466      }
1467
1468    evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, 10000);
1469 }
1470
1471 static void
1472 _elm_fx_wipe_op(void *data, Elm_Animator *animator, double frame)
1473 {
1474    Elm_Fx_Wipe *wipe;
1475
1476    Evas_Map *map;
1477
1478    Evas_Coord _x, _y, _w, _h;
1479
1480    map = evas_map_new(4);
1481    if (!map)
1482       return;
1483
1484    wipe = data;
1485    evas_map_smooth_set(map, EINA_TRUE);
1486    evas_object_geometry_get(wipe->obj, &_x, &_y, &_w, &_h);
1487
1488    if (wipe->type == ELM_FX_WIPE_TYPE_SHOW)
1489       _elm_fx_wipe_show(map, wipe->dir, _x, _y, _w, _h, (float)frame);
1490    else
1491       _elm_fx_wipe_hide(map, wipe->dir, _x, _y, _w, _h, (float)frame);
1492
1493    evas_object_map_enable_set(wipe->obj, EINA_TRUE);
1494    evas_object_map_set(wipe->obj, map);
1495    evas_map_free(map);
1496 }
1497
1498 /**
1499  * Add Wipe effect.  
1500  *
1501  * @param[in] obj Evas_Object that effect is applying to
1502  * @param[in] type Wipe type. Hide or show
1503  * @param[in] dir Wipe Direction
1504  * @return Wipe effect
1505  *
1506  * @ingroup Transit 
1507  */
1508 EAPI Elm_Effect *
1509 elm_fx_wipe_add(Evas_Object *obj, Elm_Fx_Wipe_Type type, Elm_Fx_Wipe_Dir dir)
1510 {
1511    Elm_Effect *effect;
1512
1513    Elm_Fx_Wipe *wipe;
1514
1515    if (!obj)
1516       return NULL;
1517
1518    effect = calloc(1, sizeof(Elm_Effect));
1519    if (!effect)
1520       return NULL;
1521
1522    wipe = calloc(1, sizeof(Elm_Fx_Wipe));
1523    if (!wipe)
1524      {
1525         free(effect);
1526         return NULL;
1527      }
1528
1529    wipe->obj = obj;
1530    wipe->type = type;
1531    wipe->dir = dir;
1532    effect->begin_op = _elm_fx_wipe_begin;
1533    effect->end_op = _elm_fx_wipe_end;
1534    effect->animation_op = _elm_fx_wipe_op;
1535    effect->user_data = wipe;
1536
1537    return effect;
1538 }
1539
1540 /////////////////////////////////////////////////////////////////////////////////////
1541 //Color FX
1542 /////////////////////////////////////////////////////////////////////////////////////
1543 typedef struct _color Elm_Fx_Color;
1544 static void _elm_fx_color_begin(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt);
1545 static void _elm_fx_color_op(void *data, Elm_Animator *animator, double frame);
1546
1547 struct _color
1548 {
1549    Evas_Object *obj;
1550    struct _unsigned_color
1551    {
1552       unsigned int r, g, b, a;
1553    } from;
1554    struct _signed_color
1555    {
1556       int r, g, b, a;
1557    } to;
1558 };
1559
1560 static void
1561 _elm_fx_color_begin(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
1562 {
1563    Elm_Fx_Color *color = data;
1564
1565    evas_object_show(color->obj);
1566 }
1567
1568 static void
1569 _elm_fx_color_op(void *data, Elm_Animator *animator, double frame)
1570 {
1571    Elm_Fx_Color *color;
1572
1573    unsigned int r, g, b, a;
1574
1575    color = data;
1576    r = (color->from.r + (int)((float)color->to.r * frame));
1577    g = (color->from.g + (int)((float)color->to.g * frame));
1578    b = (color->from.b + (int)((float)color->to.b * frame));
1579    a = (color->from.a + (int)((float)color->to.a * frame));
1580
1581    evas_object_color_set(color->obj, r, g, b, a);
1582 }
1583
1584 /**
1585  * Add Color effect.  
1586  *
1587  * @param[in]  obj           Evas_Object that effect is applying to
1588  * @param[in]  from_r        RGB R when effect begins
1589  * @param[in]  from_g        RGB G when effect begins 
1590  * @param[in]  from_b        RGB B when effect begins
1591  * @param[in]  from_a        RGB A when effect begins
1592  * @param[in]  to_r          RGB R when effect ends
1593  * @param[in]  to_g          RGB G when effect ends
1594  * @param[in]  to_b          RGB B when effect ends
1595  * @param[in]  to_a          RGB A when effect ends
1596  * @return               Color Effect
1597  *
1598  * @ingroup Transit 
1599  */
1600 EAPI Elm_Effect *
1601 elm_fx_color_add(Evas_Object *obj, unsigned int from_r, unsigned int from_g,
1602                  unsigned int from_b, unsigned int from_a, unsigned int to_r,
1603                  unsigned int to_g, unsigned int to_b, unsigned int to_a)
1604 {
1605    Elm_Effect *effect;
1606
1607    Elm_Fx_Color *color;
1608
1609    if (!obj)
1610       return NULL;
1611
1612    effect = calloc(1, sizeof(Elm_Effect));
1613    if (!effect)
1614       return NULL;
1615
1616    color = calloc(1, sizeof(Elm_Fx_Color));
1617    if (!color)
1618      {
1619         free(effect);
1620         return NULL;
1621      }
1622
1623    color->obj = obj;
1624    color->from.r = from_r;
1625    color->from.g = from_g;
1626    color->from.b = from_b;
1627    color->from.a = from_a;
1628    color->to.r = to_r - from_r;
1629    color->to.g = to_g - from_g;
1630    color->to.b = to_b - from_b;
1631    color->to.a = to_a - from_a;
1632
1633    effect->begin_op = _elm_fx_color_begin;
1634    effect->animation_op = _elm_fx_color_op;
1635    effect->user_data = color;
1636
1637    return effect;
1638 }
1639
1640 /////////////////////////////////////////////////////////////////////////////////////
1641 //Fade FX
1642 /////////////////////////////////////////////////////////////////////////////////////
1643 typedef struct _fade Elm_Fx_Fade;
1644 static void _elm_fx_fade_begin(void *data, Eina_Bool auto_reverse, 
1645                                 unsigned int repeat_cnt);
1646 static void _elm_fx_fade_end(void *data, Eina_Bool auto_reverse, 
1647                                 unsigned int repeat_cnt);
1648 static void _elm_fx_fade_op(void *data, Elm_Animator *animator, 
1649                                 double frame);
1650
1651 struct _fade
1652 {
1653    Evas_Object *before;
1654    Evas_Object *after;
1655    struct _signed_color before_color, after_color;
1656    int before_alpha;
1657    int after_alpha;
1658    Eina_Bool inversed:1;
1659 };
1660
1661 static void
1662 _elm_fx_fade_begin(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
1663 {
1664    Elm_Fx_Fade *fade = data;
1665
1666    fade->inversed = EINA_FALSE;
1667 }
1668
1669 static void
1670 _elm_fx_fade_end(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
1671 {
1672    Elm_Fx_Fade *fade = data;
1673
1674    evas_object_color_set(fade->before, fade->before_color.r,
1675                          fade->before_color.g, fade->before_color.b,
1676                          fade->before_color.a);
1677    evas_object_color_set(fade->after, fade->after_color.r, fade->after_color.g,
1678                          fade->after_color.b, fade->after_color.a);
1679 }
1680
1681 static void
1682 _elm_fx_fade_op(void *data, Elm_Animator *animator, double frame)
1683 {
1684    Elm_Fx_Fade *fade;
1685
1686    float _frame;
1687
1688    fade = data;
1689
1690    if (frame < 0.5)
1691      {
1692         if (!fade->inversed)
1693           {
1694              evas_object_hide(fade->after);
1695              evas_object_show(fade->before);
1696              fade->inversed = EINA_TRUE;
1697           }
1698
1699         _frame = (1 - (frame * 2));
1700
1701         evas_object_color_set(fade->before, fade->before_color.r * _frame,
1702                               fade->before_color.g * _frame,
1703                               fade->before_color.b * _frame,
1704                               fade->before_color.a + fade->before_alpha * (1 -
1705                                                                            _frame));
1706      }
1707    else
1708      {
1709         if (fade->inversed)
1710           {
1711              evas_object_hide(fade->before);
1712              evas_object_show(fade->after);
1713              fade->inversed = EINA_FALSE;
1714           }
1715
1716         _frame = ((frame - 0.5) * 2);
1717
1718         evas_object_color_set(fade->after, fade->after_color.r * _frame,
1719                               fade->after_color.g * _frame,
1720                               fade->after_color.b * _frame,
1721                               fade->after_color.a + fade->after_alpha * (1 -
1722                                                                          _frame));
1723      }
1724
1725 }
1726
1727 /**
1728  * Add Fade effect  
1729  *
1730  * @param[in] before Evas Object before fade in 
1731  * @param[in] after Evas Object after fade out 
1732  * @return Fade effect
1733  * 
1734  * @ingroup Transit 
1735  */
1736 EAPI Elm_Effect *
1737 elm_fx_fade_add(Evas_Object *before, Evas_Object *after)
1738 {
1739    Elm_Effect *effect;
1740
1741    Elm_Fx_Fade *fade;
1742
1743    if ((!before) && (!after))
1744       return NULL;
1745
1746    effect = calloc(1, sizeof(Elm_Effect));
1747    if (!effect)
1748       return NULL;
1749
1750    fade = calloc(1, sizeof(Elm_Fx_Fade));
1751
1752    if (!fade)
1753      {
1754         free(effect);
1755         return NULL;
1756      }
1757
1758    evas_object_color_get(before, &fade->before_color.r, &fade->before_color.g,
1759                          &fade->before_color.b, &fade->before_color.a);
1760    evas_object_color_get(after, &fade->after_color.r, &fade->after_color.g,
1761                          &fade->after_color.b, &fade->after_color.a);
1762
1763    fade->before = before;
1764    fade->after = after;
1765    fade->before_alpha = (255 - fade->before_color.a);
1766    fade->after_alpha = (255 - fade->after_color.a);
1767
1768    effect->begin_op = _elm_fx_fade_begin;
1769    effect->end_op = _elm_fx_fade_end;
1770    effect->animation_op = _elm_fx_fade_op;
1771    effect->user_data = fade;
1772
1773    return effect;
1774 }
1775
1776 /////////////////////////////////////////////////////////////////////////////////////
1777 //Blend FX
1778 /////////////////////////////////////////////////////////////////////////////////////
1779 typedef struct _blend Elm_Fx_Blend;
1780 static void _elm_fx_blend_begin(void *data, Eina_Bool auto_reverse, 
1781                                 unsigned int repeat_cnt);
1782 static void _elm_fx_blend_end(void *data, Eina_Bool auto_reverse, 
1783                                 unsigned int repeat_cnt);
1784 static void _elm_fx_blend_op(void *data, Elm_Animator *animator, 
1785                                 double frame);
1786
1787 struct _blend
1788 {
1789    Evas_Object *before;
1790    Evas_Object *after;
1791    struct _signed_color from, to;
1792 };
1793
1794 static void
1795 _elm_fx_blend_begin(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
1796 {
1797    Elm_Fx_Blend *blend = data;
1798
1799    evas_object_show(blend->before);
1800 }
1801
1802 static void
1803 _elm_fx_blend_end(void *data, Eina_Bool auto_reverse, unsigned int repeat_cnt)
1804 {
1805    Elm_Fx_Blend *blend = data;
1806
1807    evas_object_color_set(blend->before, blend->from.r, blend->from.g,
1808                          blend->from.b, blend->from.a);
1809    evas_object_color_set(blend->after, blend->to.r, blend->to.g, blend->to.b,
1810                          blend->to.a);
1811    if (!auto_reverse)
1812       evas_object_hide(blend->before);
1813    else
1814       evas_object_hide(blend->after);
1815 }
1816
1817 static void
1818 _elm_fx_blend_op(void *data, Elm_Animator *animator, double frame)
1819 {
1820    Elm_Fx_Blend *blend = data;
1821
1822    evas_object_show(blend->after);
1823    evas_object_color_set(blend->before, (int)(blend->from.r * (1 - frame)),
1824                          (int)(blend->from.g * (1 - frame)),
1825                          (int)(blend->from.b * (1 - frame)),
1826                          (int)(blend->from.a * (1 - frame)));
1827    evas_object_color_set(blend->after, (int)(blend->to.r * frame),
1828                          (int)(blend->to.g * frame), (int)(blend->to.b * frame),
1829                          (int)(blend->to.a * frame));
1830 }
1831
1832 /**
1833  * Add Blend effect  
1834  *
1835  * @param[in] before Evas Object before blending
1836  * @param[in] after Evas Object after blending 
1837  * @return Blend effect
1838  *
1839  * @ingroup Transit 
1840  */
1841 EAPI Elm_Effect *
1842 elm_fx_blend_add(Evas_Object *before, Evas_Object *after)
1843 {
1844    Elm_Effect *effect;
1845
1846    Elm_Fx_Blend *blend;
1847
1848    if ((!before) && (!after))
1849       return NULL;
1850
1851    effect = calloc(1, sizeof(Elm_Effect));
1852    if (!effect)
1853       return NULL;
1854
1855    blend = calloc(1, sizeof(Elm_Fx_Blend));
1856    if (!blend)
1857      {
1858         free(effect);
1859         return NULL;
1860      }
1861
1862    blend->before = before;
1863    blend->after = after;
1864    evas_object_color_get(before, &blend->from.r, &blend->from.g, &blend->from.b,
1865                          &blend->from.a);
1866    evas_object_color_get(after, &blend->to.r, &blend->to.g, &blend->to.b,
1867                          &blend->to.a);
1868
1869    effect->begin_op = _elm_fx_blend_begin;
1870    effect->end_op = _elm_fx_blend_end;
1871    effect->animation_op = _elm_fx_blend_op;
1872    effect->user_data = blend;
1873
1874    return effect;
1875 }
1876
1877 /////////////////////////////////////////////////////////////////////////////////////
1878 //Rotation FX
1879 /////////////////////////////////////////////////////////////////////////////////////
1880 typedef struct _rotation Elm_Fx_Rotation;
1881 static void _elm_fx_rotation_begin(void *data, Eina_Bool auto_reverse, 
1882                                 unsigned int repeat_cnt);
1883 static void _elm_fx_rotation_end(void *data, Eina_Bool auto_reverse, 
1884                                 unsigned int repeat_cnt);
1885 static void _elm_fx_rotation_op(void *data, Elm_Animator *animator, 
1886                                 double frame);
1887
1888 struct _rotation
1889 {
1890    Evas_Object *obj;
1891    Eina_Bool cw;
1892    float from, to;
1893 };
1894
1895 static void
1896 _elm_fx_rotation_begin(void *data, Eina_Bool auto_reverse,
1897                        unsigned int repeat_cnt)
1898 {
1899    Elm_Fx_Rotation *rotation = data;
1900
1901    evas_object_show(rotation->obj);
1902 }
1903
1904 static void
1905 _elm_fx_rotation_end(void *data, Eina_Bool auto_reverse,
1906                      unsigned int repeat_cnt)
1907 {
1908    Elm_Fx_Rotation *rotation = data;
1909
1910    evas_object_map_enable_set(rotation->obj, EINA_FALSE);
1911 }
1912
1913 static void
1914 _elm_fx_rotation_op(void *data, Elm_Animator *animator, double frame)
1915 {
1916    Elm_Fx_Rotation *rotation;
1917
1918    Evas_Map *map;
1919
1920    Evas_Coord x, y, w, h;
1921
1922    float degree;
1923
1924    float half_w, half_h;
1925
1926    map = evas_map_new(4);
1927    if (!map)
1928       return;
1929
1930    rotation = data;
1931
1932    evas_map_smooth_set(map, EINA_TRUE);
1933    evas_map_util_points_populate_from_object_full(map, rotation->obj, 0);
1934    degree = rotation->from + (float)(frame * rotation->to);
1935
1936    if (!rotation->cw)
1937       degree *= -1;
1938
1939    evas_object_geometry_get(rotation->obj, &x, &y, &w, &h);
1940
1941    half_w = (float)w *0.5;
1942
1943    half_h = (float)h *0.5;
1944
1945    evas_map_util_3d_rotate(map, 0, 0, degree, x + half_w, y + half_h, 0);
1946    evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, 10000);
1947    evas_object_map_enable_set(rotation->obj, EINA_TRUE);
1948    evas_object_map_set(rotation->obj, map);
1949    evas_map_free(map);
1950 }
1951
1952 /**
1953  * Add Rotation effect
1954  *
1955  * @param[in] obj Evas_Object that effect is applying to 
1956  * @param[in] from degree Degree when effect begins
1957  * @param[in] to_degree Degree when effect is ends
1958  * @param[in] cw Rotation direction. EINA_TRUE is clock wise
1959  * @return Rotation effect
1960  *
1961  * @ingroup Transit 
1962  */
1963 EAPI Elm_Effect *
1964 elm_fx_rotation_add(Evas_Object *obj, float from_degree, float to_degree,
1965                     Eina_Bool cw)
1966 {
1967    Elm_Effect *effect;
1968
1969    Elm_Fx_Rotation *rotation;
1970
1971    if (!obj)
1972       return NULL;
1973
1974    effect = calloc(1, sizeof(Elm_Effect));
1975    if (!effect)
1976       return NULL;
1977
1978    rotation = calloc(1, sizeof(Elm_Fx_Rotation));
1979
1980    if (!rotation)
1981      {
1982         free(effect);
1983         return NULL;
1984      }
1985
1986    rotation->obj = obj;
1987    rotation->from = from_degree;
1988    rotation->to = to_degree - from_degree;
1989    rotation->cw = cw;
1990
1991    effect->begin_op = _elm_fx_rotation_begin;
1992    effect->end_op = _elm_fx_rotation_end;
1993    effect->animation_op = _elm_fx_rotation_op;
1994    effect->user_data = rotation;
1995
1996    return effect;
1997 }
1998
1999
2000
2001
2002 /////////////////////////////////////////////////////////////////////////////////////
2003 //Rotation3d FX
2004 /////////////////////////////////////////////////////////////////////////////////////
2005 typedef struct _rotation3d Elm_Fx_Rotation3d;
2006 static void _elm_fx_rotation3d_begin(void *data, Eina_Bool auto_reverse,
2007                                 unsigned int repeat_cnt);
2008 static void _elm_fx_rotation3d_end(void *data, Eina_Bool auto_reverse,
2009                                 unsigned int repeat_cnt);
2010 static void _elm_fx_rotation3d_op(void *data, Elm_Animator *animator,
2011                                 double frame);
2012
2013 struct _rotation3d
2014 {
2015    Evas_Object *obj;
2016    float from[3];
2017    float to[3];
2018    float axis_pos[3];
2019 };
2020
2021 static void
2022 _elm_fx_rotation3d_begin(void *data, Eina_Bool auto_reverse,
2023                        unsigned int repeat_cnt)
2024 {
2025    Elm_Fx_Rotation3d *rotation = data;
2026    evas_object_show(rotation->obj);
2027 }
2028
2029 static void
2030 _elm_fx_rotation3d_end(void *data, Eina_Bool auto_reverse,
2031                      unsigned int repeat_cnt)
2032 {
2033    Elm_Fx_Rotation3d *rotation = data;
2034    evas_object_map_enable_set(rotation->obj, EINA_FALSE);
2035 }
2036
2037 static void
2038 _elm_fx_rotation3d_op(void *data, Elm_Animator *animator, double frame)
2039 {
2040    Elm_Fx_Rotation3d *rotation;
2041
2042    Evas_Map *map;
2043
2044    Evas_Coord x, y, w, h;
2045
2046    float degree[3];
2047
2048    float half_w, half_h;
2049
2050    map = evas_map_new(4);
2051    if (!map)
2052       return;
2053
2054    rotation = data;
2055
2056    evas_map_smooth_set(map, EINA_TRUE);
2057    evas_map_util_points_populate_from_object_full(map, rotation->obj, 0);
2058    degree[0] = rotation->from[0] + (float)(frame * rotation->to[0]);
2059    degree[1] = rotation->from[1] + (float)(frame * rotation->to[1]);
2060    degree[2] = rotation->from[2] + (float)(frame * rotation->to[2]);
2061
2062    evas_object_geometry_get(rotation->obj, &x, &y, &w, &h);
2063
2064    half_w = (float)w *0.5;
2065
2066    half_h = (float)h *0.5;
2067
2068    evas_map_util_3d_rotate(map, degree[0], degree[1], degree[2], rotation->axis_pos[0], rotation->axis_pos[1], rotation->axis_pos[2]);
2069    evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, 1000);
2070    evas_object_map_enable_set(rotation->obj, EINA_TRUE);
2071    evas_object_map_set(rotation->obj, map);
2072    evas_map_free(map);
2073 }
2074
2075 /**
2076  * Add Rotation3d effect
2077  *
2078  * @param[in] obj Evas_Object that effect is applying to
2079  * @param[in] from degree Degree when effect begins
2080  * @param[in] to_degree Degree when effect is ends
2081  * @param[in] axis_dir[3] rotation axis vector. it should be normalized.
2082  * @param[in] axis_pos[3] rotation axis origin position.
2083  * @param[in] cw Rotation direction. EINA_TRUE is clock wise
2084  * @return Rotation effect
2085  *
2086  * @ingroup Transit
2087  */
2088 EAPI Elm_Effect *
2089 elm_fx_rotation3d_add(Evas_Object *obj, float from_degree, float to_degree,
2090                 float* axis_dir, float* axis_pos)
2091 {
2092    Elm_Effect *effect;
2093
2094    Elm_Fx_Rotation3d *rotation;
2095
2096    if (!obj)
2097       return NULL;
2098
2099    effect = calloc(1, sizeof(Elm_Effect));
2100    if (!effect)
2101       return NULL;
2102
2103    rotation = calloc(1, sizeof(Elm_Fx_Rotation3d));
2104
2105    if (!rotation)
2106      {
2107         free(effect);
2108         return NULL;
2109      }
2110
2111    rotation->obj = obj;
2112    rotation->from[0] = from_degree * axis_dir[0];
2113    rotation->from[1] = from_degree * axis_dir[1];
2114    rotation->from[2] = from_degree * axis_dir[2];
2115    rotation->to[0] = (to_degree * axis_dir[0]) - rotation->from[0];
2116    rotation->to[1] = (to_degree * axis_dir[1]) - rotation->from[1];
2117    rotation->to[2] = (to_degree * axis_dir[2]) - rotation->from[2];
2118    rotation->axis_pos[0] = axis_pos[0];
2119    rotation->axis_pos[1] = axis_pos[1];
2120    rotation->axis_pos[2] = axis_pos[2];
2121
2122    effect->begin_op = _elm_fx_rotation3d_begin;
2123    effect->end_op = _elm_fx_rotation3d_end;
2124    effect->animation_op = _elm_fx_rotation3d_op;
2125    effect->user_data = rotation;
2126
2127    return effect;
2128 }
2129
2130
2131
2132 /////////////////////////////////////////////////////////////////////////////////////
2133 // ImageAnimation FX
2134 /////////////////////////////////////////////////////////////////////////////////////
2135 typedef struct _image_animation Elm_Fx_Image_Animation;
2136 static void _elm_fx_image_animation_begin(void *data, Eina_Bool auto_reverse,
2137                        unsigned int repeat_cnt);
2138 static void _elm_fx_image_animation_op(void *data, Elm_Animator *animator, 
2139                                 double frame);
2140 EAPI Elm_Effect *elm_fx_image_animation_add(Evas_Object *obj, const char **images, 
2141                                 unsigned int item_num);
2142
2143 struct _image_animation
2144 {
2145    Evas_Object *obj;
2146    char **images;
2147    int img_cnt;
2148 };
2149
2150
2151 static void
2152 _elm_fx_image_animation_begin(void *data, Eina_Bool auto_reverse,
2153                        unsigned int repeat_cnt)
2154 {
2155    Elm_Fx_Image_Animation *image_animation = data;
2156    evas_object_show(image_animation->obj);
2157 }
2158
2159
2160 static void
2161 _elm_fx_image_animation_op(void *data, Elm_Animator *animator, double frame)
2162 {
2163    Elm_Fx_Image_Animation *image_animation = (Elm_Fx_Image_Animation *) data;
2164
2165    elm_icon_file_set(image_animation->obj,
2166                      image_animation->images[ (int) floor(frame * (image_animation->img_cnt-1)) ], NULL);
2167 }
2168
2169 static void
2170 _elm_fx_image_animation_del(void *data)
2171 {
2172         int idx;
2173         Elm_Fx_Image_Animation *image_animation = data;
2174
2175         for(idx = 0; idx < image_animation->img_cnt; ++idx ) {
2176                 eina_stringshare_del(image_animation->images[ idx ]);
2177         }
2178
2179         free(image_animation->images);
2180 }
2181
2182 /**
2183  * Add image_animation effect.  
2184  *
2185  * @param[in] obj Icon object
2186  * @param[in] images Array of image file path. 
2187  * @param[in] img_cnt Count of image. 
2188  * @return ImageAnimation effect.
2189  *
2190  * @ingroup Transit 
2191  */
2192 EAPI Elm_Effect *
2193 elm_fx_image_animation_add(Evas_Object *obj, const char **images,
2194                           unsigned int img_cnt)
2195 {
2196    Elm_Effect *effect;
2197    Elm_Fx_Image_Animation *image_animation;
2198    int idx;
2199
2200    if ((!obj) || !images || !(*images))
2201       return NULL;
2202
2203    effect = calloc(1, sizeof(Elm_Effect));
2204    if (!effect)
2205       return NULL;
2206
2207    image_animation = calloc(1, sizeof(Elm_Fx_Image_Animation));
2208
2209    if (!image_animation)
2210      {
2211         free(effect);
2212         return NULL;
2213      }
2214
2215    image_animation->obj = obj;
2216    image_animation->images = calloc( img_cnt, sizeof(char*));
2217    for(idx = 0; idx < img_cnt; ++idx )
2218            image_animation->images[ idx ] = eina_stringshare_add( images[ idx ] );
2219
2220    image_animation->img_cnt = img_cnt;
2221
2222    effect->begin_op = _elm_fx_image_animation_begin;
2223    effect->animation_op = _elm_fx_image_animation_op;
2224    effect->del_op = _elm_fx_image_animation_del;
2225    effect->user_data = image_animation;
2226
2227    return effect;
2228 }