• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkTime.h"
9 
10 #ifndef SkAnimTimer_DEFINED
11 #define SkAnimTimer_DEFINED
12 
13 /**
14  *  Class to track a "timer". It supports 3 states: stopped, paused, running.
15  *
16  *  The caller must call updateTime() to resync with the clock (typically just before
17  *  using the timer). Forcing the caller to do this ensures that the timer's return values
18  *  are consistent if called repeatedly, as they only reflect the time since the last
19  *  calle to updateTimer().
20  */
21 class SkAnimTimer {
22 public:
23     enum State {
24         kStopped_State,
25         kPaused_State,
26         kRunning_State
27     };
28 
29     /**
30      *  Class begins in the "stopped" state.
31      */
SkAnimTimer()32     SkAnimTimer() : fBaseTime(0), fCurrTime(0), fState(kStopped_State) {}
33 
isStopped()34     bool isStopped() const { return kStopped_State == fState; }
isRunning()35     bool isRunning() const { return kRunning_State == fState; }
isPaused()36     bool isPaused() const { return kPaused_State == fState; }
37 
38     /**
39      *  Stops the timer, and resets it, such that the next call to run or togglePauseResume
40      *  will begin at time 0.
41      */
stop()42     void stop() {
43         this->setState(kStopped_State);
44     }
45 
46     /**
47      *  If the timer is paused or stopped, it will resume (or start if it was stopped).
48      */
run()49     void run() {
50         this->setState(kRunning_State);
51     }
52 
53     /**
54      *  If the timer is stopped, this has no effect, else it toggles between paused and running.
55      */
togglePauseResume()56     void togglePauseResume() {
57         if (kRunning_State == fState) {
58             this->setState(kPaused_State);
59         } else {
60             this->setState(kRunning_State);
61         }
62     }
63 
64     /**
65      *  Call this each time you want to sample the clock for the timer. This is NOT done
66      *  automatically, so that repeated calls to msec() or secs() will always return the
67      *  same value.
68      *
69      *  This may safely be called with the timer in any state.
70      */
updateTime()71     void updateTime() {
72         if (kRunning_State == fState) {
73             fCurrTime = SkTime::GetMSecs();
74         }
75     }
76 
77     /**
78      *  Return the time in milliseconds the timer has been in the running state.
79      *  Returns 0 if the timer is stopped.
80      */
msec()81     SkMSec msec() const { return fCurrTime - fBaseTime; }
82 
83     /**
84      *  Return the time in seconds the timer has been in the running state.
85      *  Returns 0 if the timer is stopped.
86      */
secs()87     double secs() const {
88         return this->msec() * 0.001;
89     }
90 
91     /**
92      *  Return the time in seconds the timer has been in the running state,
93      *  scaled by "speed" and (if not zero) mod by period.
94      *  Returns 0 if the timer is stopped.
95      */
96     SkScalar scaled(SkScalar speed, SkScalar period = 0) const {
97         double value = this->secs() * speed;
98         if (period) {
99             value = ::fmod(value, SkScalarToDouble(period));
100         }
101         return SkDoubleToScalar(value);
102     }
103 
104 private:
105     SkMSec  fBaseTime;
106     SkMSec  fCurrTime;
107     State   fState;
108 
setState(State newState)109     void setState(State newState) {
110         switch (newState) {
111             case kStopped_State:
112                 fBaseTime = fCurrTime = 0;
113                 fState = kStopped_State;
114                 break;
115             case kPaused_State:
116                 if (kRunning_State == fState) {
117                     fState = kPaused_State;
118                 } // else stay stopped or paused
119                 break;
120             case kRunning_State:
121                 switch (fState) {
122                     case kStopped_State:
123                         fBaseTime = fCurrTime = SkTime::GetMSecs();
124                         break;
125                     case kPaused_State: {// they want "resume"
126                         SkMSec now = SkTime::GetMSecs();
127                         fBaseTime += now - fCurrTime;
128                         fCurrTime = now;
129                     } break;
130                     case kRunning_State:
131                         break;
132                 }
133                 fState = kRunning_State;
134                 break;
135         }
136     }
137 };
138 
139 #endif
140