1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/base/animation/tween.h"
6
7#include <math.h>
8
9#if defined(OS_WIN)
10#include <float.h>
11#endif
12
13#include "base/logging.h"
14
15namespace ui {
16
17// static
18double Tween::CalculateValue(Tween::Type type, double state) {
19  DCHECK_GE(state, 0);
20  DCHECK_LE(state, 1);
21
22  switch (type) {
23    case EASE_IN:
24      return pow(state, 2);
25
26    case EASE_IN_2:
27      return pow(state, 4);
28
29    case EASE_IN_OUT:
30      if (state < 0.5)
31        return pow(state * 2, 2) / 2.0;
32      return 1.0 - (pow((state - 1.0) * 2, 2) / 2.0);
33
34    case FAST_IN_OUT:
35      return (pow(state - 0.5, 3) + 0.125) / 0.25;
36
37    case LINEAR:
38      return state;
39
40    case EASE_OUT_SNAP:
41      state = 0.95 * (1.0 - pow(1.0 - state, 2));
42      return state;
43
44    case EASE_OUT:
45      return 1.0 - pow(1.0 - state, 2);
46
47    case SMOOTH_IN_OUT:
48      return sin(state);
49
50    case ZERO:
51      return 0;
52  }
53
54  NOTREACHED();
55  return state;
56}
57
58// static
59double Tween::ValueBetween(double value, double start, double target) {
60  return start + (target - start) * value;
61}
62
63// static
64int Tween::ValueBetween(double value, int start, int target) {
65  if (start == target)
66    return start;
67  double delta = static_cast<double>(target - start);
68  if (delta < 0)
69    delta--;
70  else
71    delta++;
72#if defined(OS_WIN)
73  return start + static_cast<int>(value * _nextafter(delta, 0));
74#else
75  return start + static_cast<int>(value * nextafter(delta, 0));
76#endif
77}
78
79// static
80gfx::Rect Tween::ValueBetween(double value,
81                              const gfx::Rect& start_bounds,
82                              const gfx::Rect& target_bounds) {
83  return gfx::Rect(ValueBetween(value, start_bounds.x(), target_bounds.x()),
84                   ValueBetween(value, start_bounds.y(), target_bounds.y()),
85                   ValueBetween(value, start_bounds.width(),
86                                target_bounds.width()),
87                   ValueBetween(value, start_bounds.height(),
88                                target_bounds.height()));
89}
90
91// static
92gfx::Transform Tween::ValueBetween(double value,
93                                   const gfx::Transform& start_transform,
94                                   const gfx::Transform& end_transform) {
95  if (value >= 1.0)
96    return end_transform;
97  if (value <= 0.0)
98    return start_transform;
99
100  gfx::Transform to_return = end_transform;
101  to_return.Blend(start_transform, value);
102
103  return to_return;
104}
105
106}  // namespace ui
107