• 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 #include <ani.h>
17 #include <array>
18 #include <iostream>
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "base/memory/referenced.h"
24 #include "base/utils/string_utils.h"
25 #include "bridge/common/utils/utils.h"
26 #include "core/animation/animation.h"
27 #include "core/animation/animator.h"
28 #include "core/animation/curve.h"
29 #include "core/animation/spring_motion.h"
30 namespace OHOS::Ace::Ani {
31 constexpr size_t INTERPOLATING_SPRING_PARAMS_SIZE = 4;
32 constexpr char INTERPOLATING_SPRING[] = "interpolating-spring";
33 
34 struct AnimatorOption {
35     int32_t duration = 0;
36     int32_t delay = 0;
37     int32_t iterations = 0;
38     double begin = 0.0;
39     double end = 0.0;
40     std::string easing = "ease";
41     std::string fill = "none";
42     std::string direction = "normal";
43 
ToStringOHOS::Ace::Ani::AnimatorOption44     std::string ToString() const
45     {
46         return "AnimatorOption:[" + std::to_string(duration) + "," + std::to_string(delay) + "," +
47                std::to_string(iterations) + "," + std::to_string(begin) + "," + std::to_string(end) + "," + easing +
48                "," + fill + "," + direction + "]";
49     }
50 };
51 
StringToAnimationDirection(const std::string & direction)52 static AnimationDirection StringToAnimationDirection(const std::string &direction)
53 {
54     if (direction.compare("alternate") == 0) {
55         return AnimationDirection::ALTERNATE;
56     } else if (direction.compare("reverse") == 0) {
57         return AnimationDirection::REVERSE;
58     } else if (direction.compare("alternate-reverse") == 0) {
59         return AnimationDirection::ALTERNATE_REVERSE;
60     } else {
61         return AnimationDirection::NORMAL;
62     }
63 }
64 
StringToFillMode(const std::string & fillMode)65 static FillMode StringToFillMode(const std::string &fillMode)
66 {
67     if (fillMode.compare("forwards") == 0) {
68         return FillMode::FORWARDS;
69     } else if (fillMode.compare("backwards") == 0) {
70         return FillMode::BACKWARDS;
71     } else if (fillMode.compare("both") == 0) {
72         return FillMode::BOTH;
73     } else {
74         return FillMode::NONE;
75     }
76 }
77 
78 class AnimatorResult final {
79 public:
80     AnimatorResult() = default;
AnimatorResult(RefPtr<Animator> & animator,std::shared_ptr<AnimatorOption> & option)81     AnimatorResult(RefPtr<Animator> &animator, std::shared_ptr<AnimatorOption> &option)
82         : animator_(animator), option_(option)
83     {
84         ApplyOption();
85     }
86     ~AnimatorResult() = default;
87 
GetAnimator() const88     RefPtr<Animator> GetAnimator() const
89     {
90         return animator_;
91     }
92 
GetAnimatorOption() const93     std::shared_ptr<AnimatorOption> GetAnimatorOption() const
94     {
95         return option_;
96     }
97 
GetOnframeRef() const98     ani_ref GetOnframeRef() const
99     {
100         return onframe_;
101     }
102 
SetOnframeRef(const ani_ref & onframe)103     void SetOnframeRef(const ani_ref &onframe)
104     {
105         onframe_ = onframe;
106     }
107 
GetOnfinishRef() const108     ani_ref GetOnfinishRef() const
109     {
110         return onfinish_;
111     }
112 
SetOnfinishRef(const ani_ref & onfinish)113     void SetOnfinishRef(const ani_ref &onfinish)
114     {
115         onfinish_ = onfinish;
116     }
117 
GetOncancelRef() const118     ani_ref GetOncancelRef() const
119     {
120         return oncancel_;
121     }
122 
SetOncancelRef(const ani_ref & oncancel)123     void SetOncancelRef(const ani_ref &oncancel)
124     {
125         oncancel_ = oncancel;
126     }
127 
GetOnrepeatRef() const128     ani_ref GetOnrepeatRef() const
129     {
130         return onrepeat_;
131     }
132 
SetOnrepeatRef(const ani_ref & onrepeat)133     void SetOnrepeatRef(const ani_ref &onrepeat)
134     {
135         onrepeat_ = onrepeat;
136     }
137 
GetMotion() const138     const RefPtr<Motion> &GetMotion() const
139     {
140         return motion_;
141     }
142 
SetMotion(const RefPtr<Motion> & motion)143     void SetMotion(const RefPtr<Motion> &motion)
144     {
145         motion_ = motion;
146     }
147 
ApplyOption()148     void ApplyOption()
149     {
150         CHECK_NULL_VOID(animator_);
151         CHECK_NULL_VOID(option_);
152         if (motion_) {
153             // duration not works. Iteration can only be 1. Direction can only be normal.
154             animator_->SetIteration(1);
155             animator_->SetAnimationDirection(AnimationDirection::NORMAL);
156         } else {
157             animator_->SetDuration(option_->duration);
158             animator_->SetIteration(option_->iterations);
159             animator_->SetAnimationDirection(StringToAnimationDirection(option_->direction));
160         }
161         animator_->SetStartDelay(option_->delay);
162         // FillMode not works for motion in animator implementation.
163         animator_->SetFillMode(StringToFillMode(option_->fill));
164     }
165 
166 private:
167     RefPtr<Animator> animator_;
168     RefPtr<Motion> motion_;
169     std::shared_ptr<AnimatorOption> option_;
170     ani_ref onframe_ = nullptr;
171     ani_ref onfinish_ = nullptr;
172     ani_ref oncancel_ = nullptr;
173     ani_ref onrepeat_ = nullptr;
174 };
175 
ANIUtils_ANIStringToStdString(ani_env * env,ani_string ani_str)176 std::string ANIUtils_ANIStringToStdString(ani_env *env, ani_string ani_str)
177 {
178     ani_size strSize;
179     env->String_GetUTF8Size(ani_str, &strSize);
180 
181     std::vector<char> buffer(strSize + 1);
182     char *utf8_buffer = buffer.data();
183 
184     // String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416
185     ani_size bytes_written = 0;
186     env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written);
187     utf8_buffer[bytes_written] = '\0';
188     std::string content = std::string(utf8_buffer);
189     return content;
190 }
191 
GetAnimatorResult(ani_env * env,ani_object obj)192 static AnimatorResult *GetAnimatorResult(ani_env *env, ani_object obj)
193 {
194     ani_long animatorResultForAni;
195     if (ANI_OK != env->Object_GetFieldByName_Long(obj, "animatorResult", &animatorResultForAni)) {
196         return nullptr;
197     }
198     return reinterpret_cast<AnimatorResult *>(animatorResultForAni);
199 }
200 
201 // ani
JSReverse(ani_env * env,ani_object obj)202 static void JSReverse(ani_env *env, ani_object obj)
203 {
204     auto animatorResult = GetAnimatorResult(env, obj);
205     if (animatorResult == nullptr) {
206         return;
207     }
208     // GetMotion
209     if (animatorResult->GetMotion()) {
210         return;
211     }
212     auto animator = animatorResult->GetAnimator();
213     if (!animator) {
214         return;
215     }
216     if (!animator->HasScheduler()) {
217         // AttachSchedulerOnContainer
218         auto result = animator->AttachSchedulerOnContainer();
219         if (!result) {
220             return;
221         }
222     }
223     animator->Reverse();
224 }
225 
226 // ani
JSCancel(ani_env * env,ani_object obj)227 static void JSCancel(ani_env *env, ani_object obj)
228 {
229     auto animatorResult = GetAnimatorResult(env, obj);
230     if (animatorResult == nullptr) {
231         return;
232     }
233     auto animator = animatorResult->GetAnimator();
234     if (animator == nullptr) {
235         return;
236     }
237     animator->Cancel();
238 }
239 
240 // ani
JSPause(ani_env * env,ani_object obj)241 static void JSPause(ani_env *env, ani_object obj)
242 {
243     auto animatorResult = GetAnimatorResult(env, obj);
244     if (animatorResult == nullptr) {
245         return;
246     }
247     auto animator = animatorResult->GetAnimator();
248     if (animator == nullptr) {
249         return;
250     }
251     animator->Pause();
252 }
253 
254 // ani
JSFinish(ani_env * env,ani_object obj)255 static void JSFinish(ani_env *env, ani_object obj)
256 {
257     auto animatorResult = GetAnimatorResult(env, obj);
258     if (animatorResult == nullptr) {
259         return;
260     }
261     auto animator = animatorResult->GetAnimator();
262     if (animator == nullptr) {
263         return;
264     }
265     animator->Finish();
266 }
267 
268 // ani
JSPlay(ani_env * env,ani_object obj)269 static void JSPlay(ani_env *env, ani_object obj)
270 {
271     auto animatorResult = GetAnimatorResult(env, obj);
272     if (animatorResult == nullptr) {
273         return;
274     }
275     auto animator = animatorResult->GetAnimator();
276     if (!animator) {
277         return;
278     }
279     if (!animator->HasScheduler()) {
280         auto result = animator->AttachSchedulerOnContainer();
281         if (!result) {
282             return;
283         }
284     }
285     if (animatorResult->GetMotion()) {
286         animator->PlayMotion(animatorResult->GetMotion());
287     } else {
288         animator->Play();
289     }
290     animator->PrintVsyncInfoIfNeed();
291 }
292 
ParseAnimatorOption(ani_env * env,ani_object obj,std::shared_ptr<AnimatorOption> option)293 static void ParseAnimatorOption(ani_env *env, ani_object obj, std::shared_ptr<AnimatorOption> option)
294 {
295     ani_double durationAni;
296     ani_double iterationsAni;
297     ani_double delayAni;
298     ani_ref easingAni;
299     ani_ref fillAni;
300     ani_ref directionAni;
301     ani_double beginAni;
302     ani_double endAni;
303 
304     env->Object_GetPropertyByName_Double(obj, "duration", &durationAni);
305     env->Object_GetPropertyByName_Double(obj, "iterations", &iterationsAni);
306     env->Object_GetPropertyByName_Double(obj, "delay", &delayAni);
307     env->Object_GetPropertyByName_Double(obj, "begin", &beginAni);
308     env->Object_GetPropertyByName_Double(obj, "end", &endAni);
309     env->Object_GetPropertyByName_Ref(obj, "easing", &easingAni);
310     env->Object_GetPropertyByName_Ref(obj, "fill", &fillAni);
311     env->Object_GetPropertyByName_Ref(obj, "direction", &directionAni);
312     std::string easing = "ease";
313     std::string fill = "none";
314     std::string direction = "normal";
315     easing = ANIUtils_ANIStringToStdString(env, reinterpret_cast<ani_string>(easingAni));
316     fill = ANIUtils_ANIStringToStdString(env, reinterpret_cast<ani_string>(fillAni));
317     direction = ANIUtils_ANIStringToStdString(env, reinterpret_cast<ani_string>(directionAni));
318 
319     option->duration = durationAni > 0 ? durationAni : 0;
320     option->iterations = iterationsAni >= -1 ? iterationsAni : 1;
321     option->begin = beginAni;
322     option->delay = delayAni;
323     option->end = endAni;
324     option->easing = easing;
325     option->fill = fill;
326     option->direction = direction;
327 }
328 
SetOnfinish(ani_env * env,ani_object object,ani_object callbackObj)329 static void SetOnfinish([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_object callbackObj)
330 {
331     AnimatorResult *animatorResult = nullptr;
332     animatorResult = GetAnimatorResult(env, object);
333     if (!animatorResult) {
334         return;
335     }
336     auto option = animatorResult->GetAnimatorOption();
337     if (!option) {
338         return;
339     }
340     auto animator = animatorResult->GetAnimator();
341     if (!animator) {
342         return;
343     }
344     ani_ref onfinishRef = reinterpret_cast<ani_ref>(callbackObj);
345     ani_ref onfinishGlobalRef;
346     env->GlobalReference_Create(onfinishRef, &onfinishGlobalRef);
347     animatorResult->SetOnfinishRef(onfinishGlobalRef);
348     animator->ClearStopListeners();
349     animator->AddStopListener([env, onfinishGlobalRef, id = animator->GetId()] {
350         auto fnObj = reinterpret_cast<ani_fn_object>(onfinishGlobalRef);
351         ani_ref result;
352         env->FunctionalObject_Call(fnObj, 0, NULL, &result);
353     });
354     return;
355 }
356 
ParseOptionToMotion(const std::shared_ptr<AnimatorOption> & option)357 static RefPtr<Motion> ParseOptionToMotion(const std::shared_ptr<AnimatorOption> &option)
358 {
359     const auto &curveStr = option->easing;
360     if (curveStr.back() != ')') {
361         return nullptr;
362     }
363     std::string::size_type leftEmbracePosition = curveStr.find_last_of('(');
364     if (leftEmbracePosition == std::string::npos) {
365         return nullptr;
366     }
367     auto aniTimFuncName = curveStr.substr(0, leftEmbracePosition);
368     if (aniTimFuncName.compare(INTERPOLATING_SPRING)) {
369         return nullptr;
370     }
371     auto params = curveStr.substr(leftEmbracePosition + 1, curveStr.length() - leftEmbracePosition - 2);
372     std::vector<std::string> paramsVector;
373     StringUtils::StringSplitter(params, ',', paramsVector);
374     if (paramsVector.size() != INTERPOLATING_SPRING_PARAMS_SIZE) {
375         return nullptr;
376     }
377     for (auto &param : paramsVector) {
378         OHOS::Ace::Framework::RemoveHeadTailSpace(param);
379     }
380     float velocity = StringUtils::StringToFloat(paramsVector[0]);
381     float mass = StringUtils::StringToFloat(paramsVector[1]);
382     float stiffness = StringUtils::StringToFloat(paramsVector[2]);
383     float damping = StringUtils::StringToFloat(paramsVector[3]);
384 
385     // input velocity is normalized velocity, while the velocity of arkui's springMotion is absolute velocity.
386     velocity = velocity * (option->end - option->begin);
387     if (LessOrEqual(mass, 0)) {
388         mass = 1.0f;
389     }
390     if (LessOrEqual(stiffness, 0)) {
391         stiffness = 1.0f;
392     }
393     if (LessOrEqual(damping, 0)) {
394         damping = 1.0f;
395     }
396     return AceType::MakeRefPtr<SpringMotion>(
397         option->begin, option->end, velocity, AceType::MakeRefPtr<SpringProperty>(mass, stiffness, damping));
398 }
399 
createDouble(ani_env * env,double value)400 static ani_object createDouble(ani_env *env, double value)
401 {
402     static const char *className = "Lstd/core/Double;";
403     ani_class persion_cls;
404     if (ANI_OK != env->FindClass(className, &persion_cls)) {
405         return nullptr;
406     }
407     ani_method personInfoCtor;
408     if (ANI_OK != env->Class_FindMethod(persion_cls, "<ctor>", "D:V", &personInfoCtor)) {
409         return nullptr;
410     }
411     ani_object personInfoObj;
412     if (ANI_OK != env->Object_New(persion_cls, personInfoCtor, &personInfoObj, ani_double(value))) {
413         return nullptr;
414     }
415     return personInfoObj;
416 }
417 
SetOnframe(ani_env * env,ani_object object,ani_object callbackObj)418 static void SetOnframe([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_object callbackObj)
419 {
420     AnimatorResult *animatorResult = nullptr;
421     animatorResult = GetAnimatorResult(env, object);
422     if (!animatorResult) {
423         return;
424     }
425     auto option = animatorResult->GetAnimatorOption();
426     if (!option) {
427         return;
428     }
429     auto animator = animatorResult->GetAnimator();
430     if (!animator) {
431         return;
432     }
433     animator->ClearInterpolators();
434     ani_ref onframeRef = reinterpret_cast<ani_ref>(callbackObj);
435     ani_ref onframeGlobalRef;
436     env->GlobalReference_Create(onframeRef, &onframeGlobalRef);
437     animatorResult->SetOnframeRef(onframeGlobalRef);
438     auto onFrameCallback = [env,
439                                onframeGlobalRef,
440                                id = animator->GetId(),
441                                weakOption = std::weak_ptr<AnimatorOption>(animatorResult->GetAnimatorOption())](
442                                double value) {
443         auto fnObj = reinterpret_cast<ani_fn_object>(onframeGlobalRef);
444         auto option = weakOption.lock();
445         auto args = createDouble(env, value);
446         if (args == nullptr) {
447             return;
448         }
449         ani_ref result;
450         auto obj = reinterpret_cast<ani_ref>(args);
451         std::vector<ani_ref> tmp = {reinterpret_cast<ani_ref>(obj)};
452         env->FunctionalObject_Call(fnObj, tmp.size(), tmp.data(), &result);
453     };
454     RefPtr<Animation<double>> animation;
455     RefPtr<Motion> motion = ParseOptionToMotion(option);
456     if (motion) {
457         motion->AddListener(onFrameCallback);
458         animatorResult->SetMotion(motion);
459     } else {
460         auto curve = OHOS::Ace::Framework::CreateCurve(option->easing);
461         animation = AceType::MakeRefPtr<CurveAnimation<double>>(option->begin, option->end, curve);
462         animation->AddListener(onFrameCallback);
463         animator->AddInterpolator(animation);
464         animatorResult->SetMotion(nullptr);
465     }
466     if (!animator->HasScheduler()) {
467         animator->AttachSchedulerOnContainer();
468     }
469     return;
470 }
471 
SetOncancel(ani_env * env,ani_object object,ani_object callbackObj)472 static void SetOncancel([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_object callbackObj)
473 {
474     AnimatorResult *animatorResult = nullptr;
475     animatorResult = GetAnimatorResult(env, object);
476     if (!animatorResult) {
477         return;
478     }
479     auto option = animatorResult->GetAnimatorOption();
480     if (!option) {
481         return;
482     }
483     auto animator = animatorResult->GetAnimator();
484     if (!animator) {
485         return;
486     }
487     ani_ref oncancelRef = reinterpret_cast<ani_ref>(callbackObj);
488     ani_ref oncancelGlobalRef;
489     env->GlobalReference_Create(oncancelRef, &oncancelGlobalRef);
490     animatorResult->SetOncancelRef(oncancelGlobalRef);
491     animator->ClearIdleListeners();
492     animator->AddIdleListener([env, oncancelGlobalRef] {
493         auto fnObj = reinterpret_cast<ani_fn_object>(oncancelGlobalRef);
494         ani_ref result;
495         env->FunctionalObject_Call(fnObj, 0, NULL, &result);
496     });
497     return;
498 }
499 
SetOnrepeat(ani_env * env,ani_object object,ani_object callbackObj)500 static void SetOnrepeat([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_object callbackObj)
501 {
502     AnimatorResult *animatorResult = nullptr;
503     animatorResult = GetAnimatorResult(env, object);
504     if (!animatorResult) {
505         return;
506     }
507     auto option = animatorResult->GetAnimatorOption();
508     if (!option) {
509         return;
510     }
511     auto animator = animatorResult->GetAnimator();
512     if (!animator) {
513         return;
514     }
515 
516     ani_ref onrepeatRef = reinterpret_cast<ani_ref>(callbackObj);
517     ani_ref onrepeatGlobalRef;
518     env->GlobalReference_Create(onrepeatRef, &onrepeatGlobalRef);
519     animatorResult->SetOnrepeatRef(onrepeatGlobalRef);
520     animator->ClearRepeatListeners();
521     animator->AddRepeatListener([env, onrepeatGlobalRef] {
522         auto fnObj = reinterpret_cast<ani_fn_object>(onrepeatGlobalRef);
523         ani_ref result;
524         env->FunctionalObject_Call(fnObj, 0, NULL, &result);
525     });
526     return;
527 }
528 
ParseExpectedFrameRateRange(ani_env * env,ani_object objOption,FrameRateRange & frameRateRange)529 void ParseExpectedFrameRateRange(ani_env *env, ani_object objOption,
530     FrameRateRange& frameRateRange)
531 {
532     static const char *className = "L@ohos/arkui/component/Common/ExpectedFrameRateRange;";
533     ani_class cls;
534     if (ANI_OK != env->FindClass(className, &cls)) {
535         return;
536     }
537 
538     ani_boolean isInstance;
539     if (ANI_OK != env->Object_InstanceOf(objOption, cls, &isInstance)) {
540         return;
541     }
542 
543     int32_t minFPS = 0;
544     int32_t maxFPS = 0;
545     int32_t expectedFPS = 0;
546 
547     ani_double minAni;
548     ani_double maxAni;
549     ani_double expectedAni;
550     env->Object_GetPropertyByName_Double(objOption, "min", &minAni);
551     env->Object_GetPropertyByName_Double(objOption, "max", &maxAni);
552     env->Object_GetPropertyByName_Double(objOption, "expected", &expectedAni);
553 
554     minFPS = static_cast<int32_t>(minAni);
555     maxFPS = static_cast<int32_t>(maxAni);
556     expectedFPS = static_cast<int32_t>(expectedAni);
557     frameRateRange.Set(minFPS, maxFPS, expectedFPS);
558 }
559 
560 // ani
JSSetExpectedFrameRateRange(ani_env * env,ani_object obj,ani_object objOption)561 static void JSSetExpectedFrameRateRange(ani_env *env, ani_object obj, ani_object objOption)
562 {
563     auto animatorResult = GetAnimatorResult(env, obj);
564     if (animatorResult == nullptr) {
565         return;
566     }
567     auto animator = animatorResult->GetAnimator();
568     if (!animator) {
569         return;
570     }
571     if (!animator->HasScheduler()) {
572         auto result = animator->AttachSchedulerOnContainer();
573         if (!result) {
574             return;
575         }
576     }
577     FrameRateRange frameRateRange;
578     ParseExpectedFrameRateRange(env, objOption, frameRateRange);
579     animator->SetExpectedFrameRateRange(frameRateRange);
580 }
581 
ANICreate(ani_env * env,ani_object object,ani_object aniOption)582 ani_object ANICreate(ani_env *env, [[maybe_unused]] ani_object object, [[maybe_unused]] ani_object aniOption)
583 {
584     ani_object animator_obj = {};
585     static const char *className = "L@ohos/animator/AnimatorResultInner;";
586     ani_class cls;
587     if (ANI_OK != env->FindClass(className, &cls)) {
588         TAG_LOGI(AceLogTag::ACE_ANIMATION, "[ANI] find class fail");
589         return animator_obj;
590     }
591 
592     ani_method ctor;
593     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
594         TAG_LOGI(AceLogTag::ACE_ANIMATION, "[ANI] find method fail");
595         return animator_obj;
596     }
597 
598     // create animatot and construct animatorResult
599     auto option = std::make_shared<AnimatorOption>();
600     ParseAnimatorOption(env, aniOption, option);
601     TAG_LOGI(AceLogTag::ACE_ANIMATION, "[ANI] option is %{public}s", option->ToString().c_str());
602     auto animator = CREATE_ANIMATOR("ohos.animator");
603     animator->AttachSchedulerOnContainer();
604     auto animatorResult = new AnimatorResult(animator, option);
605 
606     // bind end with front object
607     if (ANI_OK != env->Object_New(cls, ctor, &animator_obj, reinterpret_cast<ani_long>(animatorResult))) {
608         TAG_LOGI(AceLogTag::ACE_ANIMATION, "[ANI] create animatorResult fail");
609         return animator_obj;
610     }
611 
612     return animator_obj;
613 }
614 
ANIReset(ani_env * env,ani_object object,ani_object options)615 static void ANIReset(ani_env *env, [[maybe_unused]] ani_object object, [[maybe_unused]] ani_object options)
616 {
617     AnimatorResult *animatorResult = nullptr;
618     animatorResult = GetAnimatorResult(env, object);
619     if (!animatorResult) {
620         return;
621     }
622     auto option = std::make_shared<AnimatorOption>();
623     ParseAnimatorOption(env, options, option);
624     auto animator = animatorResult->GetAnimator();
625     if (!animator) {
626         return;
627     }
628     animator->ClearInterpolators();
629     animator->ResetIsReverse();
630     animatorResult->ApplyOption();
631     ani_ref onframeRef = animatorResult->GetOnframeRef();
632     if (onframeRef) {
633         auto onFrameCallback = [env, onframeRef, id = animator->GetId()](double value) {
634             auto fnObj = reinterpret_cast<ani_fn_object>(onframeRef);
635             auto args = createDouble(env, value);
636             if (args == nullptr) {
637                 return;
638             }
639             ani_ref result;
640             auto obj = reinterpret_cast<ani_ref>(args);
641             std::vector<ani_ref> tmp = {reinterpret_cast<ani_ref>(obj)};
642             env->FunctionalObject_Call(fnObj, tmp.size(), tmp.data(), &result);
643         };
644         RefPtr<Animation<double>> animation;
645         RefPtr<Motion> motion = ParseOptionToMotion(option);
646         if (motion) {
647             motion->AddListener(onFrameCallback);
648             animatorResult->SetMotion(motion);
649         } else {
650             auto curve = Framework::CreateCurve(option->easing);
651             animation = AceType::MakeRefPtr<CurveAnimation<double>>(option->begin, option->end, curve);
652             animation->AddListener(onFrameCallback);
653             animator->AddInterpolator(animation);
654             animatorResult->SetMotion(nullptr);
655         }
656     }
657     return;
658 }
659 
ANIUpdate(ani_env * env,ani_object object,ani_object options)660 static void ANIUpdate(ani_env *env, [[maybe_unused]] ani_object object, [[maybe_unused]] ani_object options)
661 {
662     ANIReset(env, object, options);
663 }
664 
BindAnimator(ani_env * env)665 ani_status BindAnimator(ani_env *env)
666 {
667     static const char *className = "L@ohos/animator/Animator;";
668     ani_class cls;
669     if (ANI_OK != env->FindClass(className, &cls)) {
670         TAG_LOGI(AceLogTag::ACE_ANIMATION, "[ANI] Bind Animator fail");
671         return ANI_ERROR;
672     }
673 
674     std::array methods = {
675         ani_native_function{"create",
676             "L@ohos/animator/AnimatorOptions;:L@ohos/animator/AnimatorResult;",
677             reinterpret_cast<void *>(ANICreate)},
678     };
679 
680     if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) {
681         TAG_LOGI(AceLogTag::ACE_ANIMATION, "[ANI] Bind Animator method fail");
682         return ANI_ERROR;
683     };
684     return ANI_OK;
685 }
686 
BindAnimatorResult(ani_env * env)687 ani_status BindAnimatorResult(ani_env *env)
688 {
689     static const char *className = "L@ohos/animator/AnimatorResultInner;";
690     ani_class cls;
691     if (ANI_OK != env->FindClass(className, &cls)) {
692         TAG_LOGI(AceLogTag::ACE_ANIMATION, "[ANI] bind animator result fail");
693         return ANI_ERROR;
694     }
695 
696     std::array methods = {
697         ani_native_function{"play", ":V", reinterpret_cast<void *>(JSPlay)},
698         ani_native_function{"reverse", ":V", reinterpret_cast<void *>(JSReverse)},
699         ani_native_function{"cancel", ":V", reinterpret_cast<void *>(JSCancel)},
700         ani_native_function{"pause", ":V", reinterpret_cast<void *>(JSPause)},
701         ani_native_function{"finish", ":V", reinterpret_cast<void *>(JSFinish)},
702         ani_native_function{"setOnFinish", nullptr, reinterpret_cast<void *>(SetOnfinish)},
703         ani_native_function{"setOnCancel", nullptr, reinterpret_cast<void *>(SetOncancel)},
704         ani_native_function{"setOnRepeat", nullptr, reinterpret_cast<void *>(SetOnrepeat)},
705         ani_native_function{"setOnFrame", nullptr, reinterpret_cast<void *>(SetOnframe)},
706         ani_native_function{"update", "L@ohos/animator/AnimatorOptions;:V", reinterpret_cast<void *>(ANIUpdate)},
707         ani_native_function{"reset", "L@ohos/animator/AnimatorOptions;:V", reinterpret_cast<void *>(ANIReset)},
708         ani_native_function{"setExpectedFrameRateRange", nullptr,
709             reinterpret_cast<void *>(JSSetExpectedFrameRateRange)},
710     };
711 
712     if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) {
713         TAG_LOGI(AceLogTag::ACE_ANIMATION, "[ANI] bind native method fail");
714         return ANI_ERROR;
715     };
716     return ANI_OK;
717 }
718 }  // namespace OHOS::Ace::Ani
719 
ANI_Constructor(ani_vm * vm,uint32_t * result)720 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
721 {
722     ani_env *env;
723     if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
724         return ANI_ERROR;
725     }
726 
727     // bind Animator class.
728     ani_status retBindAnimator = OHOS::Ace::Ani::BindAnimator(env);
729     if (retBindAnimator != ANI_OK) {
730         TAG_LOGI(OHOS::Ace::AceLogTag::ACE_ANIMATION, "[ANI] BindAnimator fail");
731         return retBindAnimator;
732     }
733     ani_status retBindResult = OHOS::Ace::Ani::BindAnimatorResult(env);
734     if (retBindResult != ANI_OK) {
735         TAG_LOGI(OHOS::Ace::AceLogTag::ACE_ANIMATION, "[ANI] BindAnimatorResult fail");
736         return retBindResult;
737     }
738 
739     *result = ANI_VERSION_1;
740     return ANI_OK;
741 }
742