1 /*
2 * Copyright (c) 2021-2022 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 "bridge/declarative_frontend/jsview/js_image_animator.h"
17
18 #include "base/log/ace_scoring_log.h"
19 #include "bridge/declarative_frontend/jsview/models/image_animator_model_impl.h"
20 #include "core/components_ng/pattern/image_animator/image_animator_model_ng.h"
21
22 namespace OHOS::Ace {
23 std::unique_ptr<ImageAnimatorModel> ImageAnimatorModel::instance_ = nullptr;
24 std::mutex ImageAnimatorModel::mutex_;
GetInstance()25 ImageAnimatorModel* ImageAnimatorModel::GetInstance()
26 {
27 if (!instance_) {
28 std::lock_guard<std::mutex> lock(mutex_);
29 if (!instance_) {
30 #ifdef NG_BUILD
31 instance_.reset(new NG::ImageAnimatorModelNG());
32 #else
33 if (Container::IsCurrentUseNewPipeline()) {
34 instance_.reset(new NG::ImageAnimatorModelNG());
35 } else {
36 instance_.reset(new Framework::ImageAnimatorModelImpl());
37 }
38 #endif
39 }
40 }
41 return instance_.get();
42 }
43
44 } // namespace OHOS::Ace
45
46 namespace OHOS::Ace::Framework {
47
48 constexpr uint32_t DEFAULT_DURATION = 1000; // ms
49 constexpr uint32_t DEFAULT_ITERATIONS = 1;
50 constexpr FillMode DEFAULT_FILL_MODE = FillMode::FORWARDS;
51
Create()52 void JSImageAnimator::Create()
53 {
54 ImageAnimatorModel::GetInstance()->Create();
55 }
56
JSBind(BindingTarget globalObj)57 void JSImageAnimator::JSBind(BindingTarget globalObj)
58 {
59 JSClass<JSImageAnimator>::Declare("ImageAnimator");
60 MethodOptions opt = MethodOptions::NONE;
61 JSClass<JSImageAnimator>::StaticMethod("create", &JSImageAnimator::Create, opt);
62 JSClass<JSImageAnimator>::StaticMethod("images", &JSImageAnimator::SetImages, opt);
63 JSClass<JSImageAnimator>::StaticMethod("state", &JSImageAnimator::SetState, opt);
64 JSClass<JSImageAnimator>::StaticMethod("duration", &JSImageAnimator::SetDuration, opt);
65 JSClass<JSImageAnimator>::StaticMethod("iterations", &JSImageAnimator::SetIteration, opt);
66 JSClass<JSImageAnimator>::StaticMethod("reverse", &JSImageAnimator::SetIsReverse, opt);
67 JSClass<JSImageAnimator>::StaticMethod("fixedSize", &JSImageAnimator::SetFixedSize, opt);
68 JSClass<JSImageAnimator>::StaticMethod("fillMode", &JSImageAnimator::SetFillMode, opt);
69 JSClass<JSImageAnimator>::StaticMethod("preDecode", &JSImageAnimator::SetPreDecode, opt);
70
71 JSClass<JSImageAnimator>::StaticMethod("onStart", &JSImageAnimator::OnStart, opt);
72 JSClass<JSImageAnimator>::StaticMethod("onPause", &JSImageAnimator::OnPause, opt);
73 JSClass<JSImageAnimator>::StaticMethod("onRepeat", &JSImageAnimator::OnRepeat, opt);
74 JSClass<JSImageAnimator>::StaticMethod("onCancel", &JSImageAnimator::OnCancel, opt);
75 JSClass<JSImageAnimator>::StaticMethod("onFinish", &JSImageAnimator::OnFinish, opt);
76 JSClass<JSImageAnimator>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
77 JSClass<JSImageAnimator>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
78 JSClass<JSImageAnimator>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
79
80 JSClass<JSImageAnimator>::InheritAndBind<JSContainerBase>(globalObj);
81 }
82
SetImages(const JSCallbackInfo & info)83 void JSImageAnimator::SetImages(const JSCallbackInfo& info)
84 {
85 if (info.Length() < 1) {
86 LOGE("JSImageAnimator: The arg is wrong, it is supposed to have one object argument.");
87 return;
88 }
89 if (info[0]->IsNull()) {
90 LOGE("JSImageAnimator: info is null.");
91 return;
92 }
93 if (!info[0]->IsArray()) {
94 LOGE("JSImageAnimator: info is not array.");
95 return;
96 }
97 JSRef<JSArray> imageArray = JSRef<JSArray>::Cast(info[0]);
98 std::vector<ImageProperties> images;
99 for (uint32_t i = 0; i < imageArray->Length(); ++i) {
100 ImageProperties imageProperties;
101 ParseImages(imageArray->GetValueAt(i), imageProperties);
102 images.push_back(imageProperties);
103 }
104
105 ImageAnimatorModel::GetInstance()->SetImages(images);
106 }
107
SetState(int32_t state)108 void JSImageAnimator::SetState(int32_t state)
109 {
110 if (state < static_cast<int32_t>(Animator::Status::IDLE) ||
111 state > static_cast<int32_t>(Animator::Status::STOPPED)) {
112 LOGW("ImageAnimator SetState %{public}d, invalid, use default AnimationStatus.Initial", state);
113 state = static_cast<int32_t>(Animator::Status::IDLE);
114 }
115
116 ImageAnimatorModel::GetInstance()->SetState(state);
117 }
118
SetDuration(int32_t duration)119 void JSImageAnimator::SetDuration(int32_t duration)
120 {
121 if (duration < 0) {
122 LOGW("ImageAnimator SetDuration %{public}d, invalid, use default %{public}d", duration, DEFAULT_DURATION);
123 duration = DEFAULT_DURATION;
124 }
125
126 ImageAnimatorModel::GetInstance()->SetDuration(duration);
127 }
128
SetIteration(int32_t iteration)129 void JSImageAnimator::SetIteration(int32_t iteration)
130 {
131 if (iteration < -1) {
132 LOGW("ImageAnimator SetIteration %{public}d, invalid, use default %{public}d", iteration, DEFAULT_ITERATIONS);
133 iteration = DEFAULT_ITERATIONS;
134 }
135
136 ImageAnimatorModel::GetInstance()->SetIteration(iteration);
137 }
138
SetFillMode(int32_t fillMode)139 void JSImageAnimator::SetFillMode(int32_t fillMode)
140 {
141 if (fillMode < static_cast<int32_t>(FillMode::NONE) || fillMode > static_cast<int32_t>(FillMode::BOTH)) {
142 LOGW("ImageAnimator SetFillMode %{public}d, invalid, use default %{public}d", fillMode,
143 static_cast<int32_t>(DEFAULT_FILL_MODE));
144 fillMode = static_cast<int32_t>(DEFAULT_FILL_MODE);
145 }
146
147 ImageAnimatorModel::GetInstance()->SetFillMode(fillMode);
148 }
149
SetPreDecode(int32_t preDecode)150 void JSImageAnimator::SetPreDecode(int32_t preDecode)
151 {
152 ImageAnimatorModel::GetInstance()->SetPreDecode(preDecode);
153 }
154
SetIsReverse(bool isReverse)155 void JSImageAnimator::SetIsReverse(bool isReverse)
156 {
157 ImageAnimatorModel::GetInstance()->SetIsReverse(isReverse);
158 }
159
SetFixedSize(bool fixedSize)160 void JSImageAnimator::SetFixedSize(bool fixedSize)
161 {
162 ImageAnimatorModel::GetInstance()->SetFixedSize(fixedSize);
163 }
164
OnStart(const JSCallbackInfo & info)165 void JSImageAnimator::OnStart(const JSCallbackInfo& info)
166 {
167 auto onStart = GetAnimatorEvent(info, "ImageAnimator.onStart");
168 ImageAnimatorModel::GetInstance()->SetOnStart(std::move(onStart));
169 }
170
OnPause(const JSCallbackInfo & info)171 void JSImageAnimator::OnPause(const JSCallbackInfo& info)
172 {
173 auto onPause = GetAnimatorEvent(info, "ImageAnimator.onPause");
174 ImageAnimatorModel::GetInstance()->SetOnPause(std::move(onPause));
175 }
176
OnRepeat(const JSCallbackInfo & info)177 void JSImageAnimator::OnRepeat(const JSCallbackInfo& info)
178 {
179 auto onRepeat = GetAnimatorEvent(info, "ImageAnimator.onRepeat");
180 ImageAnimatorModel::GetInstance()->SetOnRepeat(std::move(onRepeat));
181 }
182
OnCancel(const JSCallbackInfo & info)183 void JSImageAnimator::OnCancel(const JSCallbackInfo& info)
184 {
185 auto onCancel = GetAnimatorEvent(info, "ImageAnimator.onCancel");
186 ImageAnimatorModel::GetInstance()->SetOnCancel(std::move(onCancel));
187 }
188
OnFinish(const JSCallbackInfo & info)189 void JSImageAnimator::OnFinish(const JSCallbackInfo& info)
190 {
191 auto onFinish = GetAnimatorEvent(info, "ImageAnimator.onFinish");
192 ImageAnimatorModel::GetInstance()->SetOnFinish(std::move(onFinish));
193 }
194
GetAnimatorEvent(const JSCallbackInfo & info,std::string && eventName)195 AnimatorEvent JSImageAnimator::GetAnimatorEvent(const JSCallbackInfo& info, std::string&& eventName)
196 {
197 if (info.Length() != 1) {
198 LOGW("JSImageAnimator: The arg is wrong, it is supposed to have one function argument. event:%{public}s",
199 eventName.c_str());
200 return {};
201 }
202 if (!info[0]->IsFunction()) {
203 LOGE("JSImageAnimator: info[0] is not a function. event:%{public}s", eventName.c_str());
204 return {};
205 }
206 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
207 auto animatorEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
208 event = std::move(eventName)]() {
209 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
210 ACE_SCORING_EVENT(event);
211 func->Execute();
212 };
213 return animatorEvent;
214 }
215
ParseImages(const JSRef<JSVal> & image,ImageProperties & imageProperties)216 void JSImageAnimator::ParseImages(const JSRef<JSVal>& image, ImageProperties& imageProperties)
217 {
218 if (!image->IsObject()) {
219 LOGE("image is not Object.");
220 return;
221 }
222 JSRef<JSObject> jsObjImage = JSRef<JSObject>::Cast(image);
223 if (!ParseJsMedia(jsObjImage->GetProperty("src"), imageProperties.src)) {
224 LOGE("parse image property src failed!");
225 }
226 ParseJsDimensionVp(jsObjImage->GetProperty("width"), imageProperties.width);
227 ParseJsDimensionVp(jsObjImage->GetProperty("height"), imageProperties.height);
228 ParseJsDimensionVp(jsObjImage->GetProperty("top"), imageProperties.top);
229 ParseJsDimensionVp(jsObjImage->GetProperty("left"), imageProperties.left);
230 ParseJsInt32(jsObjImage->GetProperty("duration"), imageProperties.duration);
231 }
232
233 } // namespace OHOS::Ace::Framework
234