1a3e0fd82Sopenharmony_ci/*
2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License.
5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at
6a3e0fd82Sopenharmony_ci *
7a3e0fd82Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a3e0fd82Sopenharmony_ci *
9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and
13a3e0fd82Sopenharmony_ci * limitations under the License.
14a3e0fd82Sopenharmony_ci */
15a3e0fd82Sopenharmony_ci
16a3e0fd82Sopenharmony_ci#include "animator/easing_equation.h"
17a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_math.h"
18a3e0fd82Sopenharmony_ci
19a3e0fd82Sopenharmony_cinamespace OHOS {
20a3e0fd82Sopenharmony_cidouble EasingEquation::overshoot_ = 1.7; // The empirical value commonly used in easing equation
21a3e0fd82Sopenharmony_ci
22a3e0fd82Sopenharmony_civoid EasingEquation::SetBackOvershoot(double overshoot)
23a3e0fd82Sopenharmony_ci{
24a3e0fd82Sopenharmony_ci    if ((overshoot >= OVERSHOOT_MIN) && (overshoot <= OVERSHOOT_MAX)) {
25a3e0fd82Sopenharmony_ci        overshoot_ = overshoot;
26a3e0fd82Sopenharmony_ci    }
27a3e0fd82Sopenharmony_ci}
28a3e0fd82Sopenharmony_ci
29a3e0fd82Sopenharmony_ciint16_t EasingEquation::BackEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
30a3e0fd82Sopenharmony_ci{
31a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
32a3e0fd82Sopenharmony_ci        double t = -(static_cast<double>(curTime) / durationTime);
33a3e0fd82Sopenharmony_ci        double x = -t * t * ((overshoot_ + 1) * t + overshoot_);
34a3e0fd82Sopenharmony_ci        return static_cast<int16_t>((x * (static_cast<int32_t>(endPos) - startPos)) + startPos);
35a3e0fd82Sopenharmony_ci    }
36a3e0fd82Sopenharmony_ci
37a3e0fd82Sopenharmony_ci    return endPos;
38a3e0fd82Sopenharmony_ci}
39a3e0fd82Sopenharmony_ci
40a3e0fd82Sopenharmony_ciint16_t EasingEquation::BackEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
41a3e0fd82Sopenharmony_ci{
42a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
43a3e0fd82Sopenharmony_ci        double t = static_cast<double>(curTime) / durationTime;
44a3e0fd82Sopenharmony_ci        t -= 1.0;
45a3e0fd82Sopenharmony_ci        double x = t * t * ((overshoot_ + 1) * t + overshoot_) + 1;
46a3e0fd82Sopenharmony_ci        return static_cast<int16_t>((x * (static_cast<int32_t>(endPos) - startPos)) + startPos);
47a3e0fd82Sopenharmony_ci    }
48a3e0fd82Sopenharmony_ci
49a3e0fd82Sopenharmony_ci    return endPos;
50a3e0fd82Sopenharmony_ci}
51a3e0fd82Sopenharmony_ci
52a3e0fd82Sopenharmony_ciint16_t EasingEquation::BackEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
53a3e0fd82Sopenharmony_ci{
54a3e0fd82Sopenharmony_ci    uint16_t halfTime = durationTime >> 1;
55a3e0fd82Sopenharmony_ci    int16_t halfStep = (endPos >> 1) + (startPos >> 1);
56a3e0fd82Sopenharmony_ci    if (curTime < halfTime) {
57a3e0fd82Sopenharmony_ci        return BackEaseIn(startPos, halfStep, curTime, halfTime);
58a3e0fd82Sopenharmony_ci    }
59a3e0fd82Sopenharmony_ci    return BackEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
60a3e0fd82Sopenharmony_ci}
61a3e0fd82Sopenharmony_ci
62a3e0fd82Sopenharmony_ci/* 1 - sqrt(1 - t^2) */
63a3e0fd82Sopenharmony_ciint16_t EasingEquation::CircEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
64a3e0fd82Sopenharmony_ci{
65a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
66a3e0fd82Sopenharmony_ci        int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
67a3e0fd82Sopenharmony_ci        uint32_t x = INTERPOLATION_RANGE - static_cast<int32_t>(Sqrt(INTERPOLATION_RANGE_SQUARE - t * t));
68a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
69a3e0fd82Sopenharmony_ci                                    startPos);
70a3e0fd82Sopenharmony_ci    }
71a3e0fd82Sopenharmony_ci
72a3e0fd82Sopenharmony_ci    return endPos;
73a3e0fd82Sopenharmony_ci}
74a3e0fd82Sopenharmony_ci
75a3e0fd82Sopenharmony_ci/* sqrt(1 - (1 - t)^2) */
76a3e0fd82Sopenharmony_ciint16_t EasingEquation::CircEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
77a3e0fd82Sopenharmony_ci{
78a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
79a3e0fd82Sopenharmony_ci        int32_t t = INTERPOLATION_RANGE - (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
80a3e0fd82Sopenharmony_ci        uint32_t x = static_cast<uint32_t>(Sqrt(INTERPOLATION_RANGE_SQUARE - t * t));
81a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
82a3e0fd82Sopenharmony_ci                                    startPos);
83a3e0fd82Sopenharmony_ci    }
84a3e0fd82Sopenharmony_ci
85a3e0fd82Sopenharmony_ci    return endPos;
86a3e0fd82Sopenharmony_ci}
87a3e0fd82Sopenharmony_ci
88a3e0fd82Sopenharmony_ciint16_t EasingEquation::CircEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
89a3e0fd82Sopenharmony_ci{
90a3e0fd82Sopenharmony_ci    uint16_t halfTime = durationTime >> 1;
91a3e0fd82Sopenharmony_ci    int16_t halfStep = (endPos >> 1) + (startPos >> 1);
92a3e0fd82Sopenharmony_ci    if (curTime < halfTime) {
93a3e0fd82Sopenharmony_ci        return CircEaseIn(startPos, halfStep, curTime, halfTime);
94a3e0fd82Sopenharmony_ci    }
95a3e0fd82Sopenharmony_ci    return CircEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
96a3e0fd82Sopenharmony_ci}
97a3e0fd82Sopenharmony_ci
98a3e0fd82Sopenharmony_ci/* t^3 */
99a3e0fd82Sopenharmony_ciint16_t EasingEquation::CubicEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
100a3e0fd82Sopenharmony_ci{
101a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
102a3e0fd82Sopenharmony_ci        int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
103a3e0fd82Sopenharmony_ci        int16_t x = (t * t * t) >> (INTERPOLATION_RANGE_OFFSET << 1);
104a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
105a3e0fd82Sopenharmony_ci                                    startPos);
106a3e0fd82Sopenharmony_ci    }
107a3e0fd82Sopenharmony_ci
108a3e0fd82Sopenharmony_ci    return endPos;
109a3e0fd82Sopenharmony_ci}
110a3e0fd82Sopenharmony_ci
111a3e0fd82Sopenharmony_ci/* 1 - (1 - t)^3 */
112a3e0fd82Sopenharmony_ciint16_t EasingEquation::CubicEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
113a3e0fd82Sopenharmony_ci{
114a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
115a3e0fd82Sopenharmony_ci        int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
116a3e0fd82Sopenharmony_ci        t = INTERPOLATION_RANGE - t;
117a3e0fd82Sopenharmony_ci        int16_t x = INTERPOLATION_RANGE - ((t * t * t) >> (INTERPOLATION_RANGE_OFFSET << 1));
118a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
119a3e0fd82Sopenharmony_ci                                    startPos);
120a3e0fd82Sopenharmony_ci    }
121a3e0fd82Sopenharmony_ci
122a3e0fd82Sopenharmony_ci    return endPos;
123a3e0fd82Sopenharmony_ci}
124a3e0fd82Sopenharmony_ci
125a3e0fd82Sopenharmony_ciint16_t EasingEquation::CubicEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
126a3e0fd82Sopenharmony_ci{
127a3e0fd82Sopenharmony_ci    uint16_t halfTime = durationTime >> 1;
128a3e0fd82Sopenharmony_ci    int16_t halfStep = (endPos >> 1) + (startPos >> 1);
129a3e0fd82Sopenharmony_ci    if (curTime < halfTime) {
130a3e0fd82Sopenharmony_ci        return CubicEaseIn(startPos, halfStep, curTime, halfTime);
131a3e0fd82Sopenharmony_ci    }
132a3e0fd82Sopenharmony_ci    return CubicEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
133a3e0fd82Sopenharmony_ci}
134a3e0fd82Sopenharmony_ci
135a3e0fd82Sopenharmony_ciint16_t EasingEquation::LinearEaseNone(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
136a3e0fd82Sopenharmony_ci{
137a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
138a3e0fd82Sopenharmony_ci        int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
139a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(((t * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
140a3e0fd82Sopenharmony_ci                                    startPos);
141a3e0fd82Sopenharmony_ci    }
142a3e0fd82Sopenharmony_ci
143a3e0fd82Sopenharmony_ci    return endPos;
144a3e0fd82Sopenharmony_ci}
145a3e0fd82Sopenharmony_ci
146a3e0fd82Sopenharmony_ci/* t^2 */
147a3e0fd82Sopenharmony_ciint16_t EasingEquation::QuadEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
148a3e0fd82Sopenharmony_ci{
149a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
150a3e0fd82Sopenharmony_ci        int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
151a3e0fd82Sopenharmony_ci        int16_t x = (t * t) >> INTERPOLATION_RANGE_OFFSET;
152a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
153a3e0fd82Sopenharmony_ci                                    startPos);
154a3e0fd82Sopenharmony_ci    }
155a3e0fd82Sopenharmony_ci
156a3e0fd82Sopenharmony_ci    return endPos;
157a3e0fd82Sopenharmony_ci}
158a3e0fd82Sopenharmony_ci
159a3e0fd82Sopenharmony_ci/* 1 - (1 - t)^2 */
160a3e0fd82Sopenharmony_ciint16_t EasingEquation::QuadEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
161a3e0fd82Sopenharmony_ci{
162a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
163a3e0fd82Sopenharmony_ci        int32_t t = INTERPOLATION_RANGE - (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
164a3e0fd82Sopenharmony_ci        int16_t x = INTERPOLATION_RANGE - ((t * t) >> INTERPOLATION_RANGE_OFFSET);
165a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
166a3e0fd82Sopenharmony_ci                                    startPos);
167a3e0fd82Sopenharmony_ci    }
168a3e0fd82Sopenharmony_ci
169a3e0fd82Sopenharmony_ci    return endPos;
170a3e0fd82Sopenharmony_ci}
171a3e0fd82Sopenharmony_ci
172a3e0fd82Sopenharmony_ciint16_t EasingEquation::QuadEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
173a3e0fd82Sopenharmony_ci{
174a3e0fd82Sopenharmony_ci    uint16_t halfTime = durationTime >> 1;
175a3e0fd82Sopenharmony_ci    int16_t halfStep = (endPos >> 1) + (startPos >> 1);
176a3e0fd82Sopenharmony_ci    if (curTime < halfTime) {
177a3e0fd82Sopenharmony_ci        return QuadEaseIn(startPos, halfStep, curTime, halfTime);
178a3e0fd82Sopenharmony_ci    }
179a3e0fd82Sopenharmony_ci    return QuadEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
180a3e0fd82Sopenharmony_ci}
181a3e0fd82Sopenharmony_ci
182a3e0fd82Sopenharmony_ci/* t^5 */
183a3e0fd82Sopenharmony_ciint16_t EasingEquation::QuintEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
184a3e0fd82Sopenharmony_ci{
185a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
186a3e0fd82Sopenharmony_ci        int64_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
187a3e0fd82Sopenharmony_ci
188a3e0fd82Sopenharmony_ci        /* 4: the fourth power of t */
189a3e0fd82Sopenharmony_ci        int16_t x = (t * t * t * t * t) >> (INTERPOLATION_RANGE_OFFSET * 4);
190a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
191a3e0fd82Sopenharmony_ci                                    startPos);
192a3e0fd82Sopenharmony_ci    }
193a3e0fd82Sopenharmony_ci
194a3e0fd82Sopenharmony_ci    return endPos;
195a3e0fd82Sopenharmony_ci}
196a3e0fd82Sopenharmony_ci
197a3e0fd82Sopenharmony_ci/* 1 - (1 - t)^5 */
198a3e0fd82Sopenharmony_ciint16_t EasingEquation::QuintEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
199a3e0fd82Sopenharmony_ci{
200a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
201a3e0fd82Sopenharmony_ci        int64_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
202a3e0fd82Sopenharmony_ci        t = INTERPOLATION_RANGE - t;
203a3e0fd82Sopenharmony_ci
204a3e0fd82Sopenharmony_ci        /* 4: the fourth power of t */
205a3e0fd82Sopenharmony_ci        int16_t x = INTERPOLATION_RANGE - ((t * t * t * t * t) >> (INTERPOLATION_RANGE_OFFSET * 4));
206a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
207a3e0fd82Sopenharmony_ci                                    startPos);
208a3e0fd82Sopenharmony_ci    }
209a3e0fd82Sopenharmony_ci
210a3e0fd82Sopenharmony_ci    return endPos;
211a3e0fd82Sopenharmony_ci}
212a3e0fd82Sopenharmony_ci
213a3e0fd82Sopenharmony_ciint16_t EasingEquation::QuintEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
214a3e0fd82Sopenharmony_ci{
215a3e0fd82Sopenharmony_ci    uint16_t halfTime = durationTime >> 1;
216a3e0fd82Sopenharmony_ci    int16_t halfStep = (endPos >> 1) + (startPos >> 1);
217a3e0fd82Sopenharmony_ci    if (curTime < halfTime) {
218a3e0fd82Sopenharmony_ci        return QuintEaseIn(startPos, halfStep, curTime, halfTime);
219a3e0fd82Sopenharmony_ci    }
220a3e0fd82Sopenharmony_ci    return QuintEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
221a3e0fd82Sopenharmony_ci}
222a3e0fd82Sopenharmony_ci
223a3e0fd82Sopenharmony_ciint16_t EasingEquation::SineEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
224a3e0fd82Sopenharmony_ci{
225a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
226a3e0fd82Sopenharmony_ci        int16_t t = (curTime * QUARTER_IN_DEGREE) / durationTime - QUARTER_IN_DEGREE;
227a3e0fd82Sopenharmony_ci        float x = Sin(t) + 1;
228a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(x * (endPos - startPos)) + startPos;
229a3e0fd82Sopenharmony_ci    }
230a3e0fd82Sopenharmony_ci
231a3e0fd82Sopenharmony_ci    return endPos;
232a3e0fd82Sopenharmony_ci}
233a3e0fd82Sopenharmony_ci
234a3e0fd82Sopenharmony_ciint16_t EasingEquation::SineEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
235a3e0fd82Sopenharmony_ci{
236a3e0fd82Sopenharmony_ci    if (curTime < durationTime) {
237a3e0fd82Sopenharmony_ci        int16_t t = (curTime * QUARTER_IN_DEGREE) / durationTime;
238a3e0fd82Sopenharmony_ci        float x = Sin(t);
239a3e0fd82Sopenharmony_ci        return static_cast<int16_t>(x * (endPos - startPos)) + startPos;
240a3e0fd82Sopenharmony_ci    }
241a3e0fd82Sopenharmony_ci
242a3e0fd82Sopenharmony_ci    return endPos;
243a3e0fd82Sopenharmony_ci}
244a3e0fd82Sopenharmony_ci
245a3e0fd82Sopenharmony_ciint16_t EasingEquation::SineEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
246a3e0fd82Sopenharmony_ci{
247a3e0fd82Sopenharmony_ci    uint16_t halfTime = durationTime >> 1;
248a3e0fd82Sopenharmony_ci    int16_t halfStep = (endPos >> 1) + (startPos >> 1);
249a3e0fd82Sopenharmony_ci    if (curTime < halfTime) {
250a3e0fd82Sopenharmony_ci        return SineEaseIn(startPos, halfStep, curTime, halfTime);
251a3e0fd82Sopenharmony_ci    }
252a3e0fd82Sopenharmony_ci    return SineEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
253a3e0fd82Sopenharmony_ci}
254a3e0fd82Sopenharmony_ci} // namespace OHOS
255