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