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 "node/animate_impl.h"
17 #include <cstddef>
18 
19 #include "node/node_model.h"
20 
21 #include "base/error/error_code.h"
22 
23 namespace OHOS::Ace::AnimateModel {
24 
AnimateTo(ArkUI_ContextHandle context,ArkUI_AnimateOption * option,ArkUI_ContextCallback * update,ArkUI_AnimateCompleteCallback * complete)25 int32_t AnimateTo(ArkUI_ContextHandle context, ArkUI_AnimateOption* option, ArkUI_ContextCallback* update,
26     ArkUI_AnimateCompleteCallback* complete)
27 {
28     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
29     if (!impl || !context || !option || !update || !update->callback) {
30         return ERROR_CODE_PARAM_INVALID;
31     }
32 
33     ArkUIAnimateOption animateOption {};
34     animateOption.duration = option->duration;
35     animateOption.tempo = option->tempo;
36     animateOption.curve = static_cast<ArkUI_Int32>(option->curve);
37     animateOption.delay = option->delay;
38     animateOption.iterations = option->iterations;
39     if (option->iCurve) {
40         animateOption.iCurve = option->iCurve->curve;
41         animateOption.curveType = option->iCurve->baseCurveType;
42     }
43     animateOption.playMode = static_cast<ArkUI_Int32>(option->playMode);
44     if (option->expectedFrameRateRange) {
45         animateOption.expectedFrameRateRange =
46             reinterpret_cast<ArkUIExpectedFrameRateRange*>(option->expectedFrameRateRange);
47     }
48 
49     if (complete && complete->callback) {
50         animateOption.onFinishCallback = reinterpret_cast<void*>(complete->callback);
51     }
52 
53     if (complete && complete->userData) {
54         animateOption.user = complete->userData;
55     }
56     auto finishCallbackType = static_cast<ArkUI_Int32>(ARKUI_FINISH_CALLBACK_REMOVED);
57     if (complete && complete->type == ARKUI_FINISH_CALLBACK_LOGICALLY) {
58         finishCallbackType = static_cast<ArkUI_Int32>(ARKUI_FINISH_CALLBACK_LOGICALLY);
59     }
60     animateOption.finishCallbackType = finishCallbackType;
61 
62     impl->getAnimation()->animateTo(reinterpret_cast<ArkUIContext*>(context), animateOption,
63         reinterpret_cast<void*>(update->callback), update->userData);
64     return ERROR_CODE_NO_ERROR;
65 }
66 
KeyframeAnimateTo(ArkUI_ContextHandle context,ArkUI_KeyframeAnimateOption * option)67 int32_t KeyframeAnimateTo(ArkUI_ContextHandle context, ArkUI_KeyframeAnimateOption* option)
68 {
69     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
70     if (!impl || !context || !option || option->keyframes.size() == 0) {
71         return ERROR_CODE_PARAM_INVALID;
72     }
73 
74     ArkUIKeyframeAnimateOption animateOption {};
75     animateOption.delay = option->delay;
76     animateOption.iterations = option->iterations;
77     animateOption.onFinish = option->onFinish;
78     animateOption.userData = option->userData;
79     ArkUIKeyframeState keyframes[option->keyframes.size()];
80     for (size_t i = 0; i < option->keyframes.size(); i++) {
81         keyframes[i].duration = option->keyframes[i].duration;
82         keyframes[i].event = option->keyframes[i].event;
83         keyframes[i].userData = option->keyframes[i].userData;
84 
85         auto curve = option->keyframes[i].curve;
86         if (!curve) {
87             continue;
88         }
89         //不支持当前curve
90         if (curve->type == ARKUI_CURVE_TYPE_SPRING_MOTION || curve->type == ARKUI_CURVE_TYPE_RESPONSIVE_SPRING_MOTION ||
91             curve->type == ARKUI_CURVE_TYPE_INTERPOLATING_SPRING) {
92             continue;
93         }
94         keyframes[i].curve = curve->curve;
95         keyframes[i].curveType = curve->type;
96     }
97     animateOption.keyframes = keyframes;
98     animateOption.keyframeSize = static_cast<int32_t>(option->keyframes.size());
99 
100     impl->getAnimation()->keyframeAnimateTo(reinterpret_cast<ArkUIContext*>(context), &animateOption);
101     return ERROR_CODE_NO_ERROR;
102 }
103 
ConvertAnimatorOption(ArkUI_AnimatorOption * option)104 ArkUIAnimatorOption* ConvertAnimatorOption(ArkUI_AnimatorOption* option)
105 {
106     ArkUIAnimatorOption* animatorOption = new ArkUIAnimatorOption;
107     animatorOption->duration = option->duration;
108     animatorOption->delay = option->delay;
109     animatorOption->iterations = option->iterations;
110     animatorOption->begin = option->begin;
111     animatorOption->end = option->end;
112     animatorOption->fill = option->fill;
113     animatorOption->direction = option->direction;
114     if (option->easing) {
115         animatorOption->easing = option->easing->curve;
116         animatorOption->curveType = option->easing->type;
117     } else {
118         animatorOption->easing = nullptr;
119     }
120 
121     if (option->expectedFrameRateRange) {
122         animatorOption->isHasExpectedFrameRateRange = 1;
123         animatorOption->expectedFrameRateRange = { option->expectedFrameRateRange->min,
124             option->expectedFrameRateRange->max, option->expectedFrameRateRange->expected };
125     } else {
126         animatorOption->isHasExpectedFrameRateRange = 0;
127     }
128 
129     int32_t keyframeSize = static_cast<int32_t>(option->keyframes.size());
130     if (keyframeSize > 0) {
131         animatorOption->keyframes = new ArkUIKeyframe[keyframeSize];
132         for (int32_t i = 0; i < keyframeSize; ++i) {
133             animatorOption->keyframes[i].keyTime = option->keyframes[i].keyTime;
134             animatorOption->keyframes[i].keyValue = option->keyframes[i].keyValue;
135             if (option->keyframes[i].curve) {
136                 animatorOption->keyframes[i].curve = option->keyframes[i].curve->curve;
137                 animatorOption->keyframes[i].curveType = option->keyframes[i].curve->type;
138             } else {
139                 animatorOption->keyframes[i].curve = nullptr;
140                 animatorOption->keyframes[i].curveType = 0; // 默认或无效的曲线类型
141             }
142         }
143     } else {
144         animatorOption->keyframes = nullptr;
145     }
146     animatorOption->keyframeSize = keyframeSize;
147 
148     animatorOption->onFrame = option->onFrame;
149     animatorOption->onFinish = option->onFinish;
150     animatorOption->onCancel = option->onCancel;
151     animatorOption->onRepeat = option->onRepeat;
152 
153     animatorOption->frameUserData = option->frameUserData;
154     animatorOption->finishUserData = option->finishUserData;
155     animatorOption->cancelUserData = option->cancelUserData;
156     animatorOption->repeatUserData = option->repeatUserData;
157     return animatorOption;
158 }
159 
CreateAnimator(ArkUI_ContextHandle context,ArkUI_AnimatorOption * option)160 ArkUI_AnimatorHandle CreateAnimator(ArkUI_ContextHandle context, ArkUI_AnimatorOption* option)
161 {
162     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
163     if (!impl || !context || !option) {
164         return nullptr;
165     }
166 
167     auto animatorOption = ConvertAnimatorOption(option);
168     auto animator = impl->getAnimation()->createAnimator(reinterpret_cast<ArkUIContext*>(context), animatorOption);
169     ArkUI_Animator* animatorHandle = new ArkUI_Animator { animator, option, animatorOption };
170     return animatorHandle;
171 }
172 
DisposeAnimator(ArkUI_AnimatorHandle animatorHandle)173 void DisposeAnimator(ArkUI_AnimatorHandle animatorHandle)
174 {
175     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
176     if (!animatorHandle || !animatorHandle->animator) {
177         return;
178     }
179     impl->getAnimation()->disposeAnimator(animatorHandle->animator);
180     if (animatorHandle->animatorOption) {
181         auto* animatorOption = reinterpret_cast<ArkUIAnimatorOption*>(animatorHandle->animatorOption);
182         if (animatorOption->keyframes) {
183             delete[] animatorOption->keyframes;
184             animatorOption->keyframes = nullptr;
185         }
186         delete animatorOption;
187         animatorHandle->animatorOption = nullptr;
188     }
189     delete animatorHandle;
190 }
191 
AnimatorReset(ArkUI_AnimatorHandle animatorHandle,ArkUI_AnimatorOption * option)192 int32_t AnimatorReset(ArkUI_AnimatorHandle animatorHandle, ArkUI_AnimatorOption* option)
193 {
194     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
195     if (!impl || !animatorHandle || !animatorHandle->animator || !option) {
196         return ERROR_CODE_PARAM_INVALID;
197     }
198 
199     auto animatorOption = ConvertAnimatorOption(option);
200     impl->getAnimation()->animatorReset(animatorHandle->animator, animatorOption);
201     if (animatorHandle->animatorOption) {
202         auto* animatorOption = reinterpret_cast<ArkUIAnimatorOption*>(animatorHandle->animatorOption);
203         if (animatorOption->keyframes) {
204             delete[] animatorOption->keyframes;
205             animatorOption->keyframes = nullptr;
206         }
207         delete animatorOption;
208         animatorHandle->animatorOption = nullptr;
209     }
210     animatorHandle->animatorOption = animatorOption;
211     return ERROR_CODE_NO_ERROR;
212 }
213 
AnimatorPlay(ArkUI_AnimatorHandle animatorHandle)214 int32_t AnimatorPlay(ArkUI_AnimatorHandle animatorHandle)
215 {
216     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
217     if (!impl || !animatorHandle || !animatorHandle->animator) {
218         return ERROR_CODE_PARAM_INVALID;
219     }
220     impl->getAnimation()->animatorPlay(animatorHandle->animator);
221     return ERROR_CODE_NO_ERROR;
222 }
223 
AnimatorFinish(ArkUI_AnimatorHandle animatorHandle)224 int32_t AnimatorFinish(ArkUI_AnimatorHandle animatorHandle)
225 {
226     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
227     if (!impl || !animatorHandle || !animatorHandle->animator) {
228         return ERROR_CODE_PARAM_INVALID;
229     }
230     impl->getAnimation()->animatorFinish(animatorHandle->animator);
231     return ERROR_CODE_NO_ERROR;
232 }
233 
AnimatorPause(ArkUI_AnimatorHandle animatorHandle)234 int32_t AnimatorPause(ArkUI_AnimatorHandle animatorHandle)
235 {
236     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
237     if (!impl || !animatorHandle || !animatorHandle->animator) {
238         return ERROR_CODE_PARAM_INVALID;
239     }
240     impl->getAnimation()->animatorPause(animatorHandle->animator);
241     return ERROR_CODE_NO_ERROR;
242 }
243 
AnimatorCancel(ArkUI_AnimatorHandle animatorHandle)244 int32_t AnimatorCancel(ArkUI_AnimatorHandle animatorHandle)
245 {
246     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
247     if (!impl || !animatorHandle || !animatorHandle->animator) {
248         return ERROR_CODE_PARAM_INVALID;
249     }
250     impl->getAnimation()->animatorCancel(animatorHandle->animator);
251     return ERROR_CODE_NO_ERROR;
252 }
253 
AnimatorReverse(ArkUI_AnimatorHandle animatorHandle)254 int32_t AnimatorReverse(ArkUI_AnimatorHandle animatorHandle)
255 {
256     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
257     if (!impl || !animatorHandle || !animatorHandle->animator) {
258         return ERROR_CODE_PARAM_INVALID;
259     }
260     impl->getAnimation()->animatorReverse(animatorHandle->animator);
261     return ERROR_CODE_NO_ERROR;
262 }
263 
InitCurve(ArkUI_AnimationCurve animationCurve)264 ArkUI_CurveHandle InitCurve(ArkUI_AnimationCurve animationCurve)
265 {
266     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
267     if (!impl) {
268         return nullptr;
269     }
270     auto curve = impl->getAnimation()->initCurve(animationCurve);
271     ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_BASE, curve, animationCurve });
272     return iCurve;
273 }
274 
StepsCurve(int32_t count,bool end)275 ArkUI_CurveHandle StepsCurve(int32_t count, bool end)
276 {
277     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
278     if (!impl || count < 1) {
279         return nullptr;
280     }
281     auto curve = impl->getAnimation()->stepsCurve(count, end);
282     ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_STEPS, curve });
283     return iCurve;
284 }
285 
CubicBezierCurve(float x1,float y1,float x2,float y2)286 ArkUI_CurveHandle CubicBezierCurve(float x1, float y1, float x2, float y2)
287 {
288     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
289     if (!impl) {
290         return nullptr;
291     }
292     x1 = std::clamp(x1, 0.0f, 1.0f);
293     x2 = std::clamp(x2, 0.0f, 1.0f);
294     auto curve = impl->getAnimation()->cubicBezierCurve(x1, y1, x2, y2);
295     ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_CUBIC_BEZIER, curve });
296     return iCurve;
297 }
298 
SpringCurve(float velocity,float mass,float stiffness,float damping)299 ArkUI_CurveHandle SpringCurve(float velocity, float mass, float stiffness, float damping)
300 {
301     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
302     if (!impl) {
303         return nullptr;
304     }
305     if (mass <= 0) {
306         mass = 1;
307     }
308     if (stiffness <= 0) {
309         stiffness = 1;
310     }
311     if (damping <= 0) {
312         damping = 1;
313     }
314     auto curve = impl->getAnimation()->springCurve(velocity, mass, stiffness, damping);
315     ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_SPRING, curve });
316     return iCurve;
317 }
318 
SpringMotion(float response,float dampingFraction,float overlapDuration)319 ArkUI_CurveHandle SpringMotion(float response, float dampingFraction, float overlapDuration)
320 {
321     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
322     if (!impl) {
323         return nullptr;
324     }
325     //default
326     if (response <= 0) {
327         response = 0.55f;
328     }
329     //default
330     if (dampingFraction <= 0) {
331         dampingFraction = 0.825f;
332     }
333     //default
334     if (overlapDuration < 0) {
335         overlapDuration = 0;
336     }
337     auto curve = impl->getAnimation()->springMotion(response, dampingFraction, overlapDuration);
338     ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_SPRING_MOTION, curve });
339     return iCurve;
340 }
341 
ResponsiveSpringMotion(float response,float dampingFraction,float overlapDuration)342 ArkUI_CurveHandle ResponsiveSpringMotion(float response, float dampingFraction, float overlapDuration)
343 {
344     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
345     if (!impl) {
346         return nullptr;
347     }
348     //default
349     if (response <= 0) {
350         response = 0.15f;
351     }
352     //default
353     if (dampingFraction < 0) {
354         dampingFraction = 0.86f;
355     }
356     //default
357     if (overlapDuration < 0) {
358         overlapDuration = 0.25f;
359     }
360     auto curve = impl->getAnimation()->responsiveSpringMotion(response, dampingFraction, overlapDuration);
361     ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_RESPONSIVE_SPRING_MOTION, curve });
362     return iCurve;
363 }
364 
InterpolatingSpring(float velocity,float mass,float stiffness,float damping)365 ArkUI_CurveHandle InterpolatingSpring(float velocity, float mass, float stiffness, float damping)
366 {
367     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
368     if (!impl) {
369         return nullptr;
370     }
371     if (mass <= 0) {
372         mass = 1;
373     }
374     if (stiffness <= 0) {
375         stiffness = 1;
376     }
377     if (damping <= 0) {
378         damping = 1;
379     }
380     auto curve = impl->getAnimation()->interpolatingSpring(velocity, mass, stiffness, damping);
381     ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_INTERPOLATING_SPRING, curve });
382     return iCurve;
383 }
384 
CustomCurve(void * userData,float (* interpolate)(float fraction,void * userdata))385 ArkUI_CurveHandle CustomCurve(void* userData, float (*interpolate)(float fraction, void* userdata))
386 {
387     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
388     if (!impl) {
389         return nullptr;
390     }
391     auto curve = impl->getAnimation()->customCurve(interpolate, userData);
392     ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_CUSTOM, curve });
393     return iCurve;
394 }
395 
DisposeCurve(ArkUI_CurveHandle curveHandle)396 void DisposeCurve(ArkUI_CurveHandle curveHandle)
397 {
398     const auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
399     if (!impl || !curveHandle) {
400         return;
401     }
402     impl->getAnimation()->disposeCurve(curveHandle->curve);
403     delete curveHandle;
404 }
405 } // namespace OHOS::Ace::AnimateModel