• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_CURVE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_CURVE_H
18 
19 #include "base/memory/ace_type.h"
20 #include "base/utils/macros.h"
21 #include "base/utils/utils.h"
22 #ifdef LINUX_PLATFORM
23 #include <functional>
24 #endif
25 
26 namespace OHOS::Ace {
27 class NativeCurveHelper;
28 
29 constexpr double SQUARE = 2.0;
30 
31 // The running time of the curve needs to be normalized to the interval of 0.0 to 1.0;
32 // Relatively, the corresponding value of the curve also needs to be normalized to the interval of 0.0 to 1.0;
33 class ACE_EXPORT_WITH_PREVIEW Curve : public AceType {
34     DECLARE_ACE_TYPE(Curve, AceType);
35 
36 public:
37     Curve() = default;
38     ~Curve() override = default;
39 
40     // Returns the value at specific time.
41     // Notice: The value of time must be between 0.0 and 1.0 since the curve uses normalized timestamp.
Move(float time)42     float Move(float time)
43     {
44         // time always between 0.0 and 1.0
45         return MoveInternal(time);
46     }
47 
48     // Each subclass needs to override this method to implement motion in the 0.0 to 1.0 time range.
49     virtual float MoveInternal(float time) = 0;
ToString()50     virtual const std::string ToString()
51     {
52         return "";
53     }
54 };
55 
56 // The reverse curve is used to convert the direction of motion.
57 // It uses the 1.0->0.0 motion of the child curve to achieve the reverse purpose.
58 class ReverseCurve final : public Curve {
59     DECLARE_ACE_TYPE(ReverseCurve, Curve);
60 
61 public:
ReverseCurve(const RefPtr<Curve> & curve)62     explicit ReverseCurve(const RefPtr<Curve>& curve) : curve_(curve) {}
63     ~ReverseCurve() override = default;
64 
MoveInternal(float time)65     float MoveInternal(float time) final
66     {
67         if (!curve_) {
68             return 0.0f;
69         }
70 
71         if (time > 1.0f || time < 0.0f) {
72             return curve_->MoveInternal(0.0f);
73         }
74         return curve_->MoveInternal(1.0f - time);
75     }
76 
77 private:
78     const RefPtr<Curve> curve_;
79 };
80 
81 class ComplementaryCurve final : public Curve {
82     DECLARE_ACE_TYPE(ComplementaryCurve, Curve);
83 
84 public:
ComplementaryCurve(const RefPtr<Curve> & curve)85     explicit ComplementaryCurve(const RefPtr<Curve>& curve) : curve_(curve) {}
86     ~ComplementaryCurve() override = default;
87 
MoveInternal(float time)88     float MoveInternal(float time) final
89     {
90         if (!curve_) {
91             return 0.0f;
92         }
93 
94         if (time > 1.0f || time < 0.0f) {
95             return curve_->MoveInternal(0.0f);
96         }
97         return 1.0f - curve_->MoveInternal(time);
98     }
99 
100 private:
101     const RefPtr<Curve> curve_;
102 };
103 
104 class DecelerationCurve final : public Curve {
105     DECLARE_ACE_TYPE(DecelerationCurve, Curve);
106 
107 public:
MoveInternal(float time)108     float MoveInternal(float time) override
109     {
110         return 1.0f - std::pow(1.0f - time, SQUARE);
111     }
112 };
113 
114 class LinearCurve final : public Curve {
115     DECLARE_ACE_TYPE(LinearCurve, Curve);
116 
117 public:
MoveInternal(float time)118     float MoveInternal(float time) override
119     {
120         if (time < fractionMin || time > fractionMax) {
121             LOGE("LinearCurve MoveInternal: time is less than 0 or larger than 1, return 1");
122             return fractionMax;
123         }
124         return time;
125     }
126 private:
127     float fractionMin = 0.0f;
128     float fractionMax = 1.0f;
129 };
130 
131 class SineCurve final : public Curve {
132     DECLARE_ACE_TYPE(SineCurve, Curve);
133 
134 public:
MoveInternal(float time)135     float MoveInternal(float time) override
136     {
137         static constexpr float PI = 3.14f;
138         return std::sin(PI * time / 2.0f); // half period
139     }
140 };
141 
142 class ElasticsCurve final : public Curve {
143     DECLARE_ACE_TYPE(ElasticsCurve, Curve);
144 
145 public:
ElasticsCurve(float tension)146     explicit ElasticsCurve(float tension) : tension_(tension) {}
147     ~ElasticsCurve() override = default;
MoveInternal(float time)148     float MoveInternal(float time) override
149     {
150         float para = time - 1.0f;
151         return para * para * ((tension_ + 1.0f) * para + tension_) + 1.0f;
152     }
153 
154 private:
155     float tension_ = 2.0f; // Default Elastics tension.
156 };
157 
158 enum class StepsCurvePosition {
159     START,
160     END,
161 };
162 
163 class StepsCurve : public Curve {
164     DECLARE_ACE_TYPE(StepsCurve, Curve);
165 
166 public:
167     explicit StepsCurve(int32_t steps, StepsCurvePosition position = StepsCurvePosition::START)
168         : steps_(steps <= 0 ? 1 : steps), position_(position) {}
169     ~StepsCurve() override = default;
170 
MoveInternal(float time)171     float MoveInternal(float time) override
172     {
173         if (time < fractionMin || time > fractionMax) {
174             LOGE("StepsCurve MoveInternal: time is less than 0 or larger than 1, return 1");
175             return fractionMax;
176         }
177         auto currentStep = static_cast<int32_t>(time * steps_);
178         if (position_ == StepsCurvePosition::START) {
179             currentStep++;
180         }
181         return static_cast<float>(currentStep) / steps_;
182     }
ToString()183     const std::string ToString() override
184     {
185         std::string curveString("steps");
186         std::string comma(",");
187         curveString.append(std::string("(") + std::to_string(steps_) + comma);
188         if (position_ == StepsCurvePosition::START) {
189             curveString.append(std::string("start"));
190         } else {
191             curveString.append(std::string("end"));
192         }
193         curveString.append(std::string(")"));
194         return curveString;
195     }
196 private:
197     int32_t steps_;
198     const StepsCurvePosition position_;
199     float fractionMin = 0.0f;
200     float fractionMax = 1.0f;
201 
202     friend class NativeCurveHelper;
203 };
204 
205 class CustomCurve final : public Curve {
206     DECLARE_ACE_TYPE(CustomCurve, Curve);
207 
208 public:
CustomCurve(const std::function<float (float)> & func)209     explicit CustomCurve(const std::function<float(float)>& func) : interpolateFunc_(func) {}
210     ~CustomCurve() override = default;
MoveInternal(float time)211     float MoveInternal(float time) override
212     {
213         float value = interpolateFunc_(time);
214         return std::clamp(value, 0.f, 1.f);
215     }
216 
217 private:
218     std::function<float(float)> interpolateFunc_;
219 
220     friend class NativeCurveHelper;
221 };
222 
223 class ResponsiveSpringMotion final : public Curve {
224     DECLARE_ACE_TYPE(ResponsiveSpringMotion, Curve);
225 
226 public:
227     ResponsiveSpringMotion(float response, float dampingRatio, float blendDuration = 0.0f)
response_(response)228         : response_(response), dampingRatio_(dampingRatio), blendDuration_(blendDuration) {}
229     ~ResponsiveSpringMotion() override = default;
230     // this MoveInterval function is not the real implementation of the function.
231     // The curve should use the curve in rosen.
MoveInternal(float time)232     float MoveInternal(float time) override
233     {
234         return 0.0f;
235     }
ToString()236     const std::string ToString() override
237     {
238         std::string curveString("responsive-spring-motion");
239         std::string comma(",");
240         curveString.append(std::string("(") + std::to_string(response_) + comma + std::to_string(dampingRatio_) +
241                             comma + std::to_string(blendDuration_) + std::string(")"));
242         return curveString;
243     }
GetResponse()244     float GetResponse() const
245     {
246         return response_;
247     }
GetDampingRatio()248     float GetDampingRatio() const
249     {
250         return dampingRatio_;
251     }
GetBlendDuration()252     float GetBlendDuration() const
253     {
254         return blendDuration_;
255     }
256     static constexpr float DEFAULT_SPRING_MOTION_RESPONSE = 0.55f;
257     static constexpr float DEFAULT_SPRING_MOTION_DAMPING_RATIO = 0.825f;
258     static constexpr float DEFAULT_SPRING_MOTION_BLEND_DURATION = 0.0f;
259     static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE = 0.15f;
260     static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO = 0.86f;
261     static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION = 0.25f;
262 private:
263     float response_;
264     float dampingRatio_;
265     float blendDuration_;
266 };
267 
268 } // namespace OHOS::Ace
269 
270 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_CURVE_H
271