Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / gfx / animation / tween.cc
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/gfx/animation/tween.h"
6
7 #include <math.h>
8
9 #if defined(OS_WIN)
10 #include <float.h>
11 #endif
12
13 #include <algorithm>
14
15 #include "base/basictypes.h"
16 #include "base/logging.h"
17 #include "base/numerics/safe_conversions.h"
18 #include "ui/gfx/geometry/cubic_bezier.h"
19 #include "ui/gfx/safe_integer_conversions.h"
20
21 namespace gfx {
22
23 // static
24 double Tween::CalculateValue(Tween::Type type, double state) {
25   DCHECK_GE(state, 0);
26   DCHECK_LE(state, 1);
27
28   switch (type) {
29     case EASE_IN:
30       return pow(state, 2);
31
32     case EASE_IN_2:
33       return pow(state, 4);
34
35     case EASE_IN_OUT:
36       if (state < 0.5)
37         return pow(state * 2, 2) / 2.0;
38       return 1.0 - (pow((state - 1.0) * 2, 2) / 2.0);
39
40     case FAST_IN_OUT:
41       return (pow(state - 0.5, 3) + 0.125) / 0.25;
42
43     case LINEAR:
44       return state;
45
46     case EASE_OUT_SNAP:
47       state = 0.95 * (1.0 - pow(1.0 - state, 2));
48       return state;
49
50     case EASE_OUT:
51       return 1.0 - pow(1.0 - state, 2);
52
53     case SMOOTH_IN_OUT:
54       return sin(state);
55
56     case FAST_OUT_SLOW_IN:
57       return gfx::CubicBezier(0.4, 0, 0.2, 1).Solve(state);
58
59     case LINEAR_OUT_SLOW_IN:
60       return gfx::CubicBezier(0, 0, .2, 1).Solve(state);
61
62     case FAST_OUT_LINEAR_IN:
63       return gfx::CubicBezier(0.4, 0, 1, 1).Solve(state);
64
65     case ZERO:
66       return 0;
67   }
68
69   NOTREACHED();
70   return state;
71 }
72
73 namespace {
74 uint8 FloatToColorByte(float f) {
75   return base::saturated_cast<uint8>(ToRoundedInt(f * 255.f));
76 }
77
78 uint8 BlendColorComponents(uint8 start,
79                            uint8 target,
80                            float start_alpha,
81                            float target_alpha,
82                            float blended_alpha,
83                            double progress) {
84   // Since progress can be outside [0, 1], blending can produce a value outside
85   // [0, 255].
86   float blended_premultiplied = Tween::FloatValueBetween(
87       progress, start / 255.f * start_alpha, target / 255.f * target_alpha);
88   return FloatToColorByte(blended_premultiplied / blended_alpha);
89 }
90
91 }  // namespace
92
93 // static
94 SkColor Tween::ColorValueBetween(double value, SkColor start, SkColor target) {
95   float start_a = SkColorGetA(start) / 255.f;
96   float target_a = SkColorGetA(target) / 255.f;
97   float blended_a = FloatValueBetween(value, start_a, target_a);
98   if (blended_a <= 0.f)
99     return SkColorSetARGB(0, 0, 0, 0);
100   blended_a = std::min(blended_a, 1.f);
101
102   uint8 blended_r = BlendColorComponents(SkColorGetR(start),
103                                          SkColorGetR(target),
104                                          start_a,
105                                          target_a,
106                                          blended_a,
107                                          value);
108   uint8 blended_g = BlendColorComponents(SkColorGetG(start),
109                                          SkColorGetG(target),
110                                          start_a,
111                                          target_a,
112                                          blended_a,
113                                          value);
114   uint8 blended_b = BlendColorComponents(SkColorGetB(start),
115                                          SkColorGetB(target),
116                                          start_a,
117                                          target_a,
118                                          blended_a,
119                                          value);
120
121   return SkColorSetARGB(
122       FloatToColorByte(blended_a), blended_r, blended_g, blended_b);
123 }
124
125 // static
126 double Tween::DoubleValueBetween(double value, double start, double target) {
127   return start + (target - start) * value;
128 }
129
130 // static
131 float Tween::FloatValueBetween(double value, float start, float target) {
132   return static_cast<float>(start + (target - start) * value);
133 }
134
135 // static
136 int Tween::IntValueBetween(double value, int start, int target) {
137   if (start == target)
138     return start;
139   double delta = static_cast<double>(target - start);
140   if (delta < 0)
141     delta--;
142   else
143     delta++;
144 #if defined(OS_WIN)
145   return start + static_cast<int>(value * _nextafter(delta, 0));
146 #else
147   return start + static_cast<int>(value * nextafter(delta, 0));
148 #endif
149 }
150
151 //static
152 int Tween::LinearIntValueBetween(double value, int start, int target) {
153   // NOTE: Do not use ToRoundedInt()!  See comments on function declaration.
154   return ToFlooredInt(0.5 + DoubleValueBetween(value, start, target));
155 }
156
157 // static
158 gfx::Rect Tween::RectValueBetween(double value,
159                                   const gfx::Rect& start_bounds,
160                                   const gfx::Rect& target_bounds) {
161   return gfx::Rect(
162       LinearIntValueBetween(value, start_bounds.x(), target_bounds.x()),
163       LinearIntValueBetween(value, start_bounds.y(), target_bounds.y()),
164       LinearIntValueBetween(value, start_bounds.width(), target_bounds.width()),
165       LinearIntValueBetween(
166           value, start_bounds.height(), target_bounds.height()));
167 }
168
169 // static
170 gfx::Transform Tween::TransformValueBetween(
171     double value,
172     const gfx::Transform& start_transform,
173     const gfx::Transform& end_transform) {
174   if (value >= 1.0)
175     return end_transform;
176   if (value <= 0.0)
177     return start_transform;
178
179   gfx::Transform to_return = end_transform;
180   to_return.Blend(start_transform, value);
181
182   return to_return;
183 }
184
185 }  // namespace gfx