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