1*c8dee2aaSAndroid Build Coastguard Worker // Copyright 2019 Google LLC
2*c8dee2aaSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*c8dee2aaSAndroid Build Coastguard Worker // found in the LICENSE file.
4*c8dee2aaSAndroid Build Coastguard Worker
5*c8dee2aaSAndroid Build Coastguard Worker #ifndef TimeUtils_DEFINED
6*c8dee2aaSAndroid Build Coastguard Worker #define TimeUtils_DEFINED
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkFloatingPoint.h"
10*c8dee2aaSAndroid Build Coastguard Worker
11*c8dee2aaSAndroid Build Coastguard Worker #include <climits>
12*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
13*c8dee2aaSAndroid Build Coastguard Worker
14*c8dee2aaSAndroid Build Coastguard Worker namespace TimeUtils {
15*c8dee2aaSAndroid Build Coastguard Worker // 32 bit value to hold a millisecond duration
16*c8dee2aaSAndroid Build Coastguard Worker using MSec = uint32_t;
17*c8dee2aaSAndroid Build Coastguard Worker
18*c8dee2aaSAndroid Build Coastguard Worker // Maximum representable milliseconds; 24d 20h 31m 23.647s
19*c8dee2aaSAndroid Build Coastguard Worker static constexpr MSec MSecMax = INT32_MAX;
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker // Returns 0 if the timer is stopped. Behavior is undefined if the timer
22*c8dee2aaSAndroid Build Coastguard Worker // has been running longer than MSecMax.
NanosToMSec(double nanos)23*c8dee2aaSAndroid Build Coastguard Worker static inline MSec NanosToMSec(double nanos) {
24*c8dee2aaSAndroid Build Coastguard Worker const double msec = nanos * 1e-6;
25*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(MSecMax >= msec);
26*c8dee2aaSAndroid Build Coastguard Worker return static_cast<MSec>(msec);
27*c8dee2aaSAndroid Build Coastguard Worker }
28*c8dee2aaSAndroid Build Coastguard Worker
NanosToSeconds(double nanos)29*c8dee2aaSAndroid Build Coastguard Worker static inline double NanosToSeconds(double nanos) {
30*c8dee2aaSAndroid Build Coastguard Worker return nanos * 1e-9;
31*c8dee2aaSAndroid Build Coastguard Worker }
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker // Return the time scaled by "speed" and (if not zero) mod by period.
34*c8dee2aaSAndroid Build Coastguard Worker static inline float Scaled(float time, float speed, float period = 0) {
35*c8dee2aaSAndroid Build Coastguard Worker double value = time * speed;
36*c8dee2aaSAndroid Build Coastguard Worker if (period) {
37*c8dee2aaSAndroid Build Coastguard Worker value = ::fmod(value, (double)(period));
38*c8dee2aaSAndroid Build Coastguard Worker }
39*c8dee2aaSAndroid Build Coastguard Worker return (float)value;
40*c8dee2aaSAndroid Build Coastguard Worker }
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker // Transitions from ends->mid->ends linearly over period time. The phase
43*c8dee2aaSAndroid Build Coastguard Worker // specifies a phase shift in time units.
PingPong(double time,float period,float phase,float ends,float mid)44*c8dee2aaSAndroid Build Coastguard Worker static inline float PingPong(double time,
45*c8dee2aaSAndroid Build Coastguard Worker float period,
46*c8dee2aaSAndroid Build Coastguard Worker float phase,
47*c8dee2aaSAndroid Build Coastguard Worker float ends,
48*c8dee2aaSAndroid Build Coastguard Worker float mid) {
49*c8dee2aaSAndroid Build Coastguard Worker double value = ::fmod(time + phase, period);
50*c8dee2aaSAndroid Build Coastguard Worker double half = period / 2.0;
51*c8dee2aaSAndroid Build Coastguard Worker double diff = ::fabs(value - half);
52*c8dee2aaSAndroid Build Coastguard Worker return (float)(ends + (1.0 - diff / half) * (mid - ends));
53*c8dee2aaSAndroid Build Coastguard Worker }
54*c8dee2aaSAndroid Build Coastguard Worker
SineWave(double time,float periodInSecs,float phaseInSecs,float min,float max)55*c8dee2aaSAndroid Build Coastguard Worker static inline float SineWave(double time,
56*c8dee2aaSAndroid Build Coastguard Worker float periodInSecs,
57*c8dee2aaSAndroid Build Coastguard Worker float phaseInSecs,
58*c8dee2aaSAndroid Build Coastguard Worker float min,
59*c8dee2aaSAndroid Build Coastguard Worker float max) {
60*c8dee2aaSAndroid Build Coastguard Worker if (periodInSecs < 0.f) {
61*c8dee2aaSAndroid Build Coastguard Worker return (min + max) / 2.f;
62*c8dee2aaSAndroid Build Coastguard Worker }
63*c8dee2aaSAndroid Build Coastguard Worker double t = NanosToSeconds(time) + phaseInSecs;
64*c8dee2aaSAndroid Build Coastguard Worker t *= 2 * SK_FloatPI / periodInSecs;
65*c8dee2aaSAndroid Build Coastguard Worker float halfAmplitude = (max - min) / 2.f;
66*c8dee2aaSAndroid Build Coastguard Worker return halfAmplitude * std::sin(t) + halfAmplitude + min;
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker } // namespace TimeUtils
69*c8dee2aaSAndroid Build Coastguard Worker #endif
70