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