1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include <stdlib.h>
6 #include <math.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 
12 #if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_SYS_TIMERFD_H)
13 # define HAVE_EPOLL   1
14 # include <sys/epoll.h>
15 # include <sys/timerfd.h>
16 #endif
17 
18 #ifdef _WIN32
19 
20 # include <winsock2.h>
21 # include <evil_private.h> /* pipe */
22 
23 # define pipe_write(fd, buffer, size) send((fd), (char *)(buffer), size, 0)
24 # define pipe_read(fd, buffer, size)  recv((fd), (char *)(buffer), size, 0)
25 # define pipe_close(fd)               closesocket(fd)
26 # define PIPE_FD_ERROR   SOCKET_ERROR
27 
28 #else
29 
30 # include <sys/select.h>
31 # include <fcntl.h>
32 
33 # define pipe_write(fd, buffer, size) write((fd), buffer, size)
34 # define pipe_read(fd, buffer, size)  read((fd), buffer, size)
35 # define pipe_close(fd)               close(fd)
36 # define PIPE_FD_ERROR   -1
37 
38 #endif /* ! _WIN32 */
39 
40 #ifdef HAVE_PRCTL
41 # include <sys/prctl.h>
42 #endif
43 
44 #include "Ecore.h"
45 #include "ecore_private.h"
46 
47 static int _ecore_anim_log_dom = -1;
48 static Eina_Bool _ee_animators_setup = EINA_FALSE;
49 
50 #ifdef ERR
51 # undef ERR
52 #endif
53 #define ERR(...) EINA_LOG_DOM_ERR(_ecore_anim_log_dom, __VA_ARGS__)
54 
55 #ifdef DBG
56 # undef DBG
57 #endif
58 #define DBG(...) EINA_LOG_DOM_DBG(_ecore_anim_log_dom, __VA_ARGS__)
59 
60 #ifdef INF
61 # undef INF
62 #endif
63 #define INF(...) EINA_LOG_DOM_INFO(_ecore_anim_log_dom, __VA_ARGS__)
64 
65 #ifdef WRN
66 # undef WRN
67 #endif
68 #define WRN(...) EINA_LOG_DOM_WARN(_ecore_anim_log_dom, __VA_ARGS__)
69 
70 #ifdef CRI
71 # undef CRI
72 #endif
73 #define CRI(...) EINA_LOG_DOM_CRIT(_ecore_anim_log_dom, __VA_ARGS__)
74 
75 static void _do_tick(void);
76 static Eina_Bool _ecore_animator_run(void *data);
77 
78 static int animators_delete_me = 0;
79 static Ecore_Animator *animators = NULL;
80 static volatile double animators_frametime = 1.0 / 60.0;
81 static unsigned int animators_suspended = 0;
82 
83 static Ecore_Animator_Source src = ECORE_ANIMATOR_SOURCE_TIMER;
84 static int ticking = 0;
85 static Ecore_Cb begin_tick_cb = NULL;
86 static const void *begin_tick_data = NULL;
87 static Ecore_Cb end_tick_cb = NULL;
88 static const void *end_tick_data = NULL;
89 static Eina_Bool animator_ran = EINA_FALSE;
90 
91 static volatile int timer_fd_read = -1;
92 static volatile int timer_fd_write = -1;
93 static Ecore_Thread *timer_thread = NULL;
94 static volatile int timer_event_is_busy = 0;
95 static Eina_Spinlock tick_queue_lock;
96 static int           tick_queue_count = 0;
97 static Eina_Bool     tick_skip = EINA_FALSE;
98 
99 #ifndef _WIN32
100 extern volatile int exit_signal_received;
101 #endif
102 
103 static Ecore_Evas_Object_Animator_Interface _anim_iface;
104 
105 static void
_tick_send(signed char val)106 _tick_send(signed char val)
107 {
108    DBG("_tick_send(%i)", val);
109    if (pipe_write(timer_fd_write, &val, 1) != 1)
110      {
111         ERR("Cannot write to animator control fd");
112      }
113 }
114 
115 static void
_timer_send_time(double t,Ecore_Thread * thread)116 _timer_send_time(double t, Ecore_Thread *thread)
117 {
118    double *tim = malloc(sizeof(*tim));
119    if (tim)
120      {
121         *tim = t;
122         DBG("   ... send %1.8f", t);
123         eina_spinlock_take(&tick_queue_lock);
124         tick_queue_count++;
125         eina_spinlock_release(&tick_queue_lock);
126         ecore_thread_feedback(thread, tim);
127      }
128 }
129 
130 static void
_timer_tick_core(void * data EINA_UNUSED,Ecore_Thread * thread)131 _timer_tick_core(void *data EINA_UNUSED, Ecore_Thread *thread)
132 {
133 #ifdef HAVE_EPOLL
134    int pollfd = -1, timerfd = -1;
135    struct epoll_event pollev = { 0 };
136    struct epoll_event pollincoming[2];
137    uint64_t timerfdbuf;
138    int i;
139    unsigned int t_ft;
140    double pframetime = -1.0;
141    struct itimerspec tspec_new;
142    struct itimerspec tspec_old;
143 #endif
144    fd_set rfds, wfds, exfds;
145    struct timeval tv;
146    Eina_Bool data_control;
147    Eina_Bool data_timeout;
148    unsigned int t;
149    signed char tick = 0;
150    double t0, d, ft;
151    int ret;
152 
153    eina_thread_name_set(eina_thread_self(), "Eanimator-timer");
154 #ifdef HAVE_PRCTL
155    prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
156 #endif
157 
158 #ifdef HAVE_EPOLL
159    pollfd = epoll_create(1);
160    if (pollfd >= 0) eina_file_close_on_exec(pollfd, EINA_TRUE);
161 
162 #if defined(TFD_NONBLOCK) && defined(TFD_CLOEXEC)
163    timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
164 #endif
165    if (timerfd < 0)
166      {
167         timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
168         if (timerfd >= 0) eina_file_close_on_exec(timerfd, EINA_TRUE);
169      }
170    if ((timerfd < 0) && (pollfd >= 0))
171      {
172         close(pollfd);
173         pollfd = -1;
174      }
175 
176 #define INPUT_TIMER_CONTROL (&(pollincoming[0]))
177 #define INPUT_TIMER_TIMERFD (&(pollincoming[1]))
178 
179    if (pollfd >= 0)
180      {
181         pollev.data.ptr = INPUT_TIMER_CONTROL;
182         pollev.events = EPOLLIN;
183         if (epoll_ctl(pollfd, EPOLL_CTL_ADD, timer_fd_read, &pollev) != 0)
184           {
185              close(timerfd);
186              timerfd = -1;
187              close(pollfd);
188              pollfd = -1;
189           }
190         if (pollfd >= 0)
191           {
192              pollev.data.ptr = INPUT_TIMER_TIMERFD;
193              pollev.events = EPOLLIN;
194              if (epoll_ctl(pollfd, EPOLL_CTL_ADD, timerfd, &pollev) != 0)
195                {
196                   close(timerfd);
197                   timerfd = -1;
198                   close(pollfd);
199                   pollfd = -1;
200                }
201           }
202      }
203 
204    if (pollfd >= 0)
205      {
206         while (!ecore_thread_check(thread))
207           {
208              data_control = EINA_FALSE;
209              data_timeout = EINA_FALSE;
210              ft = animators_frametime;
211 
212              DBG("------- timer_event_is_busy=%i", timer_event_is_busy);
213 
214              t0 = ecore_time_get();
215              d = fmod(t0, ft);
216              if (tick)
217                {
218                   if (!EINA_DBL_EQ(pframetime, ft))
219                     {
220                        t = (ft - d) * 1000000000.0;
221                        t_ft = ft * 1000000000.0;
222                        tspec_new.it_value.tv_sec = t / 1000000000;
223                        tspec_new.it_value.tv_nsec = t % 1000000000;
224                        tspec_new.it_interval.tv_sec = t_ft / 1000000000;
225                        tspec_new.it_interval.tv_nsec = t_ft % 1000000000;
226                        timerfd_settime(timerfd, 0, &tspec_new, &tspec_old);
227                        pframetime = ft;
228                     }
229                   DBG("sleep...");
230                   ret = epoll_wait(pollfd, pollincoming, 2, -1);
231                }
232              else
233                {
234                   tspec_new.it_value.tv_sec = 0;
235                   tspec_new.it_value.tv_nsec = 0;
236                   tspec_new.it_interval.tv_sec = 0;
237                   tspec_new.it_interval.tv_nsec = 0;
238                   pframetime = -1.0;
239                   timerfd_settime(timerfd, 0, &tspec_new, &tspec_old);
240                   DBG("wait...");
241                   ret = epoll_wait(pollfd, pollincoming, 2, -1);
242                }
243 
244              for (i = 0; i < ret; i++)
245                {
246                   if (pollincoming[i].events & EPOLLIN)
247                     {
248                        if (pollincoming[i].data.ptr == INPUT_TIMER_TIMERFD)
249                          {
250                             if (read(timerfd, &timerfdbuf, sizeof(timerfdbuf)) == -1)
251                               {
252                                  ERR("Cannot read from timer descriptor. %m.");
253                               }
254                             data_timeout = EINA_TRUE;
255                          }
256                        else if (pollincoming[i].data.ptr == INPUT_TIMER_CONTROL)
257                          data_control = EINA_TRUE;
258                     }
259                }
260              if (data_control)
261                {
262                   if (pipe_read(timer_fd_read, &tick, sizeof(tick)) != 1)
263                     {
264                        ERR("Cannot read from animator control fd");
265                     }
266                   DBG("tick = %i", tick);
267                   if (tick == -1) goto done;
268                }
269              else if (data_timeout)
270                {
271                   if (tick) _timer_send_time(t0 - d + ft, thread);
272                }
273           }
274      }
275    else
276 #endif
277      {
278         while (!ecore_thread_check(thread))
279           {
280              data_control = EINA_FALSE;
281              data_timeout = EINA_FALSE;
282              ft = animators_frametime;
283 
284              DBG("------- timer_event_is_busy=%i", timer_event_is_busy);
285              FD_ZERO(&rfds);
286              FD_ZERO(&wfds);
287              FD_ZERO(&exfds);
288              FD_SET(timer_fd_read, &rfds);
289 
290              t0 = ecore_time_get();
291              d = fmod(t0, ft);
292              if (tick)
293                {
294                   DBG("sleep...");
295                   t = (animators_frametime - d) * 1000000.0;
296                   tv.tv_sec = t / 1000000;
297                   tv.tv_usec = t % 1000000;
298                   ret = select(timer_fd_read + 1, &rfds, &wfds, &exfds, &tv);
299                }
300              else
301                {
302                   DBG("wait...");
303                   ret = select(timer_fd_read + 1, &rfds, &wfds, &exfds, NULL);
304                }
305              if ((ret == 1) && (FD_ISSET(timer_fd_read, &rfds)))
306                data_control = EINA_TRUE;
307              else if (ret == 0)
308                data_timeout = EINA_TRUE;
309              if (data_control)
310                {
311                   if (pipe_read(timer_fd_read, &tick, sizeof(tick)) != 1)
312                     {
313                        ERR("Cannot read from animator control fd");
314                     }
315                   DBG("tick = %i", tick);
316                   if (tick == -1) goto done;
317                }
318              else if (data_timeout)
319                {
320                   if (tick) _timer_send_time(t0 - d + ft, thread);
321                }
322           }
323      }
324 done:
325 #ifdef HAVE_EPOLL
326    if (pollfd >= 0)
327      {
328         close(pollfd);
329         pollfd = -1;
330      }
331    if (timerfd >= 0)
332      {
333         close(timerfd);
334         timerfd = -1;
335      }
336 #endif
337    pipe_close(timer_fd_read);
338    timer_fd_read = -1;
339    pipe_close(timer_fd_write);
340    timer_fd_write = -1;
341 }
342 
343 static void
_timer_tick_notify(void * data EINA_UNUSED,Ecore_Thread * thread EINA_UNUSED,void * msg)344 _timer_tick_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void *msg)
345 {
346    int tick_queued;
347 
348    eina_spinlock_take(&tick_queue_lock);
349    tick_queued = tick_queue_count;
350    tick_queue_count--;
351    eina_spinlock_release(&tick_queue_lock);
352    DBG("notify.... %3.3f %i", *((double *)msg), timer_event_is_busy);
353    if (timer_event_is_busy)
354      {
355         double *t = msg;
356         static double pt = 0.0;
357 
358         DBG("VSYNC %1.8f = delt %1.8f", *t, *t - pt);
359         if ((!tick_skip) || (tick_queued == 1))
360           {
361              ecore_loop_time_set(*t);
362 #ifndef _WIN32
363              if (!exit_signal_received)
364 #endif
365                _do_tick();
366              _ecore_animator_flush();
367           }
368         pt = *t;
369      }
370    free(msg);
371 }
372 
373 static void
_timer_tick_finished(void * data EINA_UNUSED,Ecore_Thread * thread EINA_UNUSED)374 _timer_tick_finished(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED)
375 {
376    eina_spinlock_free(&tick_queue_lock);
377    timer_thread = NULL;
378    tick_queue_count = 0;
379    if (timer_fd_read >= 0)
380      {
381         pipe_close(timer_fd_read);
382         timer_fd_read = -1;
383      }
384    if (timer_fd_write >= 0)
385      {
386         pipe_close(timer_fd_write);
387         timer_fd_write = -1;
388      }
389 }
390 
391 static void
_timer_tick_begin(void)392 _timer_tick_begin(void)
393 {
394    if (timer_fd_read < 0)
395      {
396         int fds[2];
397 
398         if (pipe(fds) != 0) return;
399         eina_file_close_on_exec(fds[0], EINA_TRUE);
400         eina_file_close_on_exec(fds[1], EINA_TRUE);
401         timer_fd_read = fds[0];
402         timer_fd_write = fds[1];
403         if (getenv("ECORE_ANIMATOR_SKIP")) tick_skip = EINA_TRUE;
404         tick_queue_count = 0;
405         eina_spinlock_new(&tick_queue_lock);
406         timer_thread = ecore_thread_feedback_run(_timer_tick_core,
407                                                  _timer_tick_notify,
408                                                  _timer_tick_finished,
409                                                  _timer_tick_finished,
410                                                  NULL, EINA_TRUE);
411      }
412    timer_event_is_busy = 1;
413    _tick_send(1);
414 }
415 
416 static void
_timer_tick_end(void)417 _timer_tick_end(void)
418 {
419    if (timer_fd_read < 0) return;
420    timer_event_is_busy = 0;
421    _tick_send(0);
422 }
423 
424 static void
_timer_tick_quit(void)425 _timer_tick_quit(void)
426 {
427    if (timer_fd_read < 0) return;
428    _tick_send(-1);
429    if (timer_thread) ecore_thread_wait(timer_thread, 0.5);
430 }
431 
432 static Eina_Bool
_have_animators(void)433 _have_animators(void)
434 {
435    if ((animators) &&
436        (animators_suspended < eina_inlist_count(EINA_INLIST_GET(animators)))
437       )
438      return EINA_TRUE;
439    return EINA_FALSE;
440 }
441 
442 static void
_begin_tick(void)443 _begin_tick(void)
444 {
445    if (ticking) return;
446    eina_evlog(">animator", NULL, 0.0, NULL);
447    ticking = 1;
448    switch (src)
449      {
450       case ECORE_ANIMATOR_SOURCE_TIMER:
451         DBG("General animator registered with timer source.");
452         _timer_tick_begin();
453         break;
454 
455       case ECORE_ANIMATOR_SOURCE_CUSTOM:
456         DBG("General animator registered with custom source.");
457         if (begin_tick_cb) begin_tick_cb((void *)begin_tick_data);
458         break;
459 
460       default:
461         break;
462      }
463 }
464 
465 static void
_end_tick(void)466 _end_tick(void)
467 {
468    if (!ticking) return;
469    eina_evlog("<animator", NULL, 0.0, NULL);
470    ticking = 0;
471 
472    DBG("General animator unregistered.");
473 
474    _timer_tick_end();
475 
476    if ((src == ECORE_ANIMATOR_SOURCE_CUSTOM) && end_tick_cb)
477      end_tick_cb((void *)end_tick_data);
478 }
479 
480 static void
_do_tick(void)481 _do_tick(void)
482 {
483    Ecore_Animator *animator;
484    Eina_Inlist *tmp;
485 
486    DBG("General animator tick.");
487    EINA_INLIST_FOREACH(animators, animator)
488      {
489         animator->just_added = EINA_FALSE;
490      }
491    if (animators) eina_evlog("!FRAME", NULL, ecore_loop_time_get(), NULL);
492    EINA_INLIST_FOREACH_SAFE(animators, tmp, animator)
493      {
494         if ((!animator->delete_me) &&
495             (!animator->suspended) &&
496             (!animator->just_added))
497           {
498              animator_ran = EINA_TRUE;
499              eina_evlog("+animator", animator, 0.0, NULL);
500              if (!_ecore_call_task_cb(animator->func, animator->data))
501                {
502                   animator->delete_me = EINA_TRUE;
503                   animators_delete_me++;
504                }
505              eina_evlog("-animator", animator, 0.0, NULL);
506           }
507         else animator->just_added = EINA_FALSE;
508      }
509 }
510 
511 static Ecore_Animator *
_ecore_animator_add(Ecore_Task_Cb func,const void * data)512 _ecore_animator_add(Ecore_Task_Cb func,
513                     const void   *data)
514 {
515    Ecore_Animator *animator;
516 
517    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
518 
519    if (!func)
520      {
521         ERR("callback function must be set up for an Ecore_Animator object.");
522         return NULL;
523      }
524 
525    animator = calloc(1, sizeof (Ecore_Animator));
526    if (!animator) return NULL;
527 
528    animator->func = func;
529    animator->data = (void *)data;
530    animator->just_added = EINA_TRUE;
531    animators = (Ecore_Animator *)eina_inlist_append(EINA_INLIST_GET(animators), EINA_INLIST_GET(animator));
532    _begin_tick();
533 
534    return animator;
535 }
536 
537 EAPI Ecore_Animator *
ecore_animator_add(Ecore_Task_Cb func,const void * data)538 ecore_animator_add(Ecore_Task_Cb func,
539                    const void   *data)
540 {
541    return _ecore_animator_add(func, data);
542 }
543 
544 EAPI Ecore_Animator *
ecore_animator_timeline_add(double runtime,Ecore_Timeline_Cb func,const void * data)545 ecore_animator_timeline_add(double            runtime,
546                             Ecore_Timeline_Cb func,
547                             const void       *data)
548 {
549    Ecore_Animator *animator;
550 
551    if (runtime <= 0.0) runtime = 0.0;
552 
553    animator = _ecore_animator_add(_ecore_animator_run, NULL);
554    if (!animator)
555      return NULL;
556 
557    animator->data = animator;
558    animator->run_func = func;
559    animator->run_data = (void *)data;
560    animator->start = ecore_loop_time_get();
561    animator->run = runtime;
562 
563    return animator;
564 }
565 
566 static double
_pos_map_sin(double in)567 _pos_map_sin(double in)
568 {
569    return eina_f32p32_double_to(eina_f32p32_sin(eina_f32p32_double_from(in)));
570 }
571 
572 #if 0
573 static double
574 _pos_map_cos(double in)
575 {
576    return eina_f32p32_double_to(eina_f32p32_cos(eina_f32p32_double_from(in)));
577 }
578 #endif
579 
580 static double
_pos_map_accel_factor(double pos,double v1)581 _pos_map_accel_factor(double pos,
582                       double v1)
583 {
584    int i, fact = (int)v1;
585    double p, o1 = pos, o2, v;
586    p = 1.0 - _pos_map_sin((M_PI / 2.0) + ((pos * M_PI) / 2.0));
587    o2 = p;
588    for (i = 0; i < fact; i++)
589      {
590         o1 = o2;
591         o2 = o2 * p;
592      }
593    v = v1 - (double)fact;
594    pos = (v * o2) + ((1.0 - v) * o1);
595    return pos;
596 }
597 
598 static double
_pos_map_pow(double pos,double divis,int p)599 _pos_map_pow(double pos,
600              double divis,
601              int    p)
602 {
603    double v = 1.0;
604    int i;
605    for (i = 0; i < p; i++) v *= pos;
606    return ((pos * divis) * (1.0 - v)) + (pos * v);
607 }
608 
609 static double
_pos_map_spring(double pos,int bounces,double decfac)610 _pos_map_spring(double pos,
611                 int    bounces,
612                 double decfac)
613 {
614    int segnum, segpos, b1, b2;
615    double len, decay, decpos, p2;
616    if (bounces < 0) bounces = 0;
617    p2 = _pos_map_pow(pos, 0.5, 3);
618    len = (M_PI / 2.0) + ((double)bounces * M_PI);
619    segnum = (bounces * 2) + 1;
620    segpos = 2 * (((int)(p2 * segnum) + 1) / 2);
621    b1 = segpos;
622    b2 = segnum + 1;
623    if (b1 < 0) b1 = 0;
624    decpos = (double)b1 / (double)b2;
625    decay = _pos_map_accel_factor(1.0 - decpos, decfac);
626    return _pos_map_sin((M_PI / 2.0) + (p2 * len)) * decay;
627 }
628 
629 static inline double
cuberoot(double v)630 cuberoot(double v)
631 {
632    if (v < 0.0)
633      return -pow(-v, 1. / 3.);
634    else
635      return pow(v, 1. / 3.);
636 }
637 
638 static double
_bezier_t_get(double _x,double _x1,double _x2)639 _bezier_t_get(double _x, double _x1, double _x2)
640 {
641    if (_x < 0.0 || _x > 1.0) return _x;
642 
643    // Cardano's algorithm
644    double\
645    pa = _x - 0.0,
646    pb = _x - _x1,
647    pc = _x - _x2,
648    pd = _x - 1.0;
649 
650    double\
651    a = 3*pa-6*pb+3*pc,
652    b = -3*pa+3*pb,
653    c = pa,
654    d = -pa+3*pb-3*pc+pd;
655 
656    a /= d;
657    b /= d;
658    c /= d;
659 
660    double\
661    p = (3*b-a*a)/3.0,
662    p3 = p/3.0,
663    q = (2*a*a*a-9*a*b+27*c)/27.0,
664    q2 = q/2.0,
665    discriminant = q2*q2 + p3*p3*p3;
666 
667    double u1, v1, root1, root2, root3;
668 
669    if (discriminant < 0)
670      {
671         double\
672         mp3  = -p/3.0,
673         mp33 = mp3*mp3*mp3,
674         r    = sqrt(mp33),
675         t    = -q / (2*r),
676         cosphi = t<-1.0 ? -1.0 : t>1.0 ? 1.0 : t,
677         phi  = acos(cosphi),
678         crtr = cuberoot(r),
679         t1   = 2*crtr;
680         root1 = t1 * cos(phi/3.0) - a/3.0;
681         root2 = t1 * cos((phi+2*M_PI)/3.0) - a/3.0;
682         root3 = t1 * cos((phi+4*M_PI)/3.0) - a/3.0;
683 
684         if (root1 >= 0.0 && root1 <= 1.0) return root1;
685         if (root2 >= 0.0 && root2 <= 1.0) return root2;
686         if (root3 >= 0.0 && root3 <= 1.0) return root3;
687      }
688    else if (discriminant == 0)
689      {
690         u1 = q2 < 0 ? cuberoot(-q2) : -cuberoot(q2);
691         root1 = 2*u1 - a/3.0;
692         root2 = -u1 - a/3.0;
693 
694         if (root1 >= 0.0 && root1 <= 1.0) return root1;
695         if (root2 >= 0.0 && root2 <= 1.0) return root2;
696      }
697    else
698      {
699         double sd = sqrt(discriminant);
700         u1 = cuberoot(sd - q2);
701         v1 = cuberoot(sd + q2);
702         root1 = u1 - v1 - a/3.0;
703 
704         if (root1 >= 0.0 && root1 <= 1.0) return root1;
705      }
706 
707    return _x;
708 }
709 
710 static double
_bezier_calc(double t,double y1,double y2)711 _bezier_calc(double t, double y1, double y2)
712 {
713    double y0 = 0.0;
714    double y3 = 1.0;
715 
716    double u = 1.0 - t;
717    double t2 = t*t;
718    double t3 = t*t*t;
719    double u2 = u*u;
720    double u3 = u*u*u;
721 
722    return       u3 *      y0 +
723           3.0 * u2 * t  * y1 +
724           3.0 * u  * t2 * y2 +
725                      t3 * y3;
726 }
727 
728 static double
_pos_map_cubic_bezier(double pos,double x1,double y1,double x2,double y2)729 _pos_map_cubic_bezier(double pos,
730                       double x1,
731                       double y1,
732                       double x2,
733                       double y2)
734 {
735    if (EINA_DBL_EQ(x1, y1) &&
736        EINA_DBL_EQ(x2, y2))
737      return pos;
738    return _bezier_calc(_bezier_t_get(pos, x1, x2), y1, y2);
739 }
740 
741 #define DBL_TO(Fp) eina_f32p32_double_to(Fp)
742 #define DBL_FROM(D) eina_f32p32_double_from(D)
743 #define INT_FROM(I) eina_f32p32_int_from(I)
744 #define SIN(Fp) eina_f32p32_sin(Fp)
745 #define COS(Fp) eina_f32p32_cos(Fp)
746 #define ADD(A, B) eina_f32p32_add(A, B)
747 #define SUB(A, B) eina_f32p32_sub(A, B)
748 #define MUL(A, B) eina_f32p32_mul(A, B)
749 
750 EAPI double
ecore_animator_pos_map_n(double pos,Ecore_Pos_Map map,int v_size,double * v)751 ecore_animator_pos_map_n(double        pos,
752                          Ecore_Pos_Map map,
753                          int           v_size,
754                          double       *v)
755 {
756     double v0 = 0, v1 = 0, v2 = 0, v3 = 0;
757 
758    /* purely functional - locking not required */
759     if (pos >= 1.0) return 1.0;
760     else if (pos <= 0.0)
761       return 0.0;
762     switch (map)
763       {
764        case ECORE_POS_MAP_LINEAR:
765          return pos;
766 
767        case ECORE_POS_MAP_ACCELERATE:
768 	 /* pos = 1 - sin(Pi / 2 + pos * Pi / 2); */
769 	 pos = DBL_TO(SUB(INT_FROM(1), SIN(ADD((EINA_F32P32_PI >> 1), MUL(DBL_FROM(pos), (EINA_F32P32_PI >> 1))))));
770          return pos;
771 
772        case ECORE_POS_MAP_DECELERATE:
773 	 /* pos = sin(pos * Pi / 2); */
774 	 pos = DBL_TO(SIN(MUL(DBL_FROM(pos), (EINA_F32P32_PI >> 1))));
775          return pos;
776 
777        case ECORE_POS_MAP_SINUSOIDAL:
778 	 /* pos = (1 - cos(pos * Pi)) / 2 */
779 	 pos = DBL_TO((SUB(INT_FROM(1), COS(MUL(DBL_FROM(pos), EINA_F32P32_PI)))) >> 1);
780          return pos;
781 
782        case ECORE_POS_MAP_ACCELERATE_FACTOR:
783          if (v_size > 0) v0 = v[0];
784          pos = _pos_map_accel_factor(pos, v0);
785          return pos;
786 
787        case ECORE_POS_MAP_DECELERATE_FACTOR:
788          if (v_size > 0) v0 = v[0];
789          pos = 1.0 - _pos_map_accel_factor(1.0 - pos, v0);
790          return pos;
791 
792        case ECORE_POS_MAP_SINUSOIDAL_FACTOR:
793          if (v_size > 0) v0 = v[0];
794          if (pos < 0.5) pos = _pos_map_accel_factor(pos * 2.0, v0) / 2.0;
795          else pos = 1.0 - (_pos_map_accel_factor((1.0 - pos) * 2.0, v0) / 2.0);
796          return pos;
797 
798        case ECORE_POS_MAP_DIVISOR_INTERP:
799          if (v_size > 0) v0 = v[0];
800          if (v_size > 1) v1 = v[1];
801          pos = _pos_map_pow(pos, v0, (int)v1);
802          return pos;
803 
804        case ECORE_POS_MAP_BOUNCE:
805          if (v_size > 0) v0 = v[0];
806          if (v_size > 1) v1 = v[1];
807          pos = _pos_map_spring(pos, (int)v1, v0);
808          if (pos < 0.0) pos = -pos;
809          pos = 1.0 - pos;
810          return pos;
811 
812        case ECORE_POS_MAP_SPRING:
813          if (v_size > 0) v0 = v[0];
814          if (v_size > 1) v1 = v[1];
815          pos = 1.0 - _pos_map_spring(pos, (int)v1, v0);
816          return pos;
817 
818        case ECORE_POS_MAP_CUBIC_BEZIER:
819          if (v_size > 0) v0 = v[0];
820          if (v_size > 1) v1 = v[1];
821          if (v_size > 2) v2 = v[2];
822          if (v_size > 3) v3 = v[3];
823          pos = _pos_map_cubic_bezier(pos, v0, v1, v2, v3);
824          return pos;
825 
826        default:
827          return pos;
828       }
829 
830     return pos;
831 }
832 
833 EAPI double
ecore_animator_pos_map(double pos,Ecore_Pos_Map map,double v1,double v2)834 ecore_animator_pos_map(double        pos,
835                        Ecore_Pos_Map map,
836                        double        v1,
837                        double        v2)
838 {
839     double v[2];
840 
841     v[0] = v1;
842     v[1] = v2;
843     return ecore_animator_pos_map_n(pos, map, 2, v);
844 }
845 
846 EAPI void *
ecore_animator_del(Ecore_Animator * animator)847 ecore_animator_del(Ecore_Animator *animator)
848 {
849    void *data = NULL;
850 
851    if (!animator) return NULL;
852    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
853 
854    if (animator->ee) return _anim_iface.del(animator);
855 
856    if (animator->delete_me)
857      {
858         data = animator->data;
859         goto end;
860      }
861 
862    animator->delete_me = EINA_TRUE;
863    animators_delete_me++;
864    if (animator->run_func)
865      data = animator->run_data;
866    else
867      data = animator->data;
868 
869  end:
870    if (!in_main_loop) _ecore_animator_flush();
871    return data;
872 }
873 
874 EAPI void
ecore_animator_frametime_set(double frametime)875 ecore_animator_frametime_set(double frametime)
876 {
877    EINA_MAIN_LOOP_CHECK_RETURN;
878    if (frametime < 0.0) frametime = 0.0;
879    if (EINA_DBL_EQ(animators_frametime, frametime)) return ;
880    animators_frametime = frametime;
881    _end_tick();
882    if (_have_animators()) _begin_tick();
883 }
884 
885 EAPI double
ecore_animator_frametime_get(void)886 ecore_animator_frametime_get(void)
887 {
888    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
889    return animators_frametime;
890 }
891 
892 EAPI void
ecore_animator_freeze(Ecore_Animator * animator)893 ecore_animator_freeze(Ecore_Animator *animator)
894 {
895    EINA_MAIN_LOOP_CHECK_RETURN;
896    if (!animator) return;
897    if (animator->delete_me) return;
898    if (animator->suspended) return;
899 
900    if (animator->ee)
901      {
902         _anim_iface.freeze(animator);
903         return;
904      }
905    animator->suspended = EINA_TRUE;
906    animators_suspended++;
907    if (!_have_animators()) _end_tick();
908 }
909 
910 EAPI void
ecore_animator_thaw(Ecore_Animator * animator)911 ecore_animator_thaw(Ecore_Animator *animator)
912 {
913    EINA_MAIN_LOOP_CHECK_RETURN;
914    if (!animator) return;
915    if (animator->delete_me) return;
916    if (!animator->suspended) return;
917 
918    if (animator->ee)
919      {
920         _anim_iface.thaw(animator);
921         return;
922      }
923    animator->suspended = EINA_FALSE;
924    animators_suspended--;
925    if (_have_animators()) _begin_tick();
926 }
927 
928 EAPI void
ecore_animator_source_set(Ecore_Animator_Source source)929 ecore_animator_source_set(Ecore_Animator_Source source)
930 {
931    EINA_MAIN_LOOP_CHECK_RETURN;
932    _end_tick();
933    src = source;
934    DBG("New source set to %s.",
935        source == ECORE_ANIMATOR_SOURCE_TIMER ? "TIMER" :
936        source == ECORE_ANIMATOR_SOURCE_CUSTOM ? "CUSTOM" :
937        "UNKNOWN");
938    if (_have_animators()) _begin_tick();
939 }
940 
941 EAPI Ecore_Animator_Source
ecore_animator_source_get(void)942 ecore_animator_source_get(void)
943 {
944    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
945    return src;
946 }
947 
948 EAPI void
ecore_animator_custom_source_tick_begin_callback_set(Ecore_Cb func,const void * data)949 ecore_animator_custom_source_tick_begin_callback_set(Ecore_Cb    func,
950                                                      const void *data)
951 {
952    EINA_MAIN_LOOP_CHECK_RETURN;
953    _end_tick();
954    begin_tick_cb = func;
955    begin_tick_data = data;
956    if (_have_animators()) _begin_tick();
957 }
958 
959 EAPI void
ecore_animator_custom_source_tick_end_callback_set(Ecore_Cb func,const void * data)960 ecore_animator_custom_source_tick_end_callback_set(Ecore_Cb    func,
961                                                    const void *data)
962 {
963    EINA_MAIN_LOOP_CHECK_RETURN;
964    _end_tick();
965    end_tick_cb = func;
966    end_tick_data = data;
967    if (_have_animators()) _begin_tick();
968 }
969 
970 EAPI void
ecore_animator_custom_tick(void)971 ecore_animator_custom_tick(void)
972 {
973    EINA_MAIN_LOOP_CHECK_RETURN;
974    if (src != ECORE_ANIMATOR_SOURCE_CUSTOM) return;
975 #ifndef _WIN32
976    if (!exit_signal_received)
977 #endif
978      _do_tick();
979    _ecore_animator_flush();
980 }
981 
982 void
_ecore_animator_shutdown(void)983 _ecore_animator_shutdown(void)
984 {
985    Ecore_Animator *animator;
986 
987    _timer_tick_quit();
988    _end_tick();
989 
990    EINA_INLIST_FREE(animators, animator)
991      {
992         if (animator->suspended) animators_suspended--;
993         if (animator->delete_me) animators_delete_me--;
994 
995         animators = (Ecore_Animator *) eina_inlist_remove
996               (EINA_INLIST_GET(animators), EINA_INLIST_GET(animator));
997         free(animator);
998      }
999 
1000    eina_log_domain_unregister(_ecore_anim_log_dom);
1001    _ecore_anim_log_dom = -1;
1002 }
1003 
1004 void
_ecore_animator_run_reset(void)1005 _ecore_animator_run_reset(void)
1006 {
1007    animator_ran = EINA_FALSE;
1008 }
1009 
1010 Eina_Bool
_ecore_animator_run_get(void)1011 _ecore_animator_run_get(void)
1012 {
1013    return animator_ran;
1014 }
1015 
1016 static Eina_Bool
_ecore_animator_run(void * data)1017 _ecore_animator_run(void *data)
1018 {
1019    Ecore_Animator *animator = data;
1020    double pos = 0.0, t;
1021    Eina_Bool run_ret;
1022 
1023    t = ecore_loop_time_get();
1024    if (animator->run > 0.0)
1025      {
1026         pos = (t - animator->start) / animator->run;
1027         if (pos > 1.0) pos = 1.0;
1028         else if (pos < 0.0)
1029           pos = 0.0;
1030      }
1031    run_ret = animator->run_func(animator->run_data, pos);
1032    if (eina_dbl_exact(pos, 1.0)) run_ret = EINA_FALSE;
1033    return run_ret;
1034 }
1035 
1036 Eina_Bool
_ecore_animator_flush(void)1037 _ecore_animator_flush(void)
1038 {
1039    Ecore_Animator *animator;
1040 
1041    if (animators_delete_me)
1042      {
1043         Ecore_Animator *l;
1044         for (l = animators; l; )
1045           {
1046              animator = l;
1047              l = (Ecore_Animator  *)EINA_INLIST_GET(l)->next;
1048              if (animator->delete_me)
1049                {
1050                   if (animator->suspended) animators_suspended--;
1051                   animators = (Ecore_Animator *)
1052                     eina_inlist_remove(EINA_INLIST_GET(animators),
1053                                        EINA_INLIST_GET(animator));
1054 
1055                   free(animator);
1056 
1057                   animators_delete_me--;
1058                   if (animators_delete_me == 0) break;
1059                }
1060           }
1061      }
1062    if (!_have_animators())
1063      {
1064         _end_tick();
1065         return EINA_FALSE;
1066      }
1067    return EINA_TRUE;
1068 }
1069 
1070 void
_ecore_animator_init(void)1071 _ecore_animator_init(void)
1072 {
1073    _ecore_anim_log_dom = eina_log_domain_register("ecore_animator", ECORE_DEFAULT_LOG_COLOR);
1074    if (_ecore_anim_log_dom < 0)
1075      {
1076         EINA_LOG_ERR("Ecore was unable to create a log domain.");
1077      }
1078 }
1079 
1080 void
ecore_evas_object_animator_init(Ecore_Evas_Object_Animator_Interface * iface)1081 ecore_evas_object_animator_init(Ecore_Evas_Object_Animator_Interface *iface)
1082 {
1083    _anim_iface = *iface;
1084    _ee_animators_setup = EINA_TRUE;
1085 }
1086 
1087 Ecore_Animator *
ecore_evas_animator_timeline_add(void * evo,double runtime,Ecore_Timeline_Cb func,const void * data)1088 ecore_evas_animator_timeline_add(void *evo, double runtime, Ecore_Timeline_Cb func, const void *data)
1089 {
1090    Ecore_Animator *anim = NULL;
1091 
1092    if (_ee_animators_setup)
1093      anim = _anim_iface.timeline_add(evo, runtime, func, data);
1094 
1095    if (anim) return anim;
1096 
1097    return ecore_animator_timeline_add(runtime, func, data);
1098 }
1099 
1100 Ecore_Animator *
ecore_evas_animator_add(void * evo,Ecore_Task_Cb func,const void * data)1101 ecore_evas_animator_add(void *evo, Ecore_Task_Cb func, const void *data)
1102 {
1103    Ecore_Animator *anim = NULL;
1104 
1105    if (_ee_animators_setup)
1106      anim = _anim_iface.add(evo, func, data);
1107 
1108    if (anim) return anim;
1109 
1110    return ecore_animator_add(func, data);
1111 }
1112