1 /*
2 * Copyright (c) 2021 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 "frameworks/bridge/declarative_frontend/jsview/js_image.h"
17
18 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
19 #include <dlfcn.h>
20 #endif
21
22 #include "base/image/pixel_map.h"
23 #include "base/log/ace_trace.h"
24 #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h"
25 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
26
27 namespace OHOS::Ace::Framework {
28
LoadImageSuccEventToJSValue(const LoadImageSuccessEvent & eventInfo)29 JSRef<JSVal> LoadImageSuccEventToJSValue(const LoadImageSuccessEvent& eventInfo)
30 {
31 JSRef<JSObject> obj = JSRef<JSObject>::New();
32 obj->SetProperty("width", eventInfo.GetWidth());
33 obj->SetProperty("height", eventInfo.GetHeight());
34 obj->SetProperty("componentWidth", eventInfo.GetComponentWidth());
35 obj->SetProperty("componentHeight", eventInfo.GetComponentHeight());
36 obj->SetProperty("loadingStatus", eventInfo.GetLoadingStatus());
37 return JSRef<JSVal>::Cast(obj);
38 }
39
LoadImageFailEventToJSValue(const LoadImageFailEvent & eventInfo)40 JSRef<JSVal> LoadImageFailEventToJSValue(const LoadImageFailEvent& eventInfo)
41 {
42 JSRef<JSObject> obj = JSRef<JSObject>::New();
43 obj->SetProperty("componentWidth", eventInfo.GetComponentWidth());
44 obj->SetProperty("componentHeight", eventInfo.GetComponentHeight());
45 return JSRef<JSVal>::Cast(obj);
46 }
47
SetAlt(const JSCallbackInfo & args)48 void JSImage::SetAlt(const JSCallbackInfo& args)
49 {
50 if (args.Length() < 1) {
51 LOGE("The argv is wrong, it it supposed to have at least 1 argument");
52 return;
53 }
54
55 std::string src;
56 if (!ParseJsMedia(args[0], src)) {
57 return;
58 }
59
60 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
61 if (image) {
62 image->SetAlt(src);
63 }
64 }
65
SetObjectFit(int32_t value)66 void JSImage::SetObjectFit(int32_t value)
67 {
68 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
69 if (image) {
70 image->SetImageFit(static_cast<ImageFit>(value));
71 }
72 }
73
SetMatchTextDirection(bool value)74 void JSImage::SetMatchTextDirection(bool value)
75 {
76 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
77 if (image) {
78 image->SetMatchTextDirection(value);
79 }
80 }
81
SetFitOriginalSize(bool value)82 void JSImage::SetFitOriginalSize(bool value)
83 {
84 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
85 if (image) {
86 image->SetFitMaxSize(!value);
87 }
88 }
89
GetFrontDecoration()90 RefPtr<Decoration> JSImage::GetFrontDecoration()
91 {
92 auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
93 auto decoration = box->GetFrontDecoration();
94 if (!decoration) {
95 decoration = AceType::MakeRefPtr<Decoration>();
96 box->SetFrontDecoration(decoration);
97 }
98
99 return decoration;
100 }
101
GetBorder()102 const Border& JSImage::GetBorder()
103 {
104 return GetFrontDecoration()->GetBorder();
105 }
106
GetLeftBorderEdge()107 BorderEdge JSImage::GetLeftBorderEdge()
108 {
109 return GetBorder().Left();
110 }
111
GetTopBorderEdge()112 BorderEdge JSImage::GetTopBorderEdge()
113 {
114 return GetBorder().Top();
115 }
116
GetRightBorderEdge()117 BorderEdge JSImage::GetRightBorderEdge()
118 {
119 return GetBorder().Right();
120 }
121
GetBottomBorderEdge()122 BorderEdge JSImage::GetBottomBorderEdge()
123 {
124 return GetBorder().Bottom();
125 }
126
SetBorderEdge(const BorderEdge & edge)127 void JSImage::SetBorderEdge(const BorderEdge& edge)
128 {
129 Border border = GetBorder();
130 border.SetBorderEdge(edge);
131 SetBorder(border);
132 }
133
SetLeftBorderEdge(const BorderEdge & edge)134 void JSImage::SetLeftBorderEdge(const BorderEdge& edge)
135 {
136 Border border = GetBorder();
137 border.SetLeftEdge(edge);
138 SetBorder(border);
139 }
140
SetTopBorderEdge(const BorderEdge & edge)141 void JSImage::SetTopBorderEdge(const BorderEdge& edge)
142 {
143 Border border = GetBorder();
144 border.SetTopEdge(edge);
145 SetBorder(border);
146 }
147
SetRightBorderEdge(const BorderEdge & edge)148 void JSImage::SetRightBorderEdge(const BorderEdge& edge)
149 {
150 Border border = GetBorder();
151 border.SetRightEdge(edge);
152 SetBorder(border);
153 }
154
SetBottomBorderEdge(const BorderEdge & edge)155 void JSImage::SetBottomBorderEdge(const BorderEdge& edge)
156 {
157 Border border = GetBorder();
158 border.SetBottomEdge(edge);
159 SetBorder(border);
160 }
161
SetBorder(const Border & border)162 void JSImage::SetBorder(const Border& border)
163 {
164 GetFrontDecoration()->SetBorder(border);
165 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
166 if (image) {
167 image->SetBorder(border);
168 }
169 }
170
SetLeftBorderColor(const Color & color)171 void JSImage::SetLeftBorderColor(const Color& color)
172 {
173 BorderEdge edge = GetLeftBorderEdge();
174 edge.SetColor(color);
175 SetLeftBorderEdge(edge);
176 }
177
SetTopBorderColor(const Color & color)178 void JSImage::SetTopBorderColor(const Color& color)
179 {
180 BorderEdge edge = GetTopBorderEdge();
181 edge.SetColor(color);
182 SetTopBorderEdge(edge);
183 }
184
SetRightBorderColor(const Color & color)185 void JSImage::SetRightBorderColor(const Color& color)
186 {
187 BorderEdge edge = GetRightBorderEdge();
188 edge.SetColor(color);
189 SetRightBorderEdge(edge);
190 }
191
SetBottomBorderColor(const Color & color)192 void JSImage::SetBottomBorderColor(const Color& color)
193 {
194 BorderEdge edge = GetBottomBorderEdge();
195 edge.SetColor(color);
196 SetBottomBorderEdge(edge);
197 }
198
SetLeftBorderWidth(const Dimension & value)199 void JSImage::SetLeftBorderWidth(const Dimension& value)
200 {
201 BorderEdge edge = GetLeftBorderEdge();
202 edge.SetWidth(value);
203 SetLeftBorderEdge(edge);
204 }
205
SetTopBorderWidth(const Dimension & value)206 void JSImage::SetTopBorderWidth(const Dimension& value)
207 {
208 BorderEdge edge = GetTopBorderEdge();
209 edge.SetWidth(value);
210 SetTopBorderEdge(edge);
211 }
212
SetRightBorderWidth(const Dimension & value)213 void JSImage::SetRightBorderWidth(const Dimension& value)
214 {
215 BorderEdge edge = GetRightBorderEdge();
216 edge.SetWidth(value);
217 SetRightBorderEdge(edge);
218 }
219
SetBottomBorderWidth(const Dimension & value)220 void JSImage::SetBottomBorderWidth(const Dimension& value)
221 {
222 BorderEdge edge = GetBottomBorderEdge();
223 edge.SetWidth(value);
224 SetBottomBorderEdge(edge);
225 }
226
OnComplete(const JSCallbackInfo & args)227 void JSImage::OnComplete(const JSCallbackInfo& args)
228 {
229 LOGD("JSImage V8OnComplete");
230 if (args[0]->IsFunction()) {
231 auto jsLoadSuccFunc = AceType::MakeRefPtr<JsEventFunction<LoadImageSuccessEvent, 1>>(
232 JSRef<JSFunc>::Cast(args[0]), LoadImageSuccEventToJSValue);
233 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
234 image->SetLoadSuccessEvent(EventMarker(
235 [execCtx = args.GetExecutionContext(), func = std::move(jsLoadSuccFunc)](const BaseEventInfo* info) {
236 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
237 auto eventInfo = TypeInfoHelper::DynamicCast<LoadImageSuccessEvent>(info);
238 ACE_SCORING_EVENT("Image.onComplete");
239 func->Execute(*eventInfo);
240 }));
241 } else {
242 LOGE("args not function");
243 }
244 }
245
OnError(const JSCallbackInfo & args)246 void JSImage::OnError(const JSCallbackInfo& args)
247 {
248 LOGD("JSImage V8OnError");
249 if (args[0]->IsFunction()) {
250 auto jsLoadFailFunc = AceType::MakeRefPtr<JsEventFunction<LoadImageFailEvent, 1>>(
251 JSRef<JSFunc>::Cast(args[0]), LoadImageFailEventToJSValue);
252 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
253 image->SetLoadFailEvent(EventMarker(
254 [execCtx = args.GetExecutionContext(), func = std::move(jsLoadFailFunc)](const BaseEventInfo* info) {
255 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
256 auto eventInfo = TypeInfoHelper::DynamicCast<LoadImageFailEvent>(info);
257 ACE_SCORING_EVENT("Image.onError");
258 func->Execute(*eventInfo);
259 }));
260 } else {
261 LOGE("args not function");
262 }
263 }
264
OnFinish(const JSCallbackInfo & info)265 void JSImage::OnFinish(const JSCallbackInfo& info)
266 {
267 LOGD("JSImage V8OnFinish");
268 if (!info[0]->IsFunction()) {
269 LOGE("info[0] is not a function.");
270 return;
271 }
272 RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
273 auto eventMarker = EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc)]() {
274 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
275 ACE_SCORING_EVENT("Image.onFinish");
276 func->Execute();
277 });
278 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
279 image->SetSvgAnimatorFinishEvent(eventMarker);
280 }
281
Create(const JSCallbackInfo & info)282 void JSImage::Create(const JSCallbackInfo& info)
283 {
284 if (info.Length() < 1) {
285 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
286 return;
287 }
288 std::string src;
289 auto noPixMap = ParseJsMedia(info[0], src);
290 RefPtr<ImageComponent> imageComponent = AceType::MakeRefPtr<OHOS::Ace::ImageComponent>(src);
291 imageComponent->SetUseSkiaSvg(false);
292 ViewStackProcessor::GetInstance()->Push(imageComponent);
293 JSInteractableView::SetFocusable(true);
294 JSInteractableView::SetFocusNode(false);
295 if (noPixMap) {
296 return;
297 }
298
299 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
300 imageComponent->SetPixmap(CreatePixelMapFromNapiValue(info[0]));
301 #endif
302 }
303
JsBorder(const JSCallbackInfo & info)304 void JSImage::JsBorder(const JSCallbackInfo& info)
305 {
306 JSViewAbstract::JsBorder(info);
307 SetBorder(GetBackDecoration()->GetBorder());
308 }
309
JsBorderRadius(const JSCallbackInfo & info)310 void JSImage::JsBorderRadius(const JSCallbackInfo& info)
311 {
312 JSViewAbstract::JsBorderRadius(info);
313 SetBorder(GetBackDecoration()->GetBorder());
314 }
315
SetSourceSize(const JSCallbackInfo & info)316 void JSImage::SetSourceSize(const JSCallbackInfo& info)
317 {
318 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
319 image->SetImageSourceSize(JSViewAbstract::ParseSize(info));
320 }
321
SetImageFill(const JSCallbackInfo & info)322 void JSImage::SetImageFill(const JSCallbackInfo& info)
323 {
324 if (info.Length() < 1) {
325 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
326 return;
327 }
328
329 Color color;
330 if (!ParseJsColor(info[0], color)) {
331 return;
332 }
333 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
334 image->SetImageFill(color);
335 }
336
SetImageRenderMode(int32_t imageRenderMode)337 void JSImage::SetImageRenderMode(int32_t imageRenderMode)
338 {
339 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
340 image->SetImageRenderMode(static_cast<ImageRenderMode>(imageRenderMode));
341 }
342
SetImageInterpolation(int32_t imageInterpolation)343 void JSImage::SetImageInterpolation(int32_t imageInterpolation)
344 {
345 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
346 image->SetImageInterpolation(static_cast<ImageInterpolation>(imageInterpolation));
347 }
348
SetImageRepeat(int32_t imageRepeat)349 void JSImage::SetImageRepeat(int32_t imageRepeat)
350 {
351 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
352 image->SetImageRepeat(static_cast<ImageRepeat>(imageRepeat));
353 }
354
JsTransition(const JSCallbackInfo & info)355 void JSImage::JsTransition(const JSCallbackInfo& info)
356 {
357 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
358 if (image && image->IsSrcSvgImage()) {
359 JSViewAbstract::JsTransition(info);
360 } else {
361 JSViewAbstract::JsTransitionPassThrough(info);
362 }
363 }
364
JsOpacity(const JSCallbackInfo & info)365 void JSImage::JsOpacity(const JSCallbackInfo& info)
366 {
367 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
368 if (image && image->IsSrcSvgImage()) {
369 JSViewAbstract::JsOpacity(info);
370 } else {
371 JSViewAbstract::JsOpacityPassThrough(info);
372 }
373 }
374
SetAutoResize(bool autoResize)375 void JSImage::SetAutoResize(bool autoResize)
376 {
377 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
378 if (image) {
379 image->SetAutoResize(autoResize);
380 }
381 }
382
SetSyncLoad(const JSCallbackInfo & info)383 void JSImage::SetSyncLoad(const JSCallbackInfo& info)
384 {
385 auto image = AceType::DynamicCast<ImageComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
386 if (image) {
387 image->SetSyncMode(info[0]->ToBoolean());
388 }
389 }
390
JSBind(BindingTarget globalObj)391 void JSImage::JSBind(BindingTarget globalObj)
392 {
393 JSClass<JSImage>::Declare("Image");
394 MethodOptions opt = MethodOptions::NONE;
395 JSClass<JSImage>::StaticMethod("create", &JSImage::Create, opt);
396 JSClass<JSImage>::StaticMethod("alt", &JSImage::SetAlt, opt);
397 JSClass<JSImage>::StaticMethod("objectFit", &JSImage::SetObjectFit, opt);
398 JSClass<JSImage>::StaticMethod("matchTextDirection", &JSImage::SetMatchTextDirection, opt);
399 JSClass<JSImage>::StaticMethod("fitOriginalSize", &JSImage::SetFitOriginalSize, opt);
400 JSClass<JSImage>::StaticMethod("sourceSize", &JSImage::SetSourceSize, opt);
401 JSClass<JSImage>::StaticMethod("fillColor", &JSImage::SetImageFill, opt);
402 JSClass<JSImage>::StaticMethod("renderMode", &JSImage::SetImageRenderMode, opt);
403 JSClass<JSImage>::StaticMethod("objectRepeat", &JSImage::SetImageRepeat, opt);
404 JSClass<JSImage>::StaticMethod("interpolation", &JSImage::SetImageInterpolation, opt);
405 JSClass<JSImage>::StaticMethod("borderStyle", &JSViewAbstract::SetBorderStyle, opt);
406 JSClass<JSImage>::StaticMethod("borderColor", &JSViewAbstract::JsBorderColor);
407 JSClass<JSImage>::StaticMethod("border", &JSImage::JsBorder);
408 JSClass<JSImage>::StaticMethod("borderWidth", &JSViewAbstract::JsBorderWidth);
409 JSClass<JSImage>::StaticMethod("borderRadius", &JSImage::JsBorderRadius);
410 JSClass<JSImage>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
411 JSClass<JSImage>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
412 JSClass<JSImage>::StaticMethod("autoResize", &JSImage::SetAutoResize);
413
414 JSClass<JSImage>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
415 JSClass<JSImage>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
416 JSClass<JSImage>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
417 JSClass<JSImage>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
418 JSClass<JSImage>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
419 JSClass<JSImage>::StaticMethod("onComplete", &JSImage::OnComplete);
420 JSClass<JSImage>::StaticMethod("onError", &JSImage::OnError);
421 JSClass<JSImage>::StaticMethod("onFinish", &JSImage::OnFinish);
422 JSClass<JSImage>::StaticMethod("syncLoad", &JSImage::SetSyncLoad);
423 JSClass<JSImage>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
424 JSClass<JSImage>::Inherit<JSViewAbstract>();
425 // override method
426 JSClass<JSImage>::StaticMethod("opacity", &JSImage::JsOpacity);
427 JSClass<JSImage>::StaticMethod("transition", &JSImage::JsTransition);
428 JSClass<JSImage>::Bind<>(globalObj);
429 }
430
431 } // namespace OHOS::Ace::Framework
432