Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / gfx / animation / tween.cc
blob483d772b5b4d47f4f7ba7f65d391f665df5819db
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.
5 #include "ui/gfx/animation/tween.h"
7 #include <math.h>
9 #if defined(OS_WIN)
10 #include <float.h>
11 #endif
13 #include <algorithm>
15 #include "base/basictypes.h"
16 #include "base/logging.h"
17 #include "ui/gfx/geometry/cubic_bezier.h"
18 #include "ui/gfx/safe_integer_conversions.h"
20 namespace gfx {
22 // static
23 double Tween::CalculateValue(Tween::Type type, double state) {
24 DCHECK_GE(state, 0);
25 DCHECK_LE(state, 1);
27 switch (type) {
28 case EASE_IN:
29 return pow(state, 2);
31 case EASE_IN_2:
32 return pow(state, 4);
34 case EASE_IN_OUT:
35 if (state < 0.5)
36 return pow(state * 2, 2) / 2.0;
37 return 1.0 - (pow((state - 1.0) * 2, 2) / 2.0);
39 case FAST_IN_OUT:
40 return (pow(state - 0.5, 3) + 0.125) / 0.25;
42 case LINEAR:
43 return state;
45 case EASE_OUT_SNAP:
46 state = 0.95 * (1.0 - pow(1.0 - state, 2));
47 return state;
49 case EASE_OUT:
50 return 1.0 - pow(1.0 - state, 2);
52 case SMOOTH_IN_OUT:
53 return sin(state);
55 case FAST_OUT_SLOW_IN:
56 return gfx::CubicBezier(0.4, 0, 0.2, 1).Solve(state);
58 case LINEAR_OUT_SLOW_IN:
59 return gfx::CubicBezier(0, 0, .2, 1).Solve(state);
61 case FAST_OUT_LINEAR_IN:
62 return gfx::CubicBezier(0.4, 0, 1, 1).Solve(state);
64 case ZERO:
65 return 0;
68 NOTREACHED();
69 return state;
72 namespace {
73 uint8 FloatToColorByte(float f) {
74 return std::min(std::max(ToRoundedInt(f * 255.f), 0), 255);
77 uint8 BlendColorComponents(uint8 start,
78 uint8 target,
79 float start_alpha,
80 float target_alpha,
81 float blended_alpha,
82 double progress) {
83 // Since progress can be outside [0, 1], blending can produce a value outside
84 // [0, 255].
85 float blended_premultiplied = Tween::FloatValueBetween(
86 progress, start / 255.f * start_alpha, target / 255.f * target_alpha);
87 return FloatToColorByte(blended_premultiplied / blended_alpha);
90 } // namespace
92 // static
93 SkColor Tween::ColorValueBetween(double value, SkColor start, SkColor target) {
94 float start_a = SkColorGetA(start) / 255.f;
95 float target_a = SkColorGetA(target) / 255.f;
96 float blended_a = FloatValueBetween(value, start_a, target_a);
97 if (blended_a <= 0.f)
98 return SkColorSetARGB(0, 0, 0, 0);
99 blended_a = std::min(blended_a, 1.f);
101 uint8 blended_r = BlendColorComponents(SkColorGetR(start),
102 SkColorGetR(target),
103 start_a,
104 target_a,
105 blended_a,
106 value);
107 uint8 blended_g = BlendColorComponents(SkColorGetG(start),
108 SkColorGetG(target),
109 start_a,
110 target_a,
111 blended_a,
112 value);
113 uint8 blended_b = BlendColorComponents(SkColorGetB(start),
114 SkColorGetB(target),
115 start_a,
116 target_a,
117 blended_a,
118 value);
120 return SkColorSetARGB(
121 FloatToColorByte(blended_a), blended_r, blended_g, blended_b);
124 // static
125 double Tween::DoubleValueBetween(double value, double start, double target) {
126 return start + (target - start) * value;
129 // static
130 float Tween::FloatValueBetween(double value, float start, float target) {
131 return static_cast<float>(start + (target - start) * value);
134 // static
135 int Tween::IntValueBetween(double value, int start, int target) {
136 if (start == target)
137 return start;
138 double delta = static_cast<double>(target - start);
139 if (delta < 0)
140 delta--;
141 else
142 delta++;
143 #if defined(OS_WIN)
144 return start + static_cast<int>(value * _nextafter(delta, 0));
145 #else
146 return start + static_cast<int>(value * nextafter(delta, 0));
147 #endif
150 //static
151 int Tween::LinearIntValueBetween(double value, int start, int target) {
152 return std::floor(0.5 + DoubleValueBetween(value, start, target));
155 // static
156 gfx::Rect Tween::RectValueBetween(double value,
157 const gfx::Rect& start_bounds,
158 const gfx::Rect& target_bounds) {
159 return gfx::Rect(
160 LinearIntValueBetween(value, start_bounds.x(), target_bounds.x()),
161 LinearIntValueBetween(value, start_bounds.y(), target_bounds.y()),
162 LinearIntValueBetween(value, start_bounds.width(), target_bounds.width()),
163 LinearIntValueBetween(
164 value, start_bounds.height(), target_bounds.height()));
167 // static
168 gfx::Transform Tween::TransformValueBetween(
169 double value,
170 const gfx::Transform& start_transform,
171 const gfx::Transform& end_transform) {
172 if (value >= 1.0)
173 return end_transform;
174 if (value <= 0.0)
175 return start_transform;
177 gfx::Transform to_return = end_transform;
178 to_return.Blend(start_transform, value);
180 return to_return;
183 } // namespace gfx