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"
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"
24 double Tween::CalculateValue(Tween::Type type, double state) {
37 return pow(state * 2, 2) / 2.0;
38 return 1.0 - (pow((state - 1.0) * 2, 2) / 2.0);
41 return (pow(state - 0.5, 3) + 0.125) / 0.25;
47 state = 0.95 * (1.0 - pow(1.0 - state, 2));
51 return 1.0 - pow(1.0 - state, 2);
56 case FAST_OUT_SLOW_IN:
57 return gfx::CubicBezier(0.4, 0, 0.2, 1).Solve(state);
59 case LINEAR_OUT_SLOW_IN:
60 return gfx::CubicBezier(0, 0, .2, 1).Solve(state);
62 case FAST_OUT_LINEAR_IN:
63 return gfx::CubicBezier(0.4, 0, 1, 1).Solve(state);
74 uint8 FloatToColorByte(float f) {
75 return base::saturated_cast<uint8>(ToRoundedInt(f * 255.f));
78 uint8 BlendColorComponents(uint8 start,
84 // Since progress can be outside [0, 1], blending can produce a value outside
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);
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);
99 return SkColorSetARGB(0, 0, 0, 0);
100 blended_a = std::min(blended_a, 1.f);
102 uint8 blended_r = BlendColorComponents(SkColorGetR(start),
108 uint8 blended_g = BlendColorComponents(SkColorGetG(start),
114 uint8 blended_b = BlendColorComponents(SkColorGetB(start),
121 return SkColorSetARGB(
122 FloatToColorByte(blended_a), blended_r, blended_g, blended_b);
126 double Tween::DoubleValueBetween(double value, double start, double target) {
127 return start + (target - start) * value;
131 float Tween::FloatValueBetween(double value, float start, float target) {
132 return static_cast<float>(start + (target - start) * value);
136 int Tween::IntValueBetween(double value, int start, int target) {
139 double delta = static_cast<double>(target - start);
145 return start + static_cast<int>(value * _nextafter(delta, 0));
147 return start + static_cast<int>(value * nextafter(delta, 0));
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));
158 gfx::Rect Tween::RectValueBetween(double value,
159 const gfx::Rect& start_bounds,
160 const gfx::Rect& target_bounds) {
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()));
170 gfx::Transform Tween::TransformValueBetween(
172 const gfx::Transform& start_transform,
173 const gfx::Transform& end_transform) {
175 return end_transform;
177 return start_transform;
179 gfx::Transform to_return = end_transform;
180 to_return.Blend(start_transform, value);