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