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 <malloc.h> 17 18 #include "bridge/common/utils/utils.h" 19 #include "cj_animator.h" 20 #include "cj_animator_ffi.h" 21 #include "core/animation/curve.h" 22 #include "core/animation/curve_animation.h" 23 #include "bridge/cj_frontend/frontend/cj_frontend_abstract.h" 24 25 using namespace OHOS::Ace; 26 using namespace OHOS::FFI; 27 28 constexpr int32_t ANIMATOR_OK = 0; 29 constexpr int32_t INIT_ERROR = 100001; 30 31 extern "C" { FfiAnimatorCreate(CAnimatorOptions option)32 int64_t FfiAnimatorCreate(CAnimatorOptions option) 33 { 34 auto opt = std::make_shared<AnimatorOption>(); 35 auto animator = CREATE_ANIMATOR("ohos.animator"); 36 animator->AttachSchedulerOnContainer(); 37 opt->duration = std::max(option.duration, 0); 38 opt->delay = std::max(option.delay, 0); 39 opt->iterations = option.iterations >= -1 ? option.iterations : 1; 40 opt->begin = option.begin; 41 opt->end = option.end; 42 opt->easing = std::string(option.easing); 43 opt->fill = std::string(option.fill); 44 opt->direction = std::string(option.direction); 45 auto nativeAnimatorResult = FFIData::Create<AnimatorResultImpl>(std::move(animator), std::move(opt)); 46 if (nativeAnimatorResult == nullptr) { 47 return INIT_ERROR; 48 } 49 int64_t id = nativeAnimatorResult->GetID(); 50 return id; 51 } 52 FfiAnimatorReset(int64_t id,CAnimatorOptions cOption)53 int32_t FfiAnimatorReset(int64_t id, CAnimatorOptions cOption) 54 { 55 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 56 if (!nativeAnimatorResult) { 57 return INIT_ERROR; 58 } 59 auto option = nativeAnimatorResult->GetAnimatorOption(); 60 if (!option) { 61 return INIT_ERROR; 62 } 63 option->duration = std::max(cOption.duration, 0); 64 option->delay = std::max(cOption.delay, 0); 65 option->iterations = cOption.iterations >= -1 ? cOption.iterations : 1; 66 option->begin = cOption.begin; 67 option->end = cOption.end; 68 option->easing = cOption.easing; 69 option->fill = cOption.fill; 70 option->direction = cOption.direction; 71 auto animator = nativeAnimatorResult->GetAnimator(); 72 if (!animator) { 73 return INIT_ERROR; 74 } 75 animator->ClearInterpolators(); 76 animator->ResetIsReverse(); 77 nativeAnimatorResult->ApplyOption(); 78 std::function<void(double)> onframeRef = nativeAnimatorResult->GetOnframeRef(); 79 if (onframeRef) { 80 auto onFrameCallback = [ 81 onframeRef, weakOption = std::weak_ptr<AnimatorOption>(nativeAnimatorResult->GetAnimatorOption())] 82 (double value) { 83 auto option = weakOption.lock(); 84 ACE_SCOPED_TRACE("ohos.animator onframe. duration:%d, curve:%s", 85 option->duration, option->easing.c_str()); 86 onframeRef(value); 87 }; 88 RefPtr<Animation<double>> animation; 89 RefPtr<Motion> motion = ParseOptionToMotion(option); 90 if (motion) { 91 motion->AddListener(onFrameCallback); 92 nativeAnimatorResult->SetMotion(motion); 93 } else { 94 auto curve = Framework::CreateCurve(option->easing); 95 animation = AceType::MakeRefPtr<CurveAnimation<double>>(option->begin, option->end, curve); 96 animation->AddListener(onFrameCallback); 97 animator->AddInterpolator(animation); 98 nativeAnimatorResult->SetMotion(nullptr); 99 } 100 } 101 return ANIMATOR_OK; 102 } 103 FfiAnimatorPlay(int64_t id)104 int32_t FfiAnimatorPlay(int64_t id) 105 { 106 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 107 if (!nativeAnimatorResult) { 108 return INIT_ERROR; 109 } 110 auto animator = nativeAnimatorResult->GetAnimator(); 111 if (!animator) { 112 TAG_LOGW(AceLogTag::ACE_ANIMATION, "Animator: no animator is created when call play"); 113 return INIT_ERROR; 114 } 115 if (!animator->HasScheduler()) { 116 auto result = animator->AttachSchedulerOnContainer(); 117 if (!result) { 118 TAG_LOGW(AceLogTag::ACE_ANIMATION, 119 "Animator: play failed, animator is not bound to specific context, id:%{public}d", 120 animator->GetId()); 121 return INIT_ERROR; 122 } 123 } 124 TAG_LOGI(AceLogTag::ACE_ANIMATION, "Animator: Play, id:%{public}d", animator->GetId()); 125 if (nativeAnimatorResult->GetMotion()) { 126 animator->PlayMotion(nativeAnimatorResult->GetMotion()); 127 } else { 128 animator->Play(); 129 } 130 animator->PrintVsyncInfoIfNeed(); 131 return ANIMATOR_OK; 132 } 133 FfiAnimatorFinish(int64_t id)134 int32_t FfiAnimatorFinish(int64_t id) 135 { 136 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 137 if (!nativeAnimatorResult) { 138 return INIT_ERROR; 139 } 140 auto animator = nativeAnimatorResult->GetAnimator(); 141 if (!animator) { 142 TAG_LOGW(AceLogTag::ACE_ANIMATION, "Animator: no animator is created when call play"); 143 return INIT_ERROR; 144 } 145 animator->Finish(); 146 return ANIMATOR_OK; 147 } 148 FfiAnimatorPause(int64_t id)149 int32_t FfiAnimatorPause(int64_t id) 150 { 151 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 152 if (!nativeAnimatorResult) { 153 return INIT_ERROR; 154 } 155 auto animator = nativeAnimatorResult->GetAnimator(); 156 if (!animator) { 157 TAG_LOGW(AceLogTag::ACE_ANIMATION, "Animator: no animator is created when call play"); 158 return INIT_ERROR; 159 } 160 animator->Pause(); 161 return ANIMATOR_OK; 162 } 163 FfiAnimatorCancel(int64_t id)164 int32_t FfiAnimatorCancel(int64_t id) 165 { 166 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 167 if (!nativeAnimatorResult) { 168 return INIT_ERROR; 169 } 170 auto animator = nativeAnimatorResult->GetAnimator(); 171 if (!animator) { 172 TAG_LOGW(AceLogTag::ACE_ANIMATION, "Animator: no animator is created when call play"); 173 return INIT_ERROR; 174 } 175 animator->Cancel(); 176 return ANIMATOR_OK; 177 } 178 FfiAnimatorReverse(int64_t id)179 int32_t FfiAnimatorReverse(int64_t id) 180 { 181 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 182 if (!nativeAnimatorResult) { 183 return INIT_ERROR; 184 } 185 if (nativeAnimatorResult->GetMotion()) { 186 TAG_LOGW(AceLogTag::ACE_ANIMATION, "JsAnimator: interpolatingSpringCurve, cannot reverse"); 187 return INIT_ERROR; 188 } 189 auto animator = nativeAnimatorResult->GetAnimator(); 190 if (!animator) { 191 TAG_LOGW(AceLogTag::ACE_ANIMATION, "JsAnimator: no animator is created when call reverse"); 192 return INIT_ERROR; 193 } 194 TAG_LOGI(AceLogTag::ACE_ANIMATION, "JsAnimator: JSReverse, id:%{public}d", animator->GetId()); 195 if (!animator->HasScheduler()) { 196 auto result = animator->AttachSchedulerOnContainer(); 197 if (!result) { 198 TAG_LOGW(AceLogTag::ACE_ANIMATION, 199 "JsAnimator: reverse failed, animator is not bound to specific context"); 200 return INIT_ERROR; 201 } 202 } 203 animator->Reverse(); 204 return ANIMATOR_OK; 205 } 206 FfiAnimatorOnframe(int64_t id,int64_t funcId)207 int32_t FfiAnimatorOnframe(int64_t id, int64_t funcId) 208 { 209 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 210 if (!nativeAnimatorResult) { 211 return INIT_ERROR; 212 } 213 nativeAnimatorResult->SetOnframe(funcId); 214 return ANIMATOR_OK; 215 } 216 FfiAnimatorOncancel(int64_t id,int64_t funcId)217 int32_t FfiAnimatorOncancel(int64_t id, int64_t funcId) 218 { 219 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 220 if (!nativeAnimatorResult) { 221 return INIT_ERROR; 222 } 223 nativeAnimatorResult->SetOncancel(funcId); 224 return ANIMATOR_OK; 225 } 226 FfiAnimatorOnfinish(int64_t id,int64_t funcId)227 int32_t FfiAnimatorOnfinish(int64_t id, int64_t funcId) 228 { 229 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 230 if (!nativeAnimatorResult) { 231 return INIT_ERROR; 232 } 233 nativeAnimatorResult->SetOnfinish(funcId); 234 return ANIMATOR_OK; 235 } 236 FfiAnimatorOnrepeat(int64_t id,int64_t funcId)237 int32_t FfiAnimatorOnrepeat(int64_t id, int64_t funcId) 238 { 239 auto nativeAnimatorResult = FFIData::GetData<AnimatorResultImpl>(id); 240 if (!nativeAnimatorResult) { 241 return INIT_ERROR; 242 } 243 nativeAnimatorResult->SetOnrepeat(funcId); 244 return ANIMATOR_OK; 245 } 246 } 247