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