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