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 return;
87 }
88 if (info[0]->IsNull()) {
89 return;
90 }
91 if (!info[0]->IsArray()) {
92 return;
93 }
94 JSRef<JSArray> imageArray = JSRef<JSArray>::Cast(info[0]);
95 std::vector<ImageProperties> images;
96 for (uint32_t i = 0; i < imageArray->Length(); ++i) {
97 ImageProperties imageProperties;
98 ParseImages(imageArray->GetValueAt(i), imageProperties);
99 images.push_back(imageProperties);
100 }
101
102 ImageAnimatorModel::GetInstance()->SetImages(images);
103 }
104
SetState(const JSCallbackInfo & info)105 void JSImageAnimator::SetState(const JSCallbackInfo& info)
106 {
107 if (info.Length() < 1) {
108 return;
109 }
110 int32_t state = static_cast<int32_t>(Animator::Status::IDLE);
111 if (info[0]->IsNumber()) {
112 state = info[0]->ToNumber<int32_t>();
113 if (state < static_cast<int32_t>(Animator::Status::IDLE) ||
114 state > static_cast<int32_t>(Animator::Status::STOPPED)) {
115 state = static_cast<int32_t>(Animator::Status::IDLE);
116 }
117 }
118
119 ImageAnimatorModel::GetInstance()->SetState(state);
120 }
121
SetDuration(const JSCallbackInfo & info)122 void JSImageAnimator::SetDuration(const JSCallbackInfo& info)
123 {
124 if (info.Length() < 1) {
125 return;
126 }
127 int32_t duration = DEFAULT_DURATION;
128 if (info[0]->IsNumber()) {
129 duration = info[0]->ToNumber<int32_t>();
130 if (duration < 0) {
131 duration = DEFAULT_DURATION;
132 }
133 }
134
135 ImageAnimatorModel::GetInstance()->SetDuration(duration);
136 }
137
SetIteration(const JSCallbackInfo & info)138 void JSImageAnimator::SetIteration(const JSCallbackInfo& info)
139 {
140 if (info.Length() < 1) {
141 return;
142 }
143 int32_t iteration = DEFAULT_ITERATIONS;
144 if (info[0]->IsNumber()) {
145 iteration = info[0]->ToNumber<int32_t>();
146 if (iteration < -1) {
147 iteration = DEFAULT_ITERATIONS;
148 }
149 }
150
151 ImageAnimatorModel::GetInstance()->SetIteration(iteration);
152 }
153
SetFillMode(const JSCallbackInfo & info)154 void JSImageAnimator::SetFillMode(const JSCallbackInfo& info)
155 {
156 if (info.Length() < 1) {
157 return;
158 }
159 int32_t fillMode = static_cast<int32_t>(DEFAULT_FILL_MODE);
160 if (info[0]->IsNumber()) {
161 fillMode = info[0]->ToNumber<int32_t>();
162 if (fillMode < static_cast<int32_t>(FillMode::NONE) || fillMode > static_cast<int32_t>(FillMode::BOTH)) {
163 fillMode = static_cast<int32_t>(DEFAULT_FILL_MODE);
164 }
165 }
166
167 ImageAnimatorModel::GetInstance()->SetFillMode(fillMode);
168 }
169
SetPreDecode(const JSCallbackInfo & info)170 void JSImageAnimator::SetPreDecode(const JSCallbackInfo& info)
171 {
172 if (info.Length() < 1) {
173 return;
174 }
175 int32_t preDecode = 0;
176 if (info[0]->IsNumber()) {
177 preDecode = info[0]->ToNumber<int32_t>();
178 }
179 ImageAnimatorModel::GetInstance()->SetPreDecode(preDecode);
180 }
181
SetIsReverse(const JSCallbackInfo & info)182 void JSImageAnimator::SetIsReverse(const JSCallbackInfo& info)
183 {
184 if (info.Length() < 1) {
185 return;
186 }
187 bool isReverse = false;
188 if (info[0]->IsBoolean()) {
189 isReverse = info[0]->ToBoolean();
190 }
191 ImageAnimatorModel::GetInstance()->SetIsReverse(isReverse);
192 }
193
SetFixedSize(const JSCallbackInfo & info)194 void JSImageAnimator::SetFixedSize(const JSCallbackInfo& info)
195 {
196 if (info.Length() < 1) {
197 return;
198 }
199 bool fixedSize = true;
200 if (info[0]->IsBoolean()) {
201 fixedSize = info[0]->ToBoolean();
202 }
203 ImageAnimatorModel::GetInstance()->SetFixedSize(fixedSize);
204 }
205
OnStart(const JSCallbackInfo & info)206 void JSImageAnimator::OnStart(const JSCallbackInfo& info)
207 {
208 auto onStart = GetAnimatorEvent(info, "ImageAnimator.onStart");
209 ImageAnimatorModel::GetInstance()->SetOnStart(std::move(onStart));
210 }
211
OnPause(const JSCallbackInfo & info)212 void JSImageAnimator::OnPause(const JSCallbackInfo& info)
213 {
214 auto onPause = GetAnimatorEvent(info, "ImageAnimator.onPause");
215 ImageAnimatorModel::GetInstance()->SetOnPause(std::move(onPause));
216 }
217
OnRepeat(const JSCallbackInfo & info)218 void JSImageAnimator::OnRepeat(const JSCallbackInfo& info)
219 {
220 auto onRepeat = GetAnimatorEvent(info, "ImageAnimator.onRepeat");
221 ImageAnimatorModel::GetInstance()->SetOnRepeat(std::move(onRepeat));
222 }
223
OnCancel(const JSCallbackInfo & info)224 void JSImageAnimator::OnCancel(const JSCallbackInfo& info)
225 {
226 auto onCancel = GetAnimatorEvent(info, "ImageAnimator.onCancel");
227 ImageAnimatorModel::GetInstance()->SetOnCancel(std::move(onCancel));
228 }
229
OnFinish(const JSCallbackInfo & info)230 void JSImageAnimator::OnFinish(const JSCallbackInfo& info)
231 {
232 auto onFinish = GetAnimatorEvent(info, "ImageAnimator.onFinish");
233 ImageAnimatorModel::GetInstance()->SetOnFinish(std::move(onFinish));
234 }
235
GetAnimatorEvent(const JSCallbackInfo & info,std::string && eventName)236 AnimatorEvent JSImageAnimator::GetAnimatorEvent(const JSCallbackInfo& info, std::string&& eventName)
237 {
238 if (info.Length() != 1) {
239 return {};
240 }
241 if (!info[0]->IsFunction()) {
242 return {};
243 }
244 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
245 auto animatorEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
246 event = std::move(eventName)]() {
247 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
248 ACE_SCORING_EVENT(event);
249 func->Execute();
250 };
251 return animatorEvent;
252 }
253
ParseImages(const JSRef<JSVal> & image,ImageProperties & imageProperties)254 void JSImageAnimator::ParseImages(const JSRef<JSVal>& image, ImageProperties& imageProperties)
255 {
256 if (!image->IsObject()) {
257 return;
258 }
259 JSRef<JSObject> jsObjImage = JSRef<JSObject>::Cast(image);
260 ParseJsMedia(jsObjImage->GetProperty("src"), imageProperties.src);
261 GetJsMediaBundleInfo(jsObjImage->GetProperty("src"), imageProperties.bundleName, imageProperties.moduleName);
262 ParseJsDimensionVp(jsObjImage->GetProperty("width"), imageProperties.width);
263 ParseJsDimensionVp(jsObjImage->GetProperty("height"), imageProperties.height);
264 ParseJsDimensionVp(jsObjImage->GetProperty("top"), imageProperties.top);
265 ParseJsDimensionVp(jsObjImage->GetProperty("left"), imageProperties.left);
266 ParseJsInt32(jsObjImage->GetProperty("duration"), imageProperties.duration);
267 }
268
269 } // namespace OHOS::Ace::Framework
270