1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "easing_curve.h"
16
17#include <base/math/mathf.h>
18
19META_BEGIN_NAMESPACE()
20
21namespace Curves {
22namespace Easing {
23
24bool AreEqual(float v1, float v2)
25{
26    return BASE_NS::Math::abs(v1 - v2) < BASE_NS::Math::EPSILON;
27}
28float Pow2(float v)
29{
30    return v * v;
31}
32float Pow3(float v)
33{
34    return v * v * v;
35}
36float Pow4(float v)
37{
38    return v * v * v * v;
39}
40float Pow5(float v)
41{
42    return v * v * v * v * v;
43}
44float EaseLinear(float t)
45{
46    return t;
47}
48float EaseInSine(float t)
49{
50    return 1.f - BASE_NS::Math::cos((t * BASE_NS::Math::PI) / 2.f);
51}
52float EaseOutSine(float t)
53{
54    return BASE_NS::Math::sin((t * BASE_NS::Math::PI) / 2.f);
55}
56float EaseInOutSine(float t)
57{
58    return -(BASE_NS::Math::cos(BASE_NS::Math::PI * t) - 1.f) / 2.f;
59}
60float EaseInQuad(float t)
61{
62    return Pow2(t);
63}
64float EaseOutQuad(float t)
65{
66    return 1.f - Pow2(1.f - t);
67}
68float EaseInOutQuad(float t)
69{
70    if (t < 0.5f) {
71        return 2 * t * t;
72    }
73    return 1.f - (Pow2(-2.f * t + 2.f) / 2.f);
74}
75float EaseInCubic(float t)
76{
77    return Pow3(t);
78}
79float EaseOutCubic(float t)
80{
81    return 1.f - Pow3(1.f - t);
82}
83float EaseInOutCubic(float t)
84{
85    if (t < 0.5f) {
86        return 4 * t * t * t;
87    }
88    return 1.f - (Pow3(-2.f * t + 2.f) / 2.f);
89}
90float EaseInQuart(float t)
91{
92    return Pow4(t);
93}
94float EaseOutQuart(float t)
95{
96    return 1.f - Pow4(1.f - t);
97}
98float EaseInOutQuart(float t)
99{
100    if (t < 0.5f) {
101        return 8 * Pow4(t);
102    }
103    return 1.f - (Pow4(-2.f * t + 2.f) / 2.f);
104}
105float EaseInQuint(float t)
106{
107    return Pow5(t);
108}
109float EaseOutQuint(float t)
110{
111    return 1.f - Pow5(1.f - t);
112}
113float EaseInOutQuint(float t)
114{
115    if (t < 0.5f) {
116        return 16 * Pow5(t);
117    }
118    return 1.f - (Pow5(-2.f * t + 2.f) / 2.f);
119}
120float EaseInExpo(float t)
121{
122    if (AreEqual(t, 0.f)) {
123        return 0;
124    }
125    return BASE_NS::Math::pow(2.f, 10 * t - 10);
126}
127float EaseOutExpo(float t)
128{
129    if (AreEqual(t, 1.f)) {
130        return 1;
131    }
132    return 1.f - BASE_NS::Math::pow(2.f, -10 * t);
133}
134float EaseInOutExpo(float t)
135{
136    if (AreEqual(t, 0.f)) {
137        return 0.f;
138    }
139    if (AreEqual(t, 1.f)) {
140        return 1.f;
141    }
142    if (t < .5f) {
143        return BASE_NS::Math::pow(2.f, 20 * t - 10) / 2.f;
144    }
145    return (2.f - BASE_NS::Math::pow(2.f, -20 * t + 10)) / 2.f;
146}
147float EaseInCirc(float t)
148{
149    return 1.f - BASE_NS::Math::sqrt(1.f - Pow2(t));
150}
151float EaseOutCirc(float t)
152{
153    return BASE_NS::Math::sqrt(1.f - Pow2(t - 1.f));
154}
155float EaseInOutCirc(float t)
156{
157    if (t < 0.5f) {
158        return (1.f - BASE_NS::Math::sqrt(1.f - Pow2(2.f * t))) / 2.f;
159    }
160    return (BASE_NS::Math::sqrt(1.f - Pow2(-2.f * t + 2.f)) + 1.f) / 2.f;
161}
162float EaseInBack(float t)
163{
164    constexpr float c1 = 1.70158f;
165    constexpr float c3 = c1 + 1.f;
166    return c3 * Pow3(t) - c1 * Pow2(t);
167}
168float EaseOutBack(float t)
169{
170    constexpr float c1 = 1.70158f;
171    constexpr float c3 = c1 + 1.f;
172    return 1.f + c3 * Pow3(t - 1.f) + c1 * Pow2(t - 1.f);
173}
174float EaseInOutBack(float t)
175{
176    constexpr float c1 = 1.70158f;
177    constexpr float c2 = c1 * 1.525f;
178    if (t < 0.5f) {
179        return (Pow2(2.f * t) * ((c2 + 1.f) * 2.f * t - c2)) / 2.f;
180    }
181    return (Pow2(2.f * t - 2.f) * ((c2 + 1.f) * (t * 2.f - 2.f) + c2) + 2.f) / 2.f;
182}
183float EaseInElastic(float t)
184{
185    constexpr float c4 = (2.f * BASE_NS::Math::PI) / 3.f;
186    if (AreEqual(t, 0.f)) {
187        return 0;
188    }
189    if (AreEqual(t, 1.f)) {
190        return 1;
191    }
192    return -BASE_NS::Math::pow(2.f, 10 * t - 10) * BASE_NS::Math::sin((t * 10 - 10.75f) * c4);
193}
194float EaseOutElastic(float t)
195{
196    constexpr float c4 = (2.f * BASE_NS::Math::PI) / 3.f;
197    if (AreEqual(t, 0.f)) {
198        return 0;
199    }
200    if (AreEqual(t, 1.f)) {
201        return 1;
202    }
203    return BASE_NS::Math::pow(2.f, -10 * t) * BASE_NS::Math::sin((t * 10 - 0.75f) * c4) + 1.f;
204}
205float EaseInOutElastic(float t)
206{
207    constexpr float c5 = (2.f * BASE_NS::Math::PI) / 4.5f;
208    if (AreEqual(t, 0.f)) {
209        return 0;
210    }
211    if (AreEqual(t, 1.f)) {
212        return 1;
213    }
214    if (t < 0.5f) {
215        return -(BASE_NS::Math::pow(2.f, 20 * t - 10) * BASE_NS::Math::sin((20 * t - 11.125f) * c5)) / 2.f;
216    }
217    return (BASE_NS::Math::pow(2.f, -20 * t + 10) * BASE_NS::Math::sin((20 * t - 11.125f) * c5)) / 2.f + 1.f;
218}
219float EaseOutBounce(float t)
220{
221    constexpr float n1 = 7.5625f;
222    constexpr float d1 = 2.75f;
223    if (t < 1.f / d1) {
224        return n1 * Pow2(t);
225    }
226    if (t < (2.f / d1)) {
227        return n1 * Pow2(t - (1.5f / d1)) + 0.75f;
228    }
229    if (t < (2.5f / d1)) {
230        return n1 * Pow2(t - (2.25f / d1)) + 0.9375f;
231    }
232    return n1 * Pow2(t - (2.625f / d1)) + 0.984375f;
233}
234float EaseInBounce(float t)
235{
236    return 1.f - EaseOutBounce(1.f - t);
237}
238float EaseInOutBounce(float t)
239{
240    if (t < 0.5f) {
241        return (1.f - EaseOutBounce(1.f - 2.f * t)) / 2.f;
242    }
243    return (1.f + EaseOutBounce(2.f * t - 1.f)) / 2.f;
244}
245float EaseStepStart(float)
246{
247    return 1.f;
248}
249float EaseStepEnd(float t)
250{
251    return t < 1.f ? 0.f : 1.f;
252}
253
254// Declares the implementation
255#define IMPLEMENT_EASING_CURVE(name)                  \
256    float name##EasingCurve::Transform(float t) const \
257    {                                                 \
258        return Ease##name(t);                         \
259    }
260
261IMPLEMENT_EASING_CURVE(Linear)
262IMPLEMENT_EASING_CURVE(InQuad)
263IMPLEMENT_EASING_CURVE(OutQuad)
264IMPLEMENT_EASING_CURVE(InOutQuad)
265IMPLEMENT_EASING_CURVE(InCubic)
266IMPLEMENT_EASING_CURVE(OutCubic)
267IMPLEMENT_EASING_CURVE(InOutCubic)
268IMPLEMENT_EASING_CURVE(InSine)
269IMPLEMENT_EASING_CURVE(OutSine)
270IMPLEMENT_EASING_CURVE(InOutSine)
271IMPLEMENT_EASING_CURVE(InQuart)
272IMPLEMENT_EASING_CURVE(OutQuart)
273IMPLEMENT_EASING_CURVE(InOutQuart)
274IMPLEMENT_EASING_CURVE(InQuint)
275IMPLEMENT_EASING_CURVE(OutQuint)
276IMPLEMENT_EASING_CURVE(InOutQuint)
277IMPLEMENT_EASING_CURVE(InExpo)
278IMPLEMENT_EASING_CURVE(OutExpo)
279IMPLEMENT_EASING_CURVE(InOutExpo)
280IMPLEMENT_EASING_CURVE(InCirc)
281IMPLEMENT_EASING_CURVE(OutCirc)
282IMPLEMENT_EASING_CURVE(InOutCirc)
283IMPLEMENT_EASING_CURVE(InBack)
284IMPLEMENT_EASING_CURVE(OutBack)
285IMPLEMENT_EASING_CURVE(InOutBack)
286IMPLEMENT_EASING_CURVE(InElastic)
287IMPLEMENT_EASING_CURVE(OutElastic)
288IMPLEMENT_EASING_CURVE(InOutElastic)
289IMPLEMENT_EASING_CURVE(InBounce)
290IMPLEMENT_EASING_CURVE(OutBounce)
291IMPLEMENT_EASING_CURVE(InOutBounce)
292IMPLEMENT_EASING_CURVE(StepStart)
293IMPLEMENT_EASING_CURVE(StepEnd)
294
295} // namespace Easing
296} // namespace Curves
297
298META_END_NAMESPACE()
299