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
16 #include "animation/rs_cubic_bezier_interpolator.h"
17
18 namespace OHOS {
19 namespace Rosen {
20 namespace {
GetCubicBezierValue(const float time,const float ctl1,const float ctl2)21 inline float GetCubicBezierValue(const float time, const float ctl1, const float ctl2)
22 {
23 if (time < 0.0f) {
24 return 0.0f;
25 }
26 if (time > 1.0f) {
27 return 1.0f;
28 }
29 constexpr static int three = 3.0;
30 const float oneMinusTime = 1.0f - time;
31 return three * oneMinusTime * oneMinusTime * time * ctl1 + three * oneMinusTime * time * time * ctl2 +
32 time * time * time;
33 }
34 } // namespace
35
RSCubicBezierInterpolator(float ctlX1,float ctlY1,float ctlX2,float ctlY2)36 RSCubicBezierInterpolator::RSCubicBezierInterpolator(float ctlX1, float ctlY1, float ctlX2, float ctlY2)
37 : controlX1_(ctlX1), controlY1_(ctlY1), controlX2_(ctlX2), controlY2_(ctlY2)
38 {}
39
RSCubicBezierInterpolator(uint64_t id,float ctlX1,float ctlY1,float ctlX2,float ctlY2)40 RSCubicBezierInterpolator::RSCubicBezierInterpolator(uint64_t id, float ctlX1, float ctlY1, float ctlX2, float ctlY2)
41 : RSInterpolator(id), controlX1_(ctlX1), controlY1_(ctlY1), controlX2_(ctlX2), controlY2_(ctlY2)
42 {}
43
InterpolateImpl(float input) const44 float RSCubicBezierInterpolator::InterpolateImpl(float input) const
45 {
46 constexpr float ONE = 1.0f;
47 if (ROSEN_EQ(input, ONE, 1e-6f)) {
48 return ONE;
49 }
50 return GetCubicBezierValue(SEARCH_STEP * BinarySearch(input), controlY1_, controlY2_);
51 }
52
BinarySearch(float key) const53 int RSCubicBezierInterpolator::BinarySearch(float key) const
54 {
55 int low = 0;
56 int high = MAX_RESOLUTION;
57 int middle = 0;
58 float approximation = 0.0;
59 constexpr float epsilon = 1e-6f;
60 while (low <= high) {
61 middle = (static_cast<unsigned int>(low + high)) >> 1;
62 approximation = GetCubicBezierValue(SEARCH_STEP * middle, controlX1_, controlX2_);
63 if (ROSEN_EQ(approximation, key, epsilon)) {
64 // Early exit if the key is found within an acceptable error range
65 return middle;
66 } else if (approximation < key) {
67 low = middle + 1;
68 } else {
69 high = middle - 1;
70 }
71 }
72 return low;
73 }
74 } // namespace Rosen
75 } // namespace OHOS
76