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 19namespace OHOS { 20double EasingEquation::overshoot_ = 1.7; // The empirical value commonly used in easing equation 21 22void EasingEquation::SetBackOvershoot(double overshoot) 23{ 24 if ((overshoot >= OVERSHOOT_MIN) && (overshoot <= OVERSHOOT_MAX)) { 25 overshoot_ = overshoot; 26 } 27} 28 29int16_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 40int16_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 52int16_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) */ 63int16_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) */ 76int16_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 88int16_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 */ 99int16_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 */ 112int16_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 125int16_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 135int16_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 */ 147int16_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 */ 160int16_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 172int16_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 */ 183int16_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 */ 198int16_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 213int16_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 223int16_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 234int16_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 245int16_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