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