Home | History | Annotate | Download | only in gm
      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      */
     32     SkAnimTimer() : fBaseTime(0), fCurrTime(0), fState(kStopped_State) {}
     33 
     34     bool isStopped() const { return kStopped_State == fState; }
     35     bool isRunning() const { return kRunning_State == fState; }
     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      */
     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      */
     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      */
     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      */
     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      */
     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      */
     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 
    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