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