1 /*
2  * Copyright (c) 2021-2023 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 <functional>
20 
21 #include "base/memory/ace_type.h"
22 #include "base/utils/macros.h"
23 #include "base/utils/utils.h"
24 
25 namespace OHOS::Ace {
26 class NativeCurveHelper;
27 
28 constexpr double SQUARE = 2.0;
29 
30 // The running time of the curve needs to be normalized to the interval of 0.0 to 1.0;
31 // Relatively, the corresponding value of the curve also needs to be normalized to the interval of 0.0 to 1.0;
32 class ACE_FORCE_EXPORT Curve : public AceType {
33     DECLARE_ACE_TYPE(Curve, AceType);
34 
35 public:
36     Curve() = default;
37     ~Curve() override = default;
38 
39     // Returns the value at specific time.
40     // Notice: The value of time must be between 0.0 and 1.0 since the curve uses normalized timestamp.
Move(float time)41     float Move(float time)
42     {
43         // time always between 0.0 and 1.0
44         return MoveInternal(time);
45     }
46 
47     // Each subclass needs to override this method to implement motion in the 0.0 to 1.0 time range.
48     virtual float MoveInternal(float time) = 0;
ToString()49     virtual const std::string ToString()
50     {
51         return "";
52     }
53 
IsEqual(const RefPtr<Curve> & curve)54     virtual bool IsEqual(const RefPtr<Curve>& curve) const
55     {
56         return false;
57     }
58 };
59 
60 // The reverse curve is used to convert the direction of motion.
61 // It uses the 1.0->0.0 motion of the child curve to achieve the reverse purpose.
62 class ReverseCurve final : public Curve {
63     DECLARE_ACE_TYPE(ReverseCurve, Curve);
64 
65 public:
ReverseCurve(const RefPtr<Curve> & curve)66     explicit ReverseCurve(const RefPtr<Curve>& curve) : curve_(curve) {}
67     ~ReverseCurve() override = default;
68 
MoveInternal(float time)69     float MoveInternal(float time) final
70     {
71         if (!curve_) {
72             return 0.0f;
73         }
74 
75         if (time > 1.0f || time < 0.0f) {
76             return curve_->MoveInternal(0.0f);
77         }
78         return curve_->MoveInternal(1.0f - time);
79     }
80 private:
81     const RefPtr<Curve> curve_;
82 };
83 
84 class ComplementaryCurve final : public Curve {
85     DECLARE_ACE_TYPE(ComplementaryCurve, Curve);
86 
87 public:
ComplementaryCurve(const RefPtr<Curve> & curve)88     explicit ComplementaryCurve(const RefPtr<Curve>& curve) : curve_(curve) {}
89     ~ComplementaryCurve() override = default;
90 
MoveInternal(float time)91     float MoveInternal(float time) final
92     {
93         if (!curve_) {
94             return 0.0f;
95         }
96 
97         if (time > 1.0f || time < 0.0f) {
98             return curve_->MoveInternal(0.0f);
99         }
100         return 1.0f - curve_->MoveInternal(time);
101     }
102 private:
103     const RefPtr<Curve> curve_;
104 };
105 
106 class DecelerationCurve final : public Curve {
107     DECLARE_ACE_TYPE(DecelerationCurve, Curve);
108 
109 public:
MoveInternal(float time)110     float MoveInternal(float time) override
111     {
112         return 1.0f - std::pow(1.0f - time, SQUARE);
113     }
114 
IsEqual(const RefPtr<Curve> & curve)115     bool IsEqual(const RefPtr<Curve>& curve) const override
116     {
117         return AceType::InstanceOf<DecelerationCurve>(curve);
118     }
119 };
120 
121 class LinearCurve final : public Curve {
122     DECLARE_ACE_TYPE(LinearCurve, Curve);
123 
124 public:
MoveInternal(float time)125     float MoveInternal(float time) override
126     {
127         if (time < fractionMin || time > fractionMax) {
128             LOGE("LinearCurve MoveInternal: time is less than 0 or larger than 1, return 1");
129             return fractionMax;
130         }
131         return time;
132     }
133 
ToString()134     const std::string ToString() override
135     {
136         std::string curveString("linear");
137         return curveString;
138     }
139 
IsEqual(const RefPtr<Curve> & curve)140     bool IsEqual(const RefPtr<Curve>& curve) const override
141     {
142         return AceType::InstanceOf<LinearCurve>(curve);
143     }
144 
145 private:
146     float fractionMin = 0.0f;
147     float fractionMax = 1.0f;
148 };
149 
150 class SineCurve final : public Curve {
151     DECLARE_ACE_TYPE(SineCurve, Curve);
152 
153 public:
MoveInternal(float time)154     float MoveInternal(float time) override
155     {
156         static constexpr float PI = 3.14f;
157         return std::sin(PI * time / 2.0f); // half period
158     }
159 
IsEqual(const RefPtr<Curve> & curve)160     bool IsEqual(const RefPtr<Curve>& curve) const override
161     {
162         return AceType::InstanceOf<SineCurve>(curve);
163     }
164 };
165 
166 class ElasticsCurve final : public Curve {
167     DECLARE_ACE_TYPE(ElasticsCurve, Curve);
168 
169 public:
ElasticsCurve(float tension)170     explicit ElasticsCurve(float tension) : tension_(tension) {}
171     ~ElasticsCurve() override = default;
MoveInternal(float time)172     float MoveInternal(float time) override
173     {
174         float para = time - 1.0f;
175         return para * para * ((tension_ + 1.0f) * para + tension_) + 1.0f;
176     }
177 
GetTension()178     float GetTension() const
179     {
180         return tension_;
181     }
182 
IsEqual(const RefPtr<Curve> & curve)183     bool IsEqual(const RefPtr<Curve>& curve) const override
184     {
185         auto other = AceType::DynamicCast<ElasticsCurve>(curve);
186         if (!other) {
187             return false;
188         }
189         return NearEqual(other->GetTension(), tension_);
190     }
191 private:
192     float tension_ = 2.0f; // Default Elastics tension.
193 };
194 
195 enum class StepsCurvePosition {
196     START,
197     END,
198 };
199 
200 class StepsCurve : public Curve {
201     DECLARE_ACE_TYPE(StepsCurve, Curve);
202 
203 public:
204     explicit StepsCurve(int32_t steps, StepsCurvePosition position = StepsCurvePosition::START)
205         : steps_(steps <= 0 ? 1 : steps), position_(position)
206     {}
207     ~StepsCurve() override = default;
208 
MoveInternal(float time)209     float MoveInternal(float time) override
210     {
211         if (time < fractionMin || time > fractionMax) {
212             LOGE("StepsCurve MoveInternal: time is less than 0 or larger than 1, return 1");
213             return fractionMax;
214         }
215         auto currentStep = static_cast<int32_t>(time * steps_);
216         if (position_ == StepsCurvePosition::START && currentStep < steps_) {
217             currentStep++;
218         }
219         return static_cast<float>(currentStep) / steps_;
220     }
ToString()221     const std::string ToString() override
222     {
223         std::string curveString("steps");
224         std::string comma(",");
225         curveString.append(std::string("(") + std::to_string(steps_) + comma);
226         if (position_ == StepsCurvePosition::START) {
227             curveString.append(std::string("start"));
228         } else {
229             curveString.append(std::string("end"));
230         }
231         curveString.append(std::string(")"));
232         return curveString;
233     }
234 
IsEqual(const RefPtr<Curve> & curve)235     bool IsEqual(const RefPtr<Curve>& curve) const override
236     {
237         auto other = AceType::DynamicCast<StepsCurve>(curve);
238         if (other) {
239             return false;
240         }
241         return other->GetSteps() == steps_ && other->GetStepsCurvePosition() == position_;
242     }
243 
GetSteps()244     int32_t GetSteps() const
245     {
246         return steps_;
247     }
248 
GetStepsCurvePosition()249     StepsCurvePosition GetStepsCurvePosition() const
250     {
251         return position_;
252     }
253 
254 private:
255     int32_t steps_;
256     const StepsCurvePosition position_;
257     float fractionMin = 0.0f;
258     float fractionMax = 1.0f;
259 
260     friend class NativeCurveHelper;
261 };
262 
263 class CustomCurve final : public Curve {
264     DECLARE_ACE_TYPE(CustomCurve, Curve);
265 
266 public:
CustomCurve(const std::function<float (float)> & func)267     explicit CustomCurve(const std::function<float(float)>& func) : interpolateFunc_(func) {}
268     ~CustomCurve() override = default;
MoveInternal(float time)269     float MoveInternal(float time) override
270     {
271         return interpolateFunc_ ? interpolateFunc_(time) : 1.0f;
272     }
ToString()273     const std::string ToString() override
274     {
275         return "customCallback";
276     }
277 private:
278     std::function<float(float)> interpolateFunc_;
279 
280     friend class NativeCurveHelper;
281 };
282 
283 class ResponsiveSpringMotion final : public Curve {
284     DECLARE_ACE_TYPE(ResponsiveSpringMotion, Curve);
285 
286 public:
287     ResponsiveSpringMotion(float response, float dampingRatio, float blendDuration = 0.0f)
288         : response_(response), dampingRatio_(dampingRatio), blendDuration_(blendDuration)
289     {}
290     ~ResponsiveSpringMotion() override = default;
291     // this MoveInterval function is not the real implementation of the function.
292     // The curve should use the curve in rosen.
MoveInternal(float time)293     float MoveInternal(float time) override
294     {
295         return 0.0f;
296     }
ToString()297     const std::string ToString() override
298     {
299         std::string curveString("responsive-spring-motion");
300         std::string comma(",");
301         curveString.append(std::string("(") + std::to_string(response_) + comma + std::to_string(dampingRatio_) +
302                            comma + std::to_string(blendDuration_) + std::string(")"));
303         return curveString;
304     }
IsEqual(const RefPtr<Curve> & curve)305     bool IsEqual(const RefPtr<Curve>& curve) const override
306     {
307         auto other = AceType::DynamicCast<ResponsiveSpringMotion>(curve);
308         if (!other) {
309             return false;
310         }
311         return NearEqual(other->GetResponse(), response_) && NearEqual(other->GetDampingRatio(), dampingRatio_) &&
312                NearEqual(other->GetBlendDuration(), blendDuration_);
313     }
GetResponse()314     float GetResponse() const
315     {
316         return response_;
317     }
GetDampingRatio()318     float GetDampingRatio() const
319     {
320         return dampingRatio_;
321     }
GetBlendDuration()322     float GetBlendDuration() const
323     {
324         return blendDuration_;
325     }
326     static constexpr float DEFAULT_SPRING_MOTION_RESPONSE = 0.55f;
327     static constexpr float DEFAULT_SPRING_MOTION_DAMPING_RATIO = 0.825f;
328     static constexpr float DEFAULT_SPRING_MOTION_BLEND_DURATION = 0.0f;
329     static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE = 0.15f;
330     static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO = 0.86f;
331     static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION = 0.25f;
332 
333 private:
334     float response_;
335     float dampingRatio_;
336     float blendDuration_;
337 };
338 
339 class InterpolatingSpring final : public Curve {
340     DECLARE_ACE_TYPE(InterpolatingSpring, Curve);
341 
342 public:
InterpolatingSpring(float velocity,float mass,float stiffness,float damping)343     InterpolatingSpring(float velocity, float mass, float stiffness, float damping)
344         : velocity_(velocity), mass_(mass), stiffness_(stiffness), damping_(damping)
345     {}
346     ~InterpolatingSpring() override = default;
347     // this MoveInterval function is not the real implementation of the function.
348     // The curve should use the curve in rosen.
MoveInternal(float time)349     float MoveInternal(float time) override
350     {
351         return 0.0f;
352     }
ToString()353     const std::string ToString() override
354     {
355         std::string curveString("interpolating-spring");
356         std::string comma(",");
357         curveString.append(std::string("(") + std::to_string(velocity_) + comma + std::to_string(mass_) + comma +
358                            std::to_string(stiffness_) + comma + std::to_string(damping_) + std::string(")"));
359         return curveString;
360     }
361 
IsEqual(const RefPtr<Curve> & curve)362     bool IsEqual(const RefPtr<Curve>& curve) const override
363     {
364         auto other = AceType::DynamicCast<InterpolatingSpring>(curve);
365         if (!other) {
366             return false;
367         }
368         return NearEqual(other->GetVelocity(), velocity_) && NearEqual(other->GetMass(), mass_) &&
369                NearEqual(other->GetStiffness(), stiffness_) && NearEqual(other->GetDamping(), damping_);
370     }
371 
GetVelocity()372     float GetVelocity() const
373     {
374         return velocity_;
375     }
376 
UpdateVelocity(float velocity)377     void UpdateVelocity(float velocity)
378     {
379         velocity_ = velocity;
380     }
381 
GetMass()382     float GetMass() const
383     {
384         return mass_;
385     }
386 
GetStiffness()387     float GetStiffness() const
388     {
389         return stiffness_;
390     }
391 
GetDamping()392     float GetDamping() const
393     {
394         return damping_;
395     }
396 
GetMinimumAmplitudeRatio()397     float GetMinimumAmplitudeRatio() const
398     {
399         return minimumAmplitudeRatio_;
400     }
401 
UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio)402     void UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio)
403     {
404         minimumAmplitudeRatio_ = minimumAmplitudeRatio;
405     }
406 
407     static constexpr float DEFAULT_INTERPOLATING_SPRING_MASS = 1.0f;
408     static constexpr float DEFAULT_INTERPOLATING_SPRING_VELOCITY = 0.0f;
409     static constexpr float DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO = 0.00025f;
410 
411 private:
412     float velocity_ = 0.0f;
413     float mass_ = 0.0f;
414     float stiffness_ = 0.0f;
415     float damping_ = 0.0f;
416     float minimumAmplitudeRatio_ = DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO;
417 };
418 
419 } // namespace OHOS::Ace
420 
421 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_CURVE_H
422