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