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