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