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