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 "core/interfaces/native/node/node_animate.h"
17
18 #include "base/error/error_code.h"
19 #include "base/memory/ace_type.h"
20 #include "base/utils/utils.h"
21 #include "core/animation/animation_pub.h"
22 #include "core/animation/curve_animation.h"
23 #include "core/animation/spring_curve.h"
24 #include "core/common/ace_engine.h"
25 #include "core/common/container.h"
26 #include "core/common/container_scope.h"
27 #include "core/components_ng/base/view_stack_model.h"
28 #include "core/components_ng/base/view_stack_processor.h"
29
30 namespace OHOS::Ace::NG::ViewAnimate {
31 namespace {
32 constexpr int32_t MAX_FLUSH_COUNT = 2;
33 int32_t g_animationCount = 0;
34
35 const std::vector<OHOS::Ace::RefPtr<OHOS::Ace::Curve>> CURVES_LIST = {
36 OHOS::Ace::Curves::LINEAR,
37 OHOS::Ace::Curves::EASE,
38 OHOS::Ace::Curves::EASE_IN,
39 OHOS::Ace::Curves::EASE_OUT,
40 OHOS::Ace::Curves::EASE_IN_OUT,
41 OHOS::Ace::Curves::FAST_OUT_SLOW_IN,
42 OHOS::Ace::Curves::LINEAR_OUT_SLOW_IN,
43 OHOS::Ace::Curves::FAST_OUT_LINEAR_IN,
44 OHOS::Ace::Curves::EXTREME_DECELERATION,
45 OHOS::Ace::Curves::SHARP,
46 OHOS::Ace::Curves::RHYTHM,
47 OHOS::Ace::Curves::SMOOTH,
48 OHOS::Ace::Curves::FRICTION,
49 };
50
51 const std::vector<AnimationDirection> DIRECTION_LIST = {
52 AnimationDirection::NORMAL,
53 AnimationDirection::REVERSE,
54 AnimationDirection::ALTERNATE,
55 AnimationDirection::ALTERNATE_REVERSE,
56 };
57
58 enum class ArkUICurveType {
59 CURVE_TYPE_CURVE = 0,
60 CURVE_TYPE_STEPS,
61 CURVE_TYPE_CUBIC_BEZIER,
62 CURVE_TYPE_SPRING,
63 CURVE_TYPE_SPRING_MOTION,
64 CURVE_TYPE_RESPONSIVE_SPRING_MOTION,
65 CURVE_TYPE_INTERPOLATING_SPRING,
66 CURVE_TYPE_CUSTOM,
67 };
68
PrintNodeAnimationInfo(const AnimationOption & option,AnimationInterface interface,const std::optional<int32_t> & cnt)69 void PrintNodeAnimationInfo(const AnimationOption& option,
70 AnimationInterface interface, const std::optional<int32_t>& cnt)
71 {
72 auto animationInterfaceName = GetAnimationInterfaceName(interface);
73 CHECK_NULL_VOID(animationInterfaceName);
74 if (option.GetIteration() == ANIMATION_REPEAT_INFINITE) {
75 if (interface == AnimationInterface::KEYFRAME_ANIMATE_TO) {
76 TAG_LOGI(AceLogTag::ACE_ANIMATION,
77 "nodeAnimate:keyframeAnimateTo iteration is infinite, remember to stop it. total duration:%{public}d",
78 option.GetDuration());
79 } else {
80 TAG_LOGI(AceLogTag::ACE_ANIMATION,
81 "nodeAnimate:%{public}s iteration is infinite, remember to stop it."
82 "duration:%{public}d, curve:%{public}s",
83 animationInterfaceName,
84 option.GetDuration(), option.GetCurve()->ToString().c_str());
85 }
86 return;
87 }
88 if (cnt) {
89 TAG_LOGI(AceLogTag::ACE_ANIMATION, "nodeAnimate:%{public}s starts, [%{public}s], finish cnt:%{public}d",
90 animationInterfaceName, option.ToString().c_str(), cnt.value());
91 }
92 }
93
FlushDirtyNodesWhenExist(const RefPtr<PipelineBase> & pipelineContext,const AnimationOption & option,AnimationInterface interface)94 void FlushDirtyNodesWhenExist(const RefPtr<PipelineBase>& pipelineContext,
95 const AnimationOption& option, AnimationInterface interface)
96 {
97 auto animationInterfaceName = GetAnimationInterfaceName(interface);
98 CHECK_NULL_VOID(animationInterfaceName);
99 int32_t flushCount = 0;
100 bool isDirtyNodesEmpty = pipelineContext->IsDirtyNodesEmpty();
101 bool isDirtyLayoutNodesEmpty = pipelineContext->IsDirtyLayoutNodesEmpty();
102 while (!isDirtyNodesEmpty || (!isDirtyLayoutNodesEmpty && !pipelineContext->IsLayouting())) {
103 if (flushCount >= MAX_FLUSH_COUNT || option.GetIteration() != ANIMATION_REPEAT_INFINITE) {
104 TAG_LOGW(AceLogTag::ACE_ANIMATION, "node_animate:%{public}s, dirtyNodes is empty:%{public}d,"
105 "dirtyLayoutNodes is empty:%{public}d, isLayouting:%{public}d",
106 animationInterfaceName, isDirtyNodesEmpty,
107 isDirtyLayoutNodesEmpty, pipelineContext->IsLayouting());
108 break;
109 }
110 if (!isDirtyNodesEmpty) {
111 pipelineContext->FlushBuild();
112 isDirtyLayoutNodesEmpty = pipelineContext->IsDirtyLayoutNodesEmpty();
113 }
114 if (!isDirtyLayoutNodesEmpty && !pipelineContext->IsLayouting()) {
115 pipelineContext->FlushUITasks(true);
116 }
117 isDirtyNodesEmpty = pipelineContext->IsDirtyNodesEmpty();
118 isDirtyLayoutNodesEmpty = pipelineContext->IsDirtyLayoutNodesEmpty();
119 flushCount++;
120 }
121 }
122 } // namespace
123
AnimateToInner(ArkUIContext * context,AnimationOption & option,const std::function<void ()> & animateToFunc,const std::function<void ()> & onFinishFunc,const std::optional<int32_t> & count,bool immediately)124 void AnimateToInner(ArkUIContext* context, AnimationOption& option, const std::function<void()>& animateToFunc,
125 const std::function<void()>& onFinishFunc, const std::optional<int32_t>& count, bool immediately)
126 {
127 CHECK_NULL_VOID(context);
128 ContainerScope scope(context->id);
129 auto containerSafely = Container::GetContainer(context->id);
130 CHECK_NULL_VOID(containerSafely);
131 auto pipelineContext = containerSafely->GetPipelineContext();
132 CHECK_NULL_VOID(pipelineContext);
133
134 ACE_SCOPED_TRACE("duration:%d, curve:%s, iteration:%d", option.GetDuration(), option.GetCurve()->ToString().c_str(),
135 option.GetIteration());
136 PrintNodeAnimationInfo(
137 option, immediately ? AnimationInterface::ANIMATE_TO_IMMEDIATELY : AnimationInterface::ANIMATE_TO, count);
138 if (!ViewStackModel::GetInstance()->IsEmptyStack()) {
139 TAG_LOGW(AceLogTag::ACE_ANIMATION,
140 "node_animate:when call animateTo, node stack is not empty, not suitable for animateTo."
141 "param is [option:%{public}s]", option.ToString().c_str());
142 }
143 NG::ScopedViewStackProcessor scopedProcessor;
144 auto triggerId = context->id;
145 AceEngine::Get().NotifyContainersOrderly([triggerId, option](const RefPtr<Container>& container) {
146 auto context = container->GetPipelineContext();
147 if (!context) {
148 // pa container do not have pipeline context.
149 return;
150 }
151 if (!container->GetSettings().usingSharedRuntime) {
152 return;
153 }
154 if (!container->IsFRSCardContainer() && !container->WindowIsShow()) {
155 return;
156 }
157 ContainerScope scope(container->GetInstanceId());
158 context->FlushBuild();
159 if (context->GetInstanceId() == triggerId) {
160 return;
161 }
162 context->PrepareOpenImplicitAnimation();
163 });
164 pipelineContext->PrepareOpenImplicitAnimation();
165 FlushDirtyNodesWhenExist(pipelineContext, option,
166 immediately ? AnimationInterface::ANIMATE_TO_IMMEDIATELY : AnimationInterface::ANIMATE_TO);
167 pipelineContext->StartImplicitAnimation(option, option.GetCurve(), onFinishFunc);
168 auto previousOption = pipelineContext->GetSyncAnimationOption();
169 pipelineContext->SetSyncAnimationOption(option);
170 // Execute the function.
171 animateToFunc();
172 pipelineContext->FlushOnceVsyncTask();
173 AceEngine::Get().NotifyContainersOrderly([triggerId](const RefPtr<Container>& container) {
174 auto context = container->GetPipelineContext();
175 if (!context) {
176 // pa container do not have pipeline context.
177 return;
178 }
179 if (!container->GetSettings().usingSharedRuntime) {
180 return;
181 }
182 if (!container->IsFRSCardContainer() && !container->WindowIsShow()) {
183 return;
184 }
185 ContainerScope scope(container->GetInstanceId());
186 context->FlushBuild();
187 if (context->GetInstanceId() == triggerId) {
188 return;
189 }
190 context->PrepareCloseImplicitAnimation();
191 });
192 pipelineContext->CloseImplicitAnimation();
193 pipelineContext->SetSyncAnimationOption(previousOption);
194 pipelineContext->FlushAfterLayoutCallbackInImplicitAnimationTask();
195 if (immediately) {
196 pipelineContext->FlushMessages();
197 } else {
198 pipelineContext->RequestFrame();
199 }
200 }
201
AnimateTo(ArkUIContext * context,ArkUIAnimateOption option,void (* event)(void * userData),void * user)202 void AnimateTo(ArkUIContext* context, ArkUIAnimateOption option, void (*event)(void* userData), void* user)
203 {
204 AnimationOption animationOption;
205 animationOption.SetDuration(NearZero(static_cast<double>(option.tempo)) ? 0 : option.duration);
206 animationOption.SetTempo(option.tempo);
207 if (option.iCurve) {
208 auto curve = reinterpret_cast<Curve*>(option.iCurve);
209 animationOption.SetCurve(AceType::Claim(curve));
210 } else {
211 animationOption.SetCurve(
212 CURVES_LIST[option.curve > static_cast<ArkUI_Int32>(CURVES_LIST.size()) ? 0 : option.curve]);
213 }
214 animationOption.SetDelay(option.delay);
215 animationOption.SetIteration(option.iterations);
216 animationOption.SetAnimationDirection(
217 DIRECTION_LIST[option.playMode > static_cast<ArkUI_Int32>(DIRECTION_LIST.size()) ? 0 : option.playMode]);
218 animationOption.SetFinishCallbackType(static_cast<FinishCallbackType>(option.finishCallbackType));
219
220 if (option.expectedFrameRateRange) {
221 RefPtr<FrameRateRange> frameRateRange = AceType::MakeRefPtr<FrameRateRange>(option.expectedFrameRateRange->min,
222 option.expectedFrameRateRange->max, option.expectedFrameRateRange->expected);
223 animationOption.SetFrameRateRange(frameRateRange);
224 }
225
226 auto onEvent = [event, user]() {
227 if (event) {
228 event(user);
229 }
230 };
231 std::optional<int32_t> count;
232 std::function<void()> onFinishEvent;
233 if (option.onFinishCallback) {
234 count = g_animationCount++;
235 onFinishEvent = [option, count]() {
236 ACE_SCOPED_TRACE("nodeAnimate:onFinish[cnt:%d]", count.value());
237 TAG_LOGI(AceLogTag::ACE_ANIMATION, "nodeAnimate:animateTo finish, cnt:%{public}d", count.value());
238 auto* onFinishFunc = reinterpret_cast<void (*)(void*)>(option.onFinishCallback);
239 onFinishFunc(option.user);
240 };
241 }
242
243 AnimateToInner(context, animationOption, onEvent, onFinishEvent, count, false);
244 }
245
StartKeyframeAnimation(const RefPtr<PipelineBase> & pipelineContext,AnimationOption & option,ArkUIKeyframeAnimateOption * animateOption)246 void StartKeyframeAnimation(const RefPtr<PipelineBase>& pipelineContext,
247 AnimationOption& option, ArkUIKeyframeAnimateOption* animateOption)
248 {
249 // flush build and flush ui tasks before open animation closure.
250 pipelineContext->FlushBuild();
251 if (!pipelineContext->IsLayouting()) {
252 pipelineContext->FlushUITasks(true);
253 }
254
255 // flush build when exist dirty nodes, flush ui tasks when exist dirty layout nodes.
256 FlushDirtyNodesWhenExist(pipelineContext, option, AnimationInterface::KEYFRAME_ANIMATE_TO);
257
258 // start KeyframeAnimation.
259 pipelineContext->StartImplicitAnimation(option, option.GetCurve(), option.GetOnFinishEvent());
260 for (int32_t i = 0; i < animateOption->keyframeSize; i++) {
261 auto keyframe = animateOption->keyframes[i];
262 if (!keyframe.event) {
263 continue;
264 }
265 auto event = [&keyframe, &pipelineContext]() {
266 keyframe.event(keyframe.userData);
267 pipelineContext->FlushBuild();
268 if (!pipelineContext->IsLayouting()) {
269 pipelineContext->FlushUITasks(true);
270 }
271 };
272 if (keyframe.curve) {
273 auto curve = reinterpret_cast<Curve*>(keyframe.curve);
274 AnimationUtils::AddDurationKeyFrame(keyframe.duration, AceType::Claim(curve), event);
275 } else {
276 AnimationUtils::AddDurationKeyFrame(keyframe.duration, Curves::EASE_IN_OUT, event);
277 }
278 }
279
280 // close KeyframeAnimation.
281 AnimationUtils::CloseImplicitAnimation();
282 }
283
KeyframeAnimateTo(ArkUIContext * context,ArkUIKeyframeAnimateOption * animateOption)284 void KeyframeAnimateTo(ArkUIContext* context, ArkUIKeyframeAnimateOption* animateOption)
285 {
286 CHECK_NULL_VOID(context);
287 ContainerScope scope(context->id);
288 auto containerSafely = Container::GetContainer(context->id);
289 CHECK_NULL_VOID(containerSafely);
290 auto pipelineContext = containerSafely->GetPipelineContext();
291 CHECK_NULL_VOID(pipelineContext);
292
293 AnimationOption option;
294 if (animateOption->onFinish) {
295 auto onFinishEvent = [onFinish = animateOption->onFinish, userData = animateOption->userData,
296 id = context->id]() {
297 ContainerScope scope(id);
298 onFinish(userData);
299 };
300 option.SetOnFinishEvent(onFinishEvent);
301 }
302
303 option.SetDelay(animateOption->delay);
304 option.SetIteration(animateOption->iterations);
305
306 int duration = 0;
307 for (int32_t i = 0; i < animateOption->keyframeSize; i++) {
308 duration += animateOption->keyframes[i].duration;
309 }
310 option.SetDuration(duration);
311 // actual curve is in keyframe, this curve will not be effective
312 option.SetCurve(Curves::EASE_IN_OUT);
313 AceScopedTrace trace("nodeAnimate:KeyframeAnimateTo iteration:%d, delay:%d",
314 option.GetIteration(), option.GetDelay());
315 PrintNodeAnimationInfo(option, AnimationInterface::KEYFRAME_ANIMATE_TO, std::nullopt);
316 if (!ViewStackModel::GetInstance()->IsEmptyStack()) {
317 TAG_LOGW(AceLogTag::ACE_ANIMATION,
318 "nodeAnimate:when call keyframeAnimateTo, node stack is not empty, not suitable for keyframeAnimateTo."
319 "param is [duration:%{public}d, delay:%{public}d, iteration:%{public}d]",
320 option.GetDuration(), option.GetDelay(), option.GetIteration());
321 }
322 NG::ScopedViewStackProcessor scopedProcessor;
323 StartKeyframeAnimation(pipelineContext, option, animateOption);
324 pipelineContext->FlushAfterLayoutCallbackInImplicitAnimationTask();
325 }
326
ParseAnimatorAnimation(const ArkUIAnimatorOption * option)327 RefPtr<Animation<double>> ParseAnimatorAnimation(const ArkUIAnimatorOption* option)
328 {
329 if (option->keyframeSize > 0) {
330 auto keyframeAnimation = AceType::MakeRefPtr<KeyframeAnimation<double>>();
331 for (int32_t i = 0; i < option->keyframeSize; i++) {
332 auto keyframe = option->keyframes[i];
333 auto animatorKeyframe = AceType::MakeRefPtr<Keyframe<double>>(keyframe.keyTime, keyframe.keyValue);
334 if (keyframe.curve) {
335 auto curve = reinterpret_cast<Curve*>(keyframe.curve);
336 animatorKeyframe->SetCurve(AceType::Claim(curve));
337 } else {
338 animatorKeyframe->SetCurve(Curves::EASE_IN_OUT);
339 }
340 keyframeAnimation->AddKeyframe(animatorKeyframe);
341 }
342 return keyframeAnimation;
343 } else {
344 RefPtr<Animation<double>> animation;
345 auto curve = reinterpret_cast<Curve*>(option->easing);
346 if (curve) {
347 animation = AceType::MakeRefPtr<CurveAnimation<double>>(option->begin, option->end, AceType::Claim(curve));
348 } else {
349 animation = AceType::MakeRefPtr<CurveAnimation<double>>(option->begin, option->end, Curves::EASE_IN_OUT);
350 }
351 return animation;
352 }
353 }
354
ParseAnimatorOption(const RefPtr<Animator> & animator,ArkUIAnimatorOption * option)355 void ParseAnimatorOption(const RefPtr<Animator>& animator, ArkUIAnimatorOption* option)
356 {
357 animator->SetDuration(option->duration);
358 animator->SetIteration(option->iterations);
359 animator->SetAnimationDirection(
360 DIRECTION_LIST[option->direction > static_cast<ArkUI_Int32>(DIRECTION_LIST.size()) ? 0 : option->direction]);
361 animator->SetStartDelay(option->delay);
362 animator->SetFillMode(static_cast<FillMode>(option->fill));
363
364 if (option->isHasExpectedFrameRateRange) {
365 FrameRateRange frameRateRange { option->expectedFrameRateRange.min, option->expectedFrameRateRange.max,
366 option->expectedFrameRateRange.expected };
367 animator->SetExpectedFrameRateRange(frameRateRange);
368 }
369 }
370
RegisterAnimatorOnFrameEvent(const RefPtr<Animator> & animator,ArkUIAnimatorOption * option)371 void RegisterAnimatorOnFrameEvent(const RefPtr<Animator>& animator, ArkUIAnimatorOption* option)
372 {
373 animator->ClearInterpolators();
374 //onframe
375 auto onFrameCallback = [callback = option->onFrame, userData = option->frameUserData](double value) {
376 if (callback) {
377 ArkUI_AnimatorOnFrameEvent event;
378 event.progress = static_cast<ArkUI_Float32>(value);
379 event.userData = userData;
380 callback(&event);
381 }
382 };
383 RefPtr<Animation<double>> animation = ParseAnimatorAnimation(option);
384 if (animation) {
385 animation->AddListener(onFrameCallback);
386 animator->AddInterpolator(animation);
387 }
388 }
389
RegisterAnimatorEvent(const RefPtr<Animator> & animator,ArkUIAnimatorOption * option)390 void RegisterAnimatorEvent(const RefPtr<Animator>& animator, ArkUIAnimatorOption* option)
391 {
392 animator->ClearStopListeners();
393 animator->ClearIdleListeners();
394 animator->ClearRepeatListeners();
395
396 RegisterAnimatorOnFrameEvent(animator, option);
397
398 //onfinish
399 animator->AddStopListener([callback = option->onFinish, userData = option->finishUserData] {
400 if (callback) {
401 ArkUI_AnimatorEvent event;
402 event.userData = userData;
403 callback(&event);
404 }
405 });
406
407 //oncancel
408 animator->AddIdleListener([callback = option->onCancel, userData = option->cancelUserData] {
409 if (callback) {
410 ArkUI_AnimatorEvent event;
411 event.userData = userData;
412 callback(&event);
413 }
414 });
415
416 //onRepeat
417 animator->AddRepeatListener([callback = option->onRepeat, userData = option->repeatUserData] {
418 if (callback) {
419 ArkUI_AnimatorEvent event;
420 event.userData = userData;
421 callback(&event);
422 }
423 });
424 }
425
CreateAnimator(ArkUIContext * context,ArkUIAnimatorOption * option)426 ArkUIAnimatorHandle CreateAnimator(ArkUIContext* context, ArkUIAnimatorOption* option)
427 {
428 CHECK_NULL_RETURN(context, nullptr);
429 ContainerScope scope(context->id);
430 auto containerSafely = Container::GetContainer(context->id);
431 CHECK_NULL_RETURN(containerSafely, nullptr);
432 auto pipelineContext = containerSafely->GetPipelineContext();
433 CHECK_NULL_RETURN(pipelineContext, nullptr);
434
435 ArkUIAnimator* result = new ArkUIAnimator;
436 auto animator = CREATE_ANIMATOR("ohos.animator");
437 animator->AttachScheduler(pipelineContext);
438 ParseAnimatorOption(animator, option);
439 RegisterAnimatorEvent(animator, option);
440 animator->IncRefCount();
441 result->animator = AceType::RawPtr(animator);
442 result->context = context;
443 result->animatorOption = option;
444 return result;
445 }
446
DisposeAnimator(ArkUIAnimatorHandle animatorHandle)447 void DisposeAnimator(ArkUIAnimatorHandle animatorHandle)
448 {
449 if (animatorHandle->animator) {
450 auto* animator = reinterpret_cast<Animator*>(animatorHandle->animator);
451 if (animator) {
452 animator->DecRefCount();
453 }
454 }
455 delete animatorHandle;
456 }
457
AnimatorReset(ArkUIAnimatorHandle animatorHandle,ArkUIAnimatorOption * option)458 int32_t AnimatorReset(ArkUIAnimatorHandle animatorHandle, ArkUIAnimatorOption* option)
459 {
460 CHECK_NULL_RETURN(animatorHandle, ERROR_CODE_PARAM_INVALID);
461 CHECK_NULL_RETURN(animatorHandle->animator, ERROR_CODE_PARAM_INVALID);
462 auto animator = reinterpret_cast<Animator*>(animatorHandle->animator);
463 animator->Cancel();
464 ParseAnimatorOption(AceType::Claim(animator), option);
465 RegisterAnimatorEvent(AceType::Claim(animator), option);
466 animatorHandle->animatorOption = option;
467 animator->ResetIsReverse();
468 return ERROR_CODE_NO_ERROR;
469 }
470
AnimatorPlay(ArkUIAnimatorHandle animatorHandle)471 int32_t AnimatorPlay(ArkUIAnimatorHandle animatorHandle)
472 {
473 CHECK_NULL_RETURN(animatorHandle, ERROR_CODE_PARAM_INVALID);
474 CHECK_NULL_RETURN(animatorHandle->animator, ERROR_CODE_PARAM_INVALID);
475 auto animator = reinterpret_cast<Animator*>(animatorHandle->animator);
476 animator->Play();
477 return ERROR_CODE_NO_ERROR;
478 }
479
AnimatorFinish(ArkUIAnimatorHandle animatorHandle)480 int32_t AnimatorFinish(ArkUIAnimatorHandle animatorHandle)
481 {
482 CHECK_NULL_RETURN(animatorHandle, ERROR_CODE_PARAM_INVALID);
483 CHECK_NULL_RETURN(animatorHandle->animator, ERROR_CODE_PARAM_INVALID);
484 auto animator = reinterpret_cast<Animator*>(animatorHandle->animator);
485 animator->Finish();
486 return ERROR_CODE_NO_ERROR;
487 }
488
AnimatorPause(ArkUIAnimatorHandle animatorHandle)489 int32_t AnimatorPause(ArkUIAnimatorHandle animatorHandle)
490 {
491 CHECK_NULL_RETURN(animatorHandle, ERROR_CODE_PARAM_INVALID);
492 CHECK_NULL_RETURN(animatorHandle->animator, ERROR_CODE_PARAM_INVALID);
493 auto animator = reinterpret_cast<Animator*>(animatorHandle->animator);
494 animator->Pause();
495 return ERROR_CODE_NO_ERROR;
496 }
497
AnimatorCancel(ArkUIAnimatorHandle animatorHandle)498 int32_t AnimatorCancel(ArkUIAnimatorHandle animatorHandle)
499 {
500 CHECK_NULL_RETURN(animatorHandle, ERROR_CODE_PARAM_INVALID);
501 CHECK_NULL_RETURN(animatorHandle->animator, ERROR_CODE_PARAM_INVALID);
502 auto animator = reinterpret_cast<Animator*>(animatorHandle->animator);
503 animator->Cancel();
504 return ERROR_CODE_NO_ERROR;
505 }
506
AnimatorReverse(ArkUIAnimatorHandle animatorHandle)507 int32_t AnimatorReverse(ArkUIAnimatorHandle animatorHandle)
508 {
509 CHECK_NULL_RETURN(animatorHandle, ERROR_CODE_PARAM_INVALID);
510 CHECK_NULL_RETURN(animatorHandle->animator, ERROR_CODE_PARAM_INVALID);
511 auto animator = reinterpret_cast<Animator*>(animatorHandle->animator);
512 animator->Reverse();
513 return ERROR_CODE_NO_ERROR;
514 }
515
CreateCurve(ArkUI_Int32 curve)516 ArkUICurveHandle CreateCurve(ArkUI_Int32 curve)
517 {
518 auto iCurve = AceType::RawPtr(CURVES_LIST[curve > static_cast<ArkUI_Int32>(CURVES_LIST.size()) ? 0 : curve]);
519 iCurve->IncRefCount();
520 return reinterpret_cast<ArkUICurveHandle>(iCurve);
521 }
522
CreateStepsCurve(ArkUI_Int32 count,ArkUI_Bool end)523 ArkUICurveHandle CreateStepsCurve(ArkUI_Int32 count, ArkUI_Bool end)
524 {
525 auto curve = AceType::MakeRefPtr<StepsCurve>(count, static_cast<StepsCurvePosition>(end));
526 curve->IncRefCount();
527 return reinterpret_cast<ArkUICurveHandle>(AceType::RawPtr(curve));
528 }
529
CreateCubicBezierCurve(ArkUI_Float32 x1,ArkUI_Float32 y1,ArkUI_Float32 x2,ArkUI_Float32 y2)530 ArkUICurveHandle CreateCubicBezierCurve(ArkUI_Float32 x1, ArkUI_Float32 y1, ArkUI_Float32 x2, ArkUI_Float32 y2)
531 {
532 auto curve = AceType::MakeRefPtr<CubicCurve>(x1, y1, x2, y2);
533 curve->IncRefCount();
534 return reinterpret_cast<ArkUICurveHandle>(AceType::RawPtr(curve));
535 }
536
CreateSpringCurve(ArkUI_Float32 velocity,ArkUI_Float32 mass,ArkUI_Float32 stiffness,ArkUI_Float32 damping)537 ArkUICurveHandle CreateSpringCurve(
538 ArkUI_Float32 velocity, ArkUI_Float32 mass, ArkUI_Float32 stiffness, ArkUI_Float32 damping)
539 {
540 auto curve = AceType::MakeRefPtr<SpringCurve>(velocity, mass, stiffness, damping);
541 curve->IncRefCount();
542 return reinterpret_cast<ArkUICurveHandle>(AceType::RawPtr(curve));
543 }
544
CreateSpringMotion(ArkUI_Float32 response,ArkUI_Float32 dampingFraction,ArkUI_Float32 overlapDuration)545 ArkUICurveHandle CreateSpringMotion(
546 ArkUI_Float32 response, ArkUI_Float32 dampingFraction, ArkUI_Float32 overlapDuration)
547 {
548 auto curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingFraction, overlapDuration);
549 curve->IncRefCount();
550 return reinterpret_cast<ArkUICurveHandle>(AceType::RawPtr(curve));
551 }
552
CreateResponsiveSpringMotion(ArkUI_Float32 response,ArkUI_Float32 dampingFraction,ArkUI_Float32 overlapDuration)553 ArkUICurveHandle CreateResponsiveSpringMotion(
554 ArkUI_Float32 response, ArkUI_Float32 dampingFraction, ArkUI_Float32 overlapDuration)
555 {
556 auto curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingFraction, overlapDuration);
557 curve->IncRefCount();
558 return reinterpret_cast<ArkUICurveHandle>(AceType::RawPtr(curve));
559 }
560
CreateInterpolatingSpring(ArkUI_Float32 velocity,ArkUI_Float32 mass,ArkUI_Float32 stiffness,ArkUI_Float32 damping)561 ArkUICurveHandle CreateInterpolatingSpring(
562 ArkUI_Float32 velocity, ArkUI_Float32 mass, ArkUI_Float32 stiffness, ArkUI_Float32 damping)
563 {
564 auto curve = AceType::MakeRefPtr<InterpolatingSpring>(velocity, mass, stiffness, damping);
565 curve->IncRefCount();
566 return reinterpret_cast<ArkUICurveHandle>(AceType::RawPtr(curve));
567 }
568
CreateCustomCurve(ArkUI_Float32 (* interpolate)(ArkUI_Float32 fraction,void * userData),void * userData)569 ArkUICurveHandle CreateCustomCurve(ArkUI_Float32 (*interpolate)(ArkUI_Float32 fraction, void* userData), void* userData)
570 {
571 auto func = [interpolate, userData](float value) -> float {
572 if (interpolate) {
573 return interpolate(value, userData);
574 }
575 return 0.0f;
576 };
577 auto curve = AceType::MakeRefPtr<CustomCurve>(func);
578 curve->IncRefCount();
579 return reinterpret_cast<ArkUICurveHandle>(AceType::RawPtr(curve));
580 }
581
DisposeCurve(ArkUICurveHandle curve)582 void DisposeCurve(ArkUICurveHandle curve)
583 {
584 CHECK_NULL_VOID(curve);
585 auto* curvePtr = reinterpret_cast<Curve*>(curve);
586 if (curvePtr) {
587 curvePtr->DecRefCount();
588 }
589 }
590 } // namespace OHOS::Ace::NG::ViewAnimate