content: /*
   * Copyright 2016 Izumi Kawashima
   * Copyright 2018 Gustl22
   *
   * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
   *
   * This program is free software: you can redistribute it and/or modify it under the
   * terms of the GNU Lesser General Public License as published by the Free Software
   * Foundation, either version 3 of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but WITHOUT ANY
   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
   * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public License along with
   * this program. If not, see <http://www.gnu.org/licenses/>.
   */
  package org.oscim.utils.animation;
  
  import static org.oscim.utils.FastMath.clamp;
  
  public class Easing {
      public enum Type {
          LINEAR,
          SINE_INOUT,
          SINE_IN,
          SINE_OUT,
          EXPO_OUT,
          QUAD_INOUT,
          CUBIC_INOUT,
          QUART_INOUT,
          QUINT_INOUT
      }
  
      public static float ease(long start, long current, float duration, Type easingType) {
          long millisElapsed = current - start;
          if (millisElapsed > duration) {
              return 1;
          }
          float x = (float) millisElapsed / duration;
          float t = millisElapsed;
          float b = 0;
          float c = 1;
          float d = duration;
  
          float adv = 0;
          switch (easingType) {
              case LINEAR: // Already linear.
                  adv = linear(x, t, b, c, d);
                  break;
              case SINE_INOUT:
                  adv = sineInout(x, t, b, c, d);
                  break;
              case SINE_IN:
                  adv = sineIn(x, t, b, c, d);
                  break;
              case SINE_OUT:
                  adv = sineOut(x, t, b, c, d);
                  break;
              case EXPO_OUT:
                  adv = expoOut(x, t, b, c, d);
                  break;
              case QUAD_INOUT:
                  adv = quadInout(x, t, b, c, d);
                  break;
              case CUBIC_INOUT:
                  adv = cubicInout(x, t, b, c, d);
                  break;
              case QUART_INOUT:
                  adv = quartInout(x, t, b, c, d);
                  break;
              case QUINT_INOUT:
                  adv = quintInout(x, t, b, c, d);
                  break;
          }
          adv = clamp(adv, 0, 1);
          return adv;
      }
  
      // Following easing functions are copied from https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
      // Under BSD license
      private static float linear(float x, float t, float b, float c, float d) {
          return c * x + b;
      }
  
      private static float sineInout(float x, float t, float b, float c, float d) {
          return -c / 2 * (float) (Math.cos(Math.PI * t / d) - 1) + b;
      }
  
      private static float sineIn(float x, float t, float b, float c, float d) {
          return -c * (float) Math.cos(t / d * (Math.PI / 2)) + c + b;
      }
  
      private static float sineOut(float x, float t, float b, float c, float d) {
          return c * (float) Math.sin(t / d * (Math.PI / 2)) + b;
      }
  
      private static float expoOut(float x, float t, float b, float c, float d) {
          return (t == d) ? b + c : c * (float) (-Math.pow(2, -10 * x) + 1) + b;
      }
  
      private static float quadInout(float x, float t, float b, float c, float d) {
          if ((t /= d / 2) < 1) return c / 2 * t * t + b;
          return -c / 2 * ((--t) * (t - 2) - 1) + b;
      }
  
      private static float cubicInout(float x, float t, float b, float c, float d) {
          if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
          return c / 2 * ((t -= 2) * t * t + 2) + b;
      }
  
      private static float quartInout(float x, float t, float b, float c, float d) {
          if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
          return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
      }
  
      private static float quintInout(float x, float t, float b, float c, float d) {
          if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
          return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
      }
  }
  