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 #include "frameworks/bridge/declarative_frontend/jsview/js_utils.h"
22
23 namespace OHOS::Ace {
24 std::unique_ptr<ImageAnimatorModel> ImageAnimatorModel::instance_ = nullptr;
25 std::mutex ImageAnimatorModel::mutex_;
GetInstance()26 ImageAnimatorModel* ImageAnimatorModel::GetInstance()
27 {
28 if (!instance_) {
29 std::lock_guard<std::mutex> lock(mutex_);
30 if (!instance_) {
31 #ifdef NG_BUILD
32 instance_.reset(new NG::ImageAnimatorModelNG());
33 #else
34 if (Container::IsCurrentUseNewPipeline()) {
35 instance_.reset(new NG::ImageAnimatorModelNG());
36 } else {
37 instance_.reset(new Framework::ImageAnimatorModelImpl());
38 }
39 #endif
40 }
41 }
42 return instance_.get();
43 }
44
45 } // namespace OHOS::Ace
46
47 namespace OHOS::Ace::Framework {
48
49 constexpr uint32_t DEFAULT_DURATION = 1000; // ms
50 constexpr uint32_t DEFAULT_ITERATIONS = 1;
51 constexpr FillMode DEFAULT_FILL_MODE = FillMode::FORWARDS;
52
Create()53 void JSImageAnimator::Create()
54 {
55 ImageAnimatorModel::GetInstance()->Create();
56 }
57
JSBind(BindingTarget globalObj)58 void JSImageAnimator::JSBind(BindingTarget globalObj)
59 {
60 JSClass<JSImageAnimator>::Declare("ImageAnimator");
61 MethodOptions opt = MethodOptions::NONE;
62 JSClass<JSImageAnimator>::StaticMethod("create", &JSImageAnimator::Create, opt);
63 JSClass<JSImageAnimator>::StaticMethod("images", &JSImageAnimator::SetImages, opt);
64 JSClass<JSImageAnimator>::StaticMethod("state", &JSImageAnimator::SetState, opt);
65 JSClass<JSImageAnimator>::StaticMethod("duration", &JSImageAnimator::SetDuration, opt);
66 JSClass<JSImageAnimator>::StaticMethod("iterations", &JSImageAnimator::SetIteration, opt);
67 JSClass<JSImageAnimator>::StaticMethod("reverse", &JSImageAnimator::SetIsReverse, opt);
68 JSClass<JSImageAnimator>::StaticMethod("fixedSize", &JSImageAnimator::SetFixedSize, opt);
69 JSClass<JSImageAnimator>::StaticMethod("fillMode", &JSImageAnimator::SetFillMode, opt);
70 JSClass<JSImageAnimator>::StaticMethod("preDecode", &JSImageAnimator::SetPreDecode, opt);
71
72 JSClass<JSImageAnimator>::StaticMethod("onStart", &JSImageAnimator::OnStart, opt);
73 JSClass<JSImageAnimator>::StaticMethod("onPause", &JSImageAnimator::OnPause, opt);
74 JSClass<JSImageAnimator>::StaticMethod("onRepeat", &JSImageAnimator::OnRepeat, opt);
75 JSClass<JSImageAnimator>::StaticMethod("onCancel", &JSImageAnimator::OnCancel, opt);
76 JSClass<JSImageAnimator>::StaticMethod("onFinish", &JSImageAnimator::OnFinish, opt);
77 JSClass<JSImageAnimator>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
78 JSClass<JSImageAnimator>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
79 JSClass<JSImageAnimator>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
80 JSClass<JSImageAnimator>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
81 JSClass<JSImageAnimator>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
82
83 JSClass<JSImageAnimator>::InheritAndBind<JSContainerBase>(globalObj);
84 }
85
SetImages(const JSCallbackInfo & info)86 void JSImageAnimator::SetImages(const JSCallbackInfo& info)
87 {
88 if (info.Length() < 1) {
89 return;
90 }
91 if (info[0]->IsNull()) {
92 return;
93 }
94 if (!info[0]->IsArray()) {
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(const JSCallbackInfo & info)108 void JSImageAnimator::SetState(const JSCallbackInfo& info)
109 {
110 if (info.Length() < 1) {
111 return;
112 }
113 int32_t state = static_cast<int32_t>(Animator::Status::IDLE);
114 if (info[0]->IsNumber()) {
115 state = info[0]->ToNumber<int32_t>();
116 if (state < static_cast<int32_t>(Animator::Status::IDLE) ||
117 state > static_cast<int32_t>(Animator::Status::STOPPED)) {
118 state = static_cast<int32_t>(Animator::Status::IDLE);
119 }
120 }
121
122 ImageAnimatorModel::GetInstance()->SetState(state);
123 }
124
SetDuration(const JSCallbackInfo & info)125 void JSImageAnimator::SetDuration(const JSCallbackInfo& info)
126 {
127 if (info.Length() < 1) {
128 return;
129 }
130 int32_t duration = DEFAULT_DURATION;
131 if (info[0]->IsNumber()) {
132 duration = info[0]->ToNumber<int32_t>();
133 if (duration < 0) {
134 duration = DEFAULT_DURATION;
135 }
136 }
137
138 ImageAnimatorModel::GetInstance()->SetDuration(duration);
139 }
140
SetIteration(const JSCallbackInfo & info)141 void JSImageAnimator::SetIteration(const JSCallbackInfo& info)
142 {
143 if (info.Length() < 1) {
144 return;
145 }
146 int32_t iteration = DEFAULT_ITERATIONS;
147 if (info[0]->IsNumber()) {
148 iteration = info[0]->ToNumber<int32_t>();
149 if (iteration < -1) {
150 iteration = DEFAULT_ITERATIONS;
151 }
152 }
153
154 ImageAnimatorModel::GetInstance()->SetIteration(iteration);
155 }
156
SetFillMode(const JSCallbackInfo & info)157 void JSImageAnimator::SetFillMode(const JSCallbackInfo& info)
158 {
159 if (info.Length() < 1) {
160 return;
161 }
162 int32_t fillMode = static_cast<int32_t>(DEFAULT_FILL_MODE);
163 if (info[0]->IsNumber()) {
164 fillMode = info[0]->ToNumber<int32_t>();
165 if (fillMode < static_cast<int32_t>(FillMode::NONE) || fillMode > static_cast<int32_t>(FillMode::BOTH)) {
166 fillMode = static_cast<int32_t>(DEFAULT_FILL_MODE);
167 }
168 }
169
170 ImageAnimatorModel::GetInstance()->SetFillMode(fillMode);
171 }
172
SetPreDecode(const JSCallbackInfo & info)173 void JSImageAnimator::SetPreDecode(const JSCallbackInfo& info)
174 {
175 if (info.Length() < 1) {
176 return;
177 }
178 int32_t preDecode = 0;
179 if (info[0]->IsNumber()) {
180 preDecode = info[0]->ToNumber<int32_t>();
181 }
182 ImageAnimatorModel::GetInstance()->SetPreDecode(preDecode);
183 }
184
SetIsReverse(const JSCallbackInfo & info)185 void JSImageAnimator::SetIsReverse(const JSCallbackInfo& info)
186 {
187 if (info.Length() < 1) {
188 return;
189 }
190 bool isReverse = false;
191 if (info[0]->IsBoolean()) {
192 isReverse = info[0]->ToBoolean();
193 }
194 ImageAnimatorModel::GetInstance()->SetIsReverse(isReverse);
195 }
196
SetFixedSize(const JSCallbackInfo & info)197 void JSImageAnimator::SetFixedSize(const JSCallbackInfo& info)
198 {
199 if (info.Length() < 1) {
200 return;
201 }
202 bool fixedSize = true;
203 if (info[0]->IsBoolean()) {
204 fixedSize = info[0]->ToBoolean();
205 }
206 ImageAnimatorModel::GetInstance()->SetFixedSize(fixedSize);
207 }
208
OnStart(const JSCallbackInfo & info)209 void JSImageAnimator::OnStart(const JSCallbackInfo& info)
210 {
211 auto onStart = GetAnimatorEvent(info, "ImageAnimator.onStart");
212 ImageAnimatorModel::GetInstance()->SetOnStart(std::move(onStart));
213 }
214
OnPause(const JSCallbackInfo & info)215 void JSImageAnimator::OnPause(const JSCallbackInfo& info)
216 {
217 auto onPause = GetAnimatorEvent(info, "ImageAnimator.onPause");
218 ImageAnimatorModel::GetInstance()->SetOnPause(std::move(onPause));
219 }
220
OnRepeat(const JSCallbackInfo & info)221 void JSImageAnimator::OnRepeat(const JSCallbackInfo& info)
222 {
223 auto onRepeat = GetAnimatorEvent(info, "ImageAnimator.onRepeat");
224 ImageAnimatorModel::GetInstance()->SetOnRepeat(std::move(onRepeat));
225 }
226
OnCancel(const JSCallbackInfo & info)227 void JSImageAnimator::OnCancel(const JSCallbackInfo& info)
228 {
229 auto onCancel = GetAnimatorEvent(info, "ImageAnimator.onCancel");
230 ImageAnimatorModel::GetInstance()->SetOnCancel(std::move(onCancel));
231 }
232
OnFinish(const JSCallbackInfo & info)233 void JSImageAnimator::OnFinish(const JSCallbackInfo& info)
234 {
235 auto onFinish = GetAnimatorEvent(info, "ImageAnimator.onFinish");
236 ImageAnimatorModel::GetInstance()->SetOnFinish(std::move(onFinish));
237 }
238
GetAnimatorEvent(const JSCallbackInfo & info,std::string && eventName)239 AnimatorEvent JSImageAnimator::GetAnimatorEvent(const JSCallbackInfo& info, std::string&& eventName)
240 {
241 if (info.Length() != 1) {
242 return {};
243 }
244 if (!info[0]->IsFunction()) {
245 return {};
246 }
247 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
248 auto animatorEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
249 event = std::move(eventName)]() {
250 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
251 ACE_SCORING_EVENT(event);
252 func->Execute();
253 };
254 return animatorEvent;
255 }
256
ParseImages(const JSRef<JSVal> & image,ImageProperties & imageProperties)257 void JSImageAnimator::ParseImages(const JSRef<JSVal>& image, ImageProperties& imageProperties)
258 {
259 if (!image->IsObject()) {
260 return;
261 }
262 JSRef<JSObject> jsObjImage = JSRef<JSObject>::Cast(image);
263 bool srcValid = ParseJsMedia(jsObjImage->GetProperty("src"), imageProperties.src);
264 GetJsMediaBundleInfo(jsObjImage->GetProperty("src"), imageProperties.bundleName, imageProperties.moduleName);
265 if (!srcValid) {
266 #if defined(PIXEL_MAP_SUPPORTED)
267 imageProperties.pixelMap = CreatePixelMapFromNapiValue(jsObjImage->GetProperty("src"));
268 #endif
269 }
270 ParseJsDimensionVp(jsObjImage->GetProperty("width"), imageProperties.width);
271 ParseJsDimensionVp(jsObjImage->GetProperty("height"), imageProperties.height);
272 ParseJsDimensionVp(jsObjImage->GetProperty("top"), imageProperties.top);
273 ParseJsDimensionVp(jsObjImage->GetProperty("left"), imageProperties.left);
274 ParseJsInt32(jsObjImage->GetProperty("duration"), imageProperties.duration);
275 }
276
277 } // namespace OHOS::Ace::Framework
278