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