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