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/view_stack_processor.h"
20 #include "core/components_ng/pattern/image_animator/image_animator_view.h"
21
22 namespace OHOS::Ace::Framework {
23
24 constexpr uint32_t DEFAULT_DURATION = 1000; // ms
25 constexpr uint32_t DEFAULT_ITERATIONS = 1;
26 constexpr FillMode DEFAULT_FILL_MODE = FillMode::FORWARDS;
27
Create()28 void JSImageAnimator::Create()
29 {
30 if (Container::IsCurrentUseNewPipeline()) {
31 NG::ImageAnimatorView::Create();
32 return;
33 }
34 RefPtr<ImageAnimatorComponent> imageAnimator = AceType::MakeRefPtr<ImageAnimatorComponent>("ImageAnimator");
35 imageAnimator->SetIteration(DEFAULT_ITERATIONS);
36 imageAnimator->SetDuration(DEFAULT_DURATION);
37 ViewStackProcessor::GetInstance()->Push(imageAnimator);
38 // Init Common Styles for ImageAnimator
39 ViewStackProcessor::GetInstance()->GetBoxComponent();
40 }
41
JSBind(BindingTarget globalObj)42 void JSImageAnimator::JSBind(BindingTarget globalObj)
43 {
44 JSClass<JSImageAnimator>::Declare("ImageAnimator");
45 MethodOptions opt = MethodOptions::NONE;
46 JSClass<JSImageAnimator>::StaticMethod("create", &JSImageAnimator::Create, opt);
47 JSClass<JSImageAnimator>::StaticMethod("images", &JSImageAnimator::SetImages, opt);
48 JSClass<JSImageAnimator>::StaticMethod("state", &JSImageAnimator::SetState, opt);
49 JSClass<JSImageAnimator>::StaticMethod("duration", &JSImageAnimator::SetDuration, opt);
50 JSClass<JSImageAnimator>::StaticMethod("iterations", &JSImageAnimator::SetIteration, opt);
51 JSClass<JSImageAnimator>::StaticMethod("reverse", &JSImageAnimator::SetIsReverse, opt);
52 JSClass<JSImageAnimator>::StaticMethod("fixedSize", &JSImageAnimator::SetFixedSize, opt);
53 JSClass<JSImageAnimator>::StaticMethod("fillMode", &JSImageAnimator::SetFillMode, opt);
54 JSClass<JSImageAnimator>::StaticMethod("preDecode", &JSImageAnimator::SetPreDecode, opt);
55
56 JSClass<JSImageAnimator>::StaticMethod("onStart", &JSImageAnimator::OnStart, opt);
57 JSClass<JSImageAnimator>::StaticMethod("onPause", &JSImageAnimator::OnPause, opt);
58 JSClass<JSImageAnimator>::StaticMethod("onRepeat", &JSImageAnimator::OnRepeat, opt);
59 JSClass<JSImageAnimator>::StaticMethod("onCancel", &JSImageAnimator::OnCancel, opt);
60 JSClass<JSImageAnimator>::StaticMethod("onFinish", &JSImageAnimator::OnFinish, opt);
61
62 JSClass<JSImageAnimator>::Inherit<JSContainerBase>();
63 JSClass<JSImageAnimator>::Inherit<JSViewAbstract>();
64 JSClass<JSImageAnimator>::Bind<>(globalObj);
65 }
66
SetImages(const JSCallbackInfo & info)67 void JSImageAnimator::SetImages(const JSCallbackInfo& info)
68 {
69 if (info.Length() < 1) {
70 LOGE("JSImageAnimator: The arg is wrong, it is supposed to have one object argument.");
71 return;
72 }
73 if (info[0]->IsNull()) {
74 LOGE("JSImageAnimator: info is null.");
75 return;
76 }
77 if (!info[0]->IsArray()) {
78 LOGE("JSImageAnimator: info is not array.");
79 return;
80 }
81 JSRef<JSArray> imageArray = JSRef<JSArray>::Cast(info[0]);
82 std::vector<ImageProperties> images;
83 for (uint32_t i = 0; i < imageArray->Length(); ++i) {
84 ImageProperties imageProperties;
85 ParseImages(imageArray->GetValueAt(i), imageProperties);
86 images.push_back(imageProperties);
87 }
88
89 if (Container::IsCurrentUseNewPipeline()) {
90 NG::ImageAnimatorView::SetImages(std::move(images));
91 return;
92 }
93
94 auto imageAnimator =
95 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
96 if (imageAnimator) {
97 imageAnimator->SetImageProperties(images);
98 }
99 }
100
SetState(int32_t state)101 void JSImageAnimator::SetState(int32_t state)
102 {
103 if (state < static_cast<int32_t>(Animator::Status::IDLE) ||
104 state > static_cast<int32_t>(Animator::Status::STOPPED)) {
105 LOGW("ImageAnimator SetState %{public}d, invalid, use default AnimationStatus.Initial", state);
106 state = static_cast<int32_t>(Animator::Status::IDLE);
107 }
108 if (Container::IsCurrentUseNewPipeline()) {
109 NG::ImageAnimatorView::SetStatus(static_cast<Animator::Status>(state));
110 return;
111 }
112 auto imageAnimator =
113 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
114 if (imageAnimator) {
115 imageAnimator->SetStatus(static_cast<Animator::Status>(state));
116 }
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 if (Container::IsCurrentUseNewPipeline()) {
126 NG::ImageAnimatorView::SetDuration(duration);
127 return;
128 }
129 auto imageAnimator =
130 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
131 if (imageAnimator) {
132 imageAnimator->SetDuration(duration);
133 }
134 }
135
SetIteration(int32_t iteration)136 void JSImageAnimator::SetIteration(int32_t iteration)
137 {
138 if (iteration < -1) {
139 LOGW("ImageAnimator SetIteration %{public}d, invalid, use default %{public}d", iteration, DEFAULT_ITERATIONS);
140 iteration = DEFAULT_ITERATIONS;
141 }
142 if (Container::IsCurrentUseNewPipeline()) {
143 NG::ImageAnimatorView::SetIteration(iteration);
144 return;
145 }
146 auto imageAnimator =
147 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
148 if (imageAnimator) {
149 imageAnimator->SetIteration(iteration);
150 }
151 }
152
SetFillMode(int32_t fillMode)153 void JSImageAnimator::SetFillMode(int32_t fillMode)
154 {
155 if (fillMode < static_cast<int32_t>(FillMode::NONE) || fillMode > static_cast<int32_t>(FillMode::BOTH)) {
156 LOGW("ImageAnimator SetFillMode %{public}d, invalid, use default %{public}d", fillMode,
157 static_cast<int32_t>(DEFAULT_FILL_MODE));
158 fillMode = static_cast<int32_t>(DEFAULT_FILL_MODE);
159 }
160 if (Container::IsCurrentUseNewPipeline()) {
161 NG::ImageAnimatorView::SetFillMode(static_cast<FillMode>(fillMode));
162 return;
163 }
164 auto imageAnimator =
165 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
166 if (imageAnimator) {
167 imageAnimator->SetFillMode(static_cast<FillMode>(fillMode));
168 }
169 }
170
SetPreDecode(int32_t preDecode)171 void JSImageAnimator::SetPreDecode(int32_t preDecode)
172 {
173 if (Container::IsCurrentUseNewPipeline()) {
174 NG::ImageAnimatorView::SetPreDecode(preDecode);
175 return;
176 }
177 auto imageAnimator =
178 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
179 if (imageAnimator) {
180 imageAnimator->SetPreDecode(preDecode);
181 }
182 }
183
SetIsReverse(bool isReverse)184 void JSImageAnimator::SetIsReverse(bool isReverse)
185 {
186 if (Container::IsCurrentUseNewPipeline()) {
187 NG::ImageAnimatorView::SetIsReverse(isReverse);
188 return;
189 }
190 auto imageAnimator =
191 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
192 if (imageAnimator) {
193 imageAnimator->SetIsReverse(isReverse);
194 }
195 }
196
SetFixedSize(bool fixedSize)197 void JSImageAnimator::SetFixedSize(bool fixedSize)
198 {
199 if (Container::IsCurrentUseNewPipeline()) {
200 NG::ImageAnimatorView::SetFixedSize(fixedSize);
201 return;
202 }
203 auto imageAnimator =
204 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
205 if (imageAnimator) {
206 imageAnimator->SetIsFixedSize(fixedSize);
207 }
208 }
209
OnStart(const JSCallbackInfo & info)210 void JSImageAnimator::OnStart(const JSCallbackInfo& info)
211 {
212 if (Container::IsCurrentUseNewPipeline()) {
213 NG::ImageAnimatorView::SetImageAnimatorEvent(GetAnimatorEvent(info), NG::AnimatorEventType::ON_START);
214 return;
215 }
216 auto imageAnimator =
217 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
218 if (!imageAnimator) {
219 return;
220 }
221 const auto& controller = imageAnimator->GetImageAnimatorController();
222 if (controller) {
223 auto startEvent = GetEventMarker(info);
224 controller->SetStartEvent(startEvent);
225 }
226 }
227
OnPause(const JSCallbackInfo & info)228 void JSImageAnimator::OnPause(const JSCallbackInfo& info)
229 {
230 if (Container::IsCurrentUseNewPipeline()) {
231 NG::ImageAnimatorView::SetImageAnimatorEvent(GetAnimatorEvent(info), NG::AnimatorEventType::ON_PAUSE);
232 return;
233 }
234 auto imageAnimator =
235 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
236 if (!imageAnimator) {
237 return;
238 }
239 const auto& controller = imageAnimator->GetImageAnimatorController();
240 if (controller) {
241 auto pauseEvent = GetEventMarker(info);
242 controller->SetPauseEvent(pauseEvent);
243 }
244 }
245
OnRepeat(const JSCallbackInfo & info)246 void JSImageAnimator::OnRepeat(const JSCallbackInfo& info)
247 {
248 if (Container::IsCurrentUseNewPipeline()) {
249 NG::ImageAnimatorView::SetImageAnimatorEvent(GetAnimatorEvent(info), NG::AnimatorEventType::ON_REPEAT);
250 return;
251 }
252 auto imageAnimator =
253 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
254 if (!imageAnimator) {
255 return;
256 }
257 const auto& controller = imageAnimator->GetImageAnimatorController();
258 if (controller) {
259 auto repeatEvent = GetEventMarker(info);
260 controller->SetRepeatEvent(repeatEvent);
261 }
262 }
263
OnCancel(const JSCallbackInfo & info)264 void JSImageAnimator::OnCancel(const JSCallbackInfo& info)
265 {
266 if (Container::IsCurrentUseNewPipeline()) {
267 NG::ImageAnimatorView::SetImageAnimatorEvent(GetAnimatorEvent(info), NG::AnimatorEventType::ON_CANCEL);
268 return;
269 }
270 auto imageAnimator =
271 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
272 if (!imageAnimator) {
273 return;
274 }
275 const auto& controller = imageAnimator->GetImageAnimatorController();
276 if (controller) {
277 auto cancelEvent = GetEventMarker(info);
278 controller->SetCancelEvent(cancelEvent);
279 }
280 }
281
OnFinish(const JSCallbackInfo & info)282 void JSImageAnimator::OnFinish(const JSCallbackInfo& info)
283 {
284 if (Container::IsCurrentUseNewPipeline()) {
285 NG::ImageAnimatorView::SetImageAnimatorEvent(GetAnimatorEvent(info), NG::AnimatorEventType::ON_FINISH);
286 return;
287 }
288 auto imageAnimator =
289 AceType::DynamicCast<ImageAnimatorComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
290 if (!imageAnimator) {
291 return;
292 }
293 const auto& controller = imageAnimator->GetImageAnimatorController();
294 if (controller) {
295 auto finishEvent = GetEventMarker(info);
296 controller->SetStopEvent(finishEvent);
297 }
298 }
299
GetEventMarker(const JSCallbackInfo & info)300 EventMarker JSImageAnimator::GetEventMarker(const JSCallbackInfo& info)
301 {
302 if (!info[0]->IsFunction()) {
303 LOGE("info[0] is not a function.");
304 return {};
305 }
306 RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
307 auto eventMarker = EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc)]() {
308 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
309 ACE_SCORING_EVENT("ImageAnimator.onClick");
310 func->Execute();
311 });
312 return eventMarker;
313 }
314
GetAnimatorEvent(const JSCallbackInfo & info)315 AnimatorEvent JSImageAnimator::GetAnimatorEvent(const JSCallbackInfo& info)
316 {
317 if (!info[0]->IsFunction()) {
318 LOGE("info[0] is not a function.");
319 return {};
320 }
321 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
322 auto animatorEvent = [func = std::move(jsFunc)]() { func->Execute(); };
323 return animatorEvent;
324 }
325
ParseImages(const JSRef<JSVal> & image,ImageProperties & imageProperties)326 void JSImageAnimator::ParseImages(const JSRef<JSVal>& image, ImageProperties& imageProperties)
327 {
328 if (!image->IsObject()) {
329 LOGE("image is not Object.");
330 return;
331 }
332 JSRef<JSObject> jsObjImage = JSRef<JSObject>::Cast(image);
333 if (!ParseJsMedia(jsObjImage->GetProperty("src"), imageProperties.src)) {
334 LOGE("parse image property src failed!");
335 }
336 ParseJsDimensionVp(jsObjImage->GetProperty("width"), imageProperties.width);
337 ParseJsDimensionVp(jsObjImage->GetProperty("height"), imageProperties.height);
338 ParseJsDimensionVp(jsObjImage->GetProperty("top"), imageProperties.top);
339 ParseJsDimensionVp(jsObjImage->GetProperty("left"), imageProperties.left);
340 ParseJsInt32(jsObjImage->GetProperty("duration"), imageProperties.duration);
341 }
342
343 } // namespace OHOS::Ace::Framework
344