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