• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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_INTERFACES_INNER_API_ACE_KIT_INCLUDE_ANIMATION_CURVE_H
17 #define FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_ANIMATION_CURVE_H
18 
19 #include <functional>
20 #include <math.h>
21 
22 #include "ui/base/ace_type.h"
23 #include "ui/base/macros.h"
24 #include "ui/base/utils/utils.h"
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_FORCE_EXPORT 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 
IsEqual(const RefPtr<Curve> & curve)55     virtual bool IsEqual(const RefPtr<Curve>& curve) const
56     {
57         return false;
58     }
59 };
60 
61 // The reverse curve is used to convert the direction of motion.
62 // It uses the 1.0->0.0 motion of the child curve to achieve the reverse purpose.
63 class ReverseCurve final : public Curve {
64     DECLARE_ACE_TYPE(ReverseCurve, Curve);
65 
66 public:
ReverseCurve(const RefPtr<Curve> & curve)67     explicit ReverseCurve(const RefPtr<Curve>& curve) : curve_(curve) {}
68     ~ReverseCurve() override = default;
69 
MoveInternal(float time)70     float MoveInternal(float time) final
71     {
72         if (!curve_) {
73             return 0.0f;
74         }
75 
76         if (time > 1.0f || time < 0.0f) {
77             return curve_->MoveInternal(0.0f);
78         }
79         return curve_->MoveInternal(1.0f - time);
80     }
81 private:
82     const RefPtr<Curve> curve_;
83 };
84 
85 class ComplementaryCurve final : public Curve {
86     DECLARE_ACE_TYPE(ComplementaryCurve, Curve);
87 
88 public:
ComplementaryCurve(const RefPtr<Curve> & curve)89     explicit ComplementaryCurve(const RefPtr<Curve>& curve) : curve_(curve) {}
90     ~ComplementaryCurve() override = default;
91 
MoveInternal(float time)92     float MoveInternal(float time) final
93     {
94         if (!curve_) {
95             return 0.0f;
96         }
97 
98         if (time > 1.0f || time < 0.0f) {
99             return curve_->MoveInternal(0.0f);
100         }
101         return 1.0f - curve_->MoveInternal(time);
102     }
103 private:
104     const RefPtr<Curve> curve_;
105 };
106 
107 class DecelerationCurve final : public Curve {
108     DECLARE_ACE_TYPE(DecelerationCurve, Curve);
109 
110 public:
MoveInternal(float time)111     float MoveInternal(float time) override
112     {
113         return 1.0f - std::pow(1.0f - time, SQUARE);
114     }
115 
IsEqual(const RefPtr<Curve> & curve)116     bool IsEqual(const RefPtr<Curve>& curve) const override
117     {
118         return AceType::InstanceOf<DecelerationCurve>(curve);
119     }
120 };
121 
122 class LinearCurve final : public Curve {
123     DECLARE_ACE_TYPE(LinearCurve, Curve);
124 
125 public:
MoveInternal(float time)126     float MoveInternal(float time) override
127     {
128         if (time < fractionMin || time > fractionMax) {
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             return fractionMax;
213         }
214         auto currentStep = static_cast<int32_t>(time * steps_);
215         if (position_ == StepsCurvePosition::START && currentStep < steps_) {
216             currentStep++;
217         }
218         return static_cast<float>(currentStep) / steps_;
219     }
ToString()220     const std::string ToString() override
221     {
222         std::string curveString("steps");
223         std::string comma(",");
224         curveString.append(std::string("(") + std::to_string(steps_) + comma);
225         if (position_ == StepsCurvePosition::START) {
226             curveString.append(std::string("start"));
227         } else {
228             curveString.append(std::string("end"));
229         }
230         curveString.append(std::string(")"));
231         return curveString;
232     }
233 
IsEqual(const RefPtr<Curve> & curve)234     bool IsEqual(const RefPtr<Curve>& curve) const override
235     {
236         auto other = AceType::DynamicCast<StepsCurve>(curve);
237         if (!other) {
238             return false;
239         }
240         return other->GetSteps() == steps_ && other->GetStepsCurvePosition() == position_;
241     }
242 
GetSteps()243     int32_t GetSteps() const
244     {
245         return steps_;
246     }
247 
GetStepsCurvePosition()248     StepsCurvePosition GetStepsCurvePosition() const
249     {
250         return position_;
251     }
252 
253 private:
254     int32_t steps_;
255     const StepsCurvePosition position_;
256     float fractionMin = 0.0f;
257     float fractionMax = 1.0f;
258 
259     friend class NativeCurveHelper;
260 };
261 
262 class CustomCurve final : public Curve {
263     DECLARE_ACE_TYPE(CustomCurve, Curve);
264 
265 public:
CustomCurve(const std::function<float (float)> & func)266     explicit CustomCurve(const std::function<float(float)>& func) : interpolateFunc_(func) {}
267     ~CustomCurve() override = default;
MoveInternal(float time)268     float MoveInternal(float time) override
269     {
270         return interpolateFunc_ ? interpolateFunc_(time) : 1.0f;
271     }
ToString()272     const std::string ToString() override
273     {
274         return "customCallback";
275     }
276 private:
277     std::function<float(float)> interpolateFunc_;
278 
279     friend class NativeCurveHelper;
280 };
281 
282 class ResponsiveSpringMotion final : public Curve {
283     DECLARE_ACE_TYPE(ResponsiveSpringMotion, Curve);
284 
285 public:
286     ResponsiveSpringMotion(float response, float dampingRatio, float blendDuration = 0.0f)
response_(response)287         : response_(response), dampingRatio_(dampingRatio), blendDuration_(blendDuration)
288     {}
289     ~ResponsiveSpringMotion() override = default;
290     // this MoveInterval function is not the real implementation of the function.
291     // The curve should use the curve in rosen.
MoveInternal(float time)292     float MoveInternal(float time) override
293     {
294         return 0.0f;
295     }
ToString()296     const std::string ToString() override
297     {
298         std::string curveString("responsive-spring-motion");
299         std::string comma(",");
300         curveString.append(std::string("(") + std::to_string(response_) + comma + std::to_string(dampingRatio_) +
301                            comma + std::to_string(blendDuration_) + std::string(")"));
302         return curveString;
303     }
IsEqual(const RefPtr<Curve> & curve)304     bool IsEqual(const RefPtr<Curve>& curve) const override
305     {
306         auto other = AceType::DynamicCast<ResponsiveSpringMotion>(curve);
307         if (!other) {
308             return false;
309         }
310         return NearEqual(other->GetResponse(), response_) && NearEqual(other->GetDampingRatio(), dampingRatio_) &&
311                NearEqual(other->GetBlendDuration(), blendDuration_);
312     }
GetResponse()313     float GetResponse() const
314     {
315         return response_;
316     }
GetDampingRatio()317     float GetDampingRatio() const
318     {
319         return dampingRatio_;
320     }
GetBlendDuration()321     float GetBlendDuration() const
322     {
323         return blendDuration_;
324     }
GetMinimumAmplitudeRatio()325     float GetMinimumAmplitudeRatio() const
326     {
327         return minimumAmplitudeRatio_;
328     }
UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio)329     void UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio)
330     {
331         minimumAmplitudeRatio_ = minimumAmplitudeRatio;
332     }
333     static constexpr float DEFAULT_SPRING_MOTION_RESPONSE = 0.55f;
334     static constexpr float DEFAULT_SPRING_MOTION_DAMPING_RATIO = 0.825f;
335     static constexpr float DEFAULT_SPRING_MOTION_BLEND_DURATION = 0.0f;
336     static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE = 0.15f;
337     static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO = 0.86f;
338     static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION = 0.25f;
339     static constexpr float DEFAULT_RESPONSIVE_SPRING_AMPLITUDE_RATIO = 0.001f;
340 
341 private:
342     float response_;
343     float dampingRatio_;
344     float blendDuration_;
345     float minimumAmplitudeRatio_ = DEFAULT_RESPONSIVE_SPRING_AMPLITUDE_RATIO;
346 };
347 
348 class InterpolatingSpring final : public Curve {
349     DECLARE_ACE_TYPE(InterpolatingSpring, Curve);
350 
351 public:
InterpolatingSpring(float velocity,float mass,float stiffness,float damping)352     InterpolatingSpring(float velocity, float mass, float stiffness, float damping)
353         : velocity_(velocity), mass_(mass), stiffness_(stiffness), damping_(damping)
354     {}
355     ~InterpolatingSpring() override = default;
356     // this MoveInterval function is not the real implementation of the function.
357     // The curve should use the curve in rosen.
MoveInternal(float time)358     float MoveInternal(float time) override
359     {
360         return 0.0f;
361     }
ToString()362     const std::string ToString() override
363     {
364         std::string curveString("interpolating-spring");
365         std::string comma(",");
366         curveString.append(std::string("(") + std::to_string(velocity_) + comma + std::to_string(mass_) + comma +
367                            std::to_string(stiffness_) + comma + std::to_string(damping_) + std::string(")"));
368         return curveString;
369     }
370 
IsEqual(const RefPtr<Curve> & curve)371     bool IsEqual(const RefPtr<Curve>& curve) const override
372     {
373         auto other = AceType::DynamicCast<InterpolatingSpring>(curve);
374         if (!other) {
375             return false;
376         }
377         return NearEqual(other->GetVelocity(), velocity_) && NearEqual(other->GetMass(), mass_) &&
378                NearEqual(other->GetStiffness(), stiffness_) && NearEqual(other->GetDamping(), damping_);
379     }
380 
GetVelocity()381     float GetVelocity() const
382     {
383         return velocity_;
384     }
385 
UpdateVelocity(float velocity)386     void UpdateVelocity(float velocity)
387     {
388         velocity_ = velocity;
389     }
390 
GetMass()391     float GetMass() const
392     {
393         return mass_;
394     }
395 
GetStiffness()396     float GetStiffness() const
397     {
398         return stiffness_;
399     }
400 
GetDamping()401     float GetDamping() const
402     {
403         return damping_;
404     }
405 
GetMinimumAmplitudeRatio()406     float GetMinimumAmplitudeRatio() const
407     {
408         return minimumAmplitudeRatio_;
409     }
410 
UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio)411     void UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio)
412     {
413         minimumAmplitudeRatio_ = minimumAmplitudeRatio;
414     }
415 
416     static constexpr float DEFAULT_INTERPOLATING_SPRING_MASS = 1.0f;
417     static constexpr float DEFAULT_INTERPOLATING_SPRING_VELOCITY = 0.0f;
418     static constexpr float DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO = 0.00025f;
419 
420 private:
421     float velocity_ = 0.0f;
422     float mass_ = 0.0f;
423     float stiffness_ = 0.0f;
424     float damping_ = 0.0f;
425     float minimumAmplitudeRatio_ = DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO;
426 };
427 } // namespace OHOS::Ace
428 
429 #endif // FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_ANIMATION_CURVE_H
430