• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 #include <cstdint>
18 #include <vector>
19 #include "base/utils/utils.h"
20 
21 #if !defined(PREVIEW)
22 #include <dlfcn.h>
23 #endif
24 
25 #include "base/geometry/ng/vector.h"
26 #include "base/image/pixel_map.h"
27 #include "base/log/ace_scoring_log.h"
28 #include "base/log/ace_trace.h"
29 #include "bridge/declarative_frontend/engine/functions/js_drag_function.h"
30 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
31 #include "bridge/declarative_frontend/engine/js_types.h"
32 #include "bridge/declarative_frontend/jsview/models/image_model_impl.h"
33 #include "core/common/container.h"
34 #include "core/components/image/image_event.h"
35 #include "core/components/image/image_theme.h"
36 #include "core/components_ng/base/view_stack_processor.h"
37 #include "core/components_ng/event/gesture_event_hub.h"
38 #include "core/components_ng/pattern/image/image_model.h"
39 #include "core/components_ng/pattern/image/image_model_ng.h"
40 #include "core/image/image_source_info.h"
41 #include "interfaces/inner_api/ace/ai/image_analyzer.h"
42 
43 namespace {
44     const std::vector<float> DEFAULT_COLORFILTER_MATRIX = {
45         1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0
46     };
47     constexpr float CEIL_SMOOTHEDGE_VALUE = 1.333f;
48     constexpr float FLOOR_SMOOTHEDGE_VALUE = 0.334f;
49     constexpr float DEFAULT_SMOOTHEDGE_VALUE = 0.0f;
50 }
51 
52 namespace OHOS::Ace {
53 
54 std::unique_ptr<ImageModel> ImageModel::instance_ = nullptr;
55 std::mutex ImageModel::mutex_;
56 
GetInstance()57 ImageModel* ImageModel::GetInstance()
58 {
59     if (!instance_) {
60         std::lock_guard<std::mutex> lock(mutex_);
61         if (!instance_) {
62 #ifdef NG_BUILD
63             instance_.reset(new NG::ImageModelNG());
64 #else
65             if (Container::IsCurrentUseNewPipeline()) {
66                 instance_.reset(new NG::ImageModelNG());
67             } else {
68                 instance_.reset(new Framework::ImageModelImpl());
69             }
70 #endif
71         }
72     }
73     return instance_.get();
74 }
75 
76 } // namespace OHOS::Ace
77 
78 namespace OHOS::Ace::Framework {
79 
LoadImageSuccEventToJSValue(const LoadImageSuccessEvent & eventInfo)80 JSRef<JSVal> LoadImageSuccEventToJSValue(const LoadImageSuccessEvent& eventInfo)
81 {
82     JSRef<JSObject> obj = JSRef<JSObject>::New();
83     obj->SetProperty("width", eventInfo.GetWidth());
84     obj->SetProperty("height", eventInfo.GetHeight());
85     obj->SetProperty("componentWidth", eventInfo.GetComponentWidth());
86     obj->SetProperty("componentHeight", eventInfo.GetComponentHeight());
87     obj->SetProperty("loadingStatus", eventInfo.GetLoadingStatus());
88     obj->SetProperty("contentWidth", eventInfo.GetContentWidth());
89     obj->SetProperty("contentHeight", eventInfo.GetContentHeight());
90     obj->SetProperty("contentOffsetX", eventInfo.GetContentOffsetX());
91     obj->SetProperty("contentOffsetY", eventInfo.GetContentOffsetY());
92     return JSRef<JSVal>::Cast(obj);
93 }
94 
LoadImageFailEventToJSValue(const LoadImageFailEvent & eventInfo)95 JSRef<JSVal> LoadImageFailEventToJSValue(const LoadImageFailEvent& eventInfo)
96 {
97     JSRef<JSObject> obj = JSRef<JSObject>::New();
98     obj->SetProperty("componentWidth", eventInfo.GetComponentWidth());
99     obj->SetProperty("componentHeight", eventInfo.GetComponentHeight());
100     obj->SetProperty("message", eventInfo.GetErrorMessage());
101     return JSRef<JSVal>::Cast(obj);
102 }
103 
SetAlt(const JSCallbackInfo & args)104 void JSImage::SetAlt(const JSCallbackInfo& args)
105 {
106     if (args.Length() < 1) {
107         return;
108     }
109 
110     std::string src;
111     if (args[0]->IsString()) {
112         src = args[0]->ToString();
113     } else if (!ParseJsMedia(args[0], src)) {
114         return;
115     }
116     int32_t resId = 0;
117     if (args[0]->IsObject()) {
118         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(args[0]);
119         JSRef<JSVal> tmp = jsObj->GetProperty("id");
120         if (!tmp->IsNull() && tmp->IsNumber()) {
121             resId = tmp->ToNumber<int32_t>();
122         }
123     }
124     if (ImageSourceInfo::ResolveURIType(src) == SrcType::NETWORK) {
125         return;
126     }
127     std::string bundleName;
128     std::string moduleName;
129     GetJsMediaBundleInfo(args[0], bundleName, moduleName);
130     ImageSourceInfo srcInfo = ImageSourceInfo { src, bundleName, moduleName };
131     srcInfo.SetIsUriPureNumber((resId == -1));
132     ImageModel::GetInstance()->SetAlt(srcInfo);
133 }
134 
SetObjectFit(const JSCallbackInfo & args)135 void JSImage::SetObjectFit(const JSCallbackInfo& args)
136 {
137     if (args.Length() < 1) {
138         ImageModel::GetInstance()->SetImageFit(ImageFit::COVER);
139         return;
140     }
141     int32_t parseRes = 2;
142     ParseJsInteger(args[0], parseRes);
143     if (parseRes < static_cast<int32_t>(ImageFit::FILL) || parseRes > static_cast<int32_t>(ImageFit::SCALE_DOWN)) {
144         parseRes = 2;
145     }
146     auto fit = static_cast<ImageFit>(parseRes);
147     ImageModel::GetInstance()->SetImageFit(fit);
148 }
149 
SetMatchTextDirection(bool value)150 void JSImage::SetMatchTextDirection(bool value)
151 {
152     ImageModel::GetInstance()->SetMatchTextDirection(value);
153 }
154 
SetFitOriginalSize(bool value)155 void JSImage::SetFitOriginalSize(bool value)
156 {
157     ImageModel::GetInstance()->SetFitOriginSize(value);
158 }
159 
SetBorder(const Border & border)160 void JSImage::SetBorder(const Border& border)
161 {
162     ImageModel::GetInstance()->SetBorder(border);
163 }
164 
OnComplete(const JSCallbackInfo & args)165 void JSImage::OnComplete(const JSCallbackInfo& args)
166 {
167     if (args[0]->IsFunction()) {
168         auto jsLoadSuccFunc = AceType::MakeRefPtr<JsEventFunction<LoadImageSuccessEvent, 1>>(
169             JSRef<JSFunc>::Cast(args[0]), LoadImageSuccEventToJSValue);
170 
171         auto onComplete = [execCtx = args.GetExecutionContext(), func = std::move(jsLoadSuccFunc)](
172                               const LoadImageSuccessEvent& info) {
173             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
174             ACE_SCORING_EVENT("Image.onComplete");
175             func->Execute(info);
176         };
177         ImageModel::GetInstance()->SetOnComplete(std::move(onComplete));
178     }
179 }
180 
OnError(const JSCallbackInfo & args)181 void JSImage::OnError(const JSCallbackInfo& args)
182 {
183     if (args[0]->IsFunction()) {
184         auto jsLoadFailFunc = AceType::MakeRefPtr<JsEventFunction<LoadImageFailEvent, 1>>(
185             JSRef<JSFunc>::Cast(args[0]), LoadImageFailEventToJSValue);
186         auto onError = [execCtx = args.GetExecutionContext(), func = std::move(jsLoadFailFunc)](
187                            const LoadImageFailEvent& info) {
188             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
189             ACE_SCORING_EVENT("Image.onError");
190             func->Execute(info);
191         };
192 
193         ImageModel::GetInstance()->SetOnError(onError);
194     }
195 }
196 
OnFinish(const JSCallbackInfo & info)197 void JSImage::OnFinish(const JSCallbackInfo& info)
198 {
199     auto tmpInfo = info[0];
200     if (!tmpInfo->IsFunction()) {
201         return;
202     }
203     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(tmpInfo));
204     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
205     auto onFinish = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
206         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
207         ACE_SCORING_EVENT("Image.onFinish");
208         PipelineContext::SetCallBackNode(node);
209         func->Execute();
210     };
211     ImageModel::GetInstance()->SetSvgAnimatorFinishEvent(onFinish);
212 }
213 
Create(const JSCallbackInfo & info)214 void JSImage::Create(const JSCallbackInfo& info)
215 {
216     if (info.Length() < 1) {
217         return;
218     }
219 
220     auto container = Container::Current();
221     CHECK_NULL_VOID(container);
222     auto context = PipelineBase::GetCurrentContext();
223     CHECK_NULL_VOID(context);
224     bool isCard = context->IsFormRender() && !container->IsDynamicRender();
225 
226     // Interim programme
227     std::string bundleName;
228     std::string moduleName;
229     std::string src;
230     bool srcValid = ParseJsMedia(info[0], src);
231     int32_t resId = 0;
232     if (info[0]->IsObject()) {
233         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
234         JSRef<JSVal> tmp = jsObj->GetProperty("id");
235         if (!tmp->IsNull() && tmp->IsNumber()) {
236             resId = tmp->ToNumber<int32_t>();
237         }
238     }
239     if (isCard && info[0]->IsString()) {
240         SrcType srcType = ImageSourceInfo::ResolveURIType(src);
241         bool notSupport = (srcType == SrcType::NETWORK || srcType == SrcType::FILE || srcType == SrcType::DATA_ABILITY);
242         if (notSupport) {
243             src.clear();
244         }
245     }
246     GetJsMediaBundleInfo(info[0], bundleName, moduleName);
247     RefPtr<PixelMap> pixmap = nullptr;
248 
249     // input is PixelMap / Drawable
250     if (!srcValid) {
251 #if defined(PIXEL_MAP_SUPPORTED)
252         if (!isCard) {
253             if (IsDrawable(info[0])) {
254                 pixmap = GetDrawablePixmap(info[0]);
255             } else {
256                 pixmap = CreatePixelMapFromNapiValue(info[0]);
257             }
258         }
259 #endif
260     }
261 
262     ImageModel::GetInstance()->Create(src, pixmap, bundleName, moduleName, (resId == -1));
263 }
264 
IsDrawable(const JSRef<JSVal> & jsValue)265 bool JSImage::IsDrawable(const JSRef<JSVal>& jsValue)
266 {
267     if (!jsValue->IsObject()) {
268         return false;
269     }
270     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
271     if (jsObj->IsUndefined()) {
272         return false;
273     }
274 
275     // if jsObject has function getPixelMap, it's a DrawableDescriptor object
276     JSRef<JSVal> func = jsObj->GetProperty("getPixelMap");
277     return (!func->IsNull() && func->IsFunction());
278 }
279 
JsBorder(const JSCallbackInfo & info)280 void JSImage::JsBorder(const JSCallbackInfo& info)
281 {
282     JSViewAbstract::JsBorder(info);
283     ImageModel::GetInstance()->SetBackBorder();
284 }
285 
JsImageResizable(const JSCallbackInfo & info)286 void JSImage::JsImageResizable(const JSCallbackInfo& info)
287 {
288     auto infoObj = info[0];
289     ImageResizableSlice sliceResult;
290     if (!infoObj->IsObject()) {
291         ImageModel::GetInstance()->SetResizableSlice(sliceResult);
292         return;
293     }
294     JSRef<JSObject> resizableObject = JSRef<JSObject>::Cast(infoObj);
295     if (resizableObject->IsEmpty()) {
296         ImageModel::GetInstance()->SetResizableSlice(sliceResult);
297         return;
298     }
299     auto sliceValue = resizableObject->GetProperty("slice");
300     JSRef<JSObject> sliceObj = JSRef<JSObject>::Cast(sliceValue);
301     if (sliceObj->IsEmpty()) {
302         ImageModel::GetInstance()->SetResizableSlice(sliceResult);
303         return;
304     }
305     static std::array<std::string, 4> keys = { "left", "right", "top", "bottom" };
306     for (uint32_t i = 0; i < keys.size(); i++) {
307         auto sliceSize = sliceObj->GetProperty(keys.at(i).c_str());
308         CalcDimension sliceDimension;
309         if (!ParseJsDimensionVp(sliceSize, sliceDimension)) {
310             continue;
311         }
312         if (!sliceDimension.IsValid()) {
313             continue;
314         }
315         switch (static_cast<BorderImageDirection>(i)) {
316             case BorderImageDirection::LEFT:
317                 sliceResult.left = sliceDimension;
318                 break;
319             case BorderImageDirection::RIGHT:
320                 sliceResult.right = sliceDimension;
321                 break;
322             case BorderImageDirection::TOP:
323                 sliceResult.top = sliceDimension;
324                 break;
325             case BorderImageDirection::BOTTOM:
326                 sliceResult.bottom = sliceDimension;
327                 break;
328             default:
329                 break;
330         }
331     }
332     ImageModel::GetInstance()->SetResizableSlice(sliceResult);
333 }
334 
JsBorderRadius(const JSCallbackInfo & info)335 void JSImage::JsBorderRadius(const JSCallbackInfo& info)
336 {
337     JSViewAbstract::JsBorderRadius(info);
338     ImageModel::GetInstance()->SetBackBorder();
339 }
340 
SetSourceSize(const JSCallbackInfo & info)341 void JSImage::SetSourceSize(const JSCallbackInfo& info)
342 {
343     ImageModel::GetInstance()->SetImageSourceSize(JSViewAbstract::ParseSize(info));
344 }
345 
SetImageFill(const JSCallbackInfo & info)346 void JSImage::SetImageFill(const JSCallbackInfo& info)
347 {
348     if (info.Length() < 1) {
349         return;
350     }
351 
352     Color color;
353     if (!ParseJsColor(info[0], color)) {
354         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
355             return;
356         }
357         auto pipelineContext = PipelineBase::GetCurrentContext();
358         CHECK_NULL_VOID(pipelineContext);
359         auto theme = pipelineContext->GetTheme<ImageTheme>();
360         CHECK_NULL_VOID(theme);
361         color = theme->GetFillColor();
362     }
363     ImageModel::GetInstance()->SetImageFill(color);
364 }
365 
SetImageRenderMode(const JSCallbackInfo & info)366 void JSImage::SetImageRenderMode(const JSCallbackInfo& info)
367 {
368     if (info.Length() < 1) {
369         return;
370     }
371     auto jsImageRenderMode = info[0];
372     if (jsImageRenderMode->IsNumber()) {
373         auto renderMode = static_cast<ImageRenderMode>(jsImageRenderMode->ToNumber<int32_t>());
374         if (renderMode < ImageRenderMode::ORIGINAL || renderMode > ImageRenderMode::TEMPLATE) {
375             renderMode = ImageRenderMode::ORIGINAL;
376         }
377         ImageModel::GetInstance()->SetImageRenderMode(renderMode);
378     }
379 }
380 
SetImageInterpolation(int32_t imageInterpolation)381 void JSImage::SetImageInterpolation(int32_t imageInterpolation)
382 {
383     auto interpolation = static_cast<ImageInterpolation>(imageInterpolation);
384     if (interpolation < ImageInterpolation::NONE || interpolation > ImageInterpolation::HIGH) {
385         interpolation = ImageInterpolation::NONE;
386     }
387     ImageModel::GetInstance()->SetImageInterpolation(interpolation);
388 }
389 
SetImageRepeat(int32_t imageRepeat)390 void JSImage::SetImageRepeat(int32_t imageRepeat)
391 {
392     auto repeat = static_cast<ImageRepeat>(imageRepeat);
393     if (repeat < ImageRepeat::NO_REPEAT || repeat > ImageRepeat::REPEAT) {
394         repeat = ImageRepeat::NO_REPEAT;
395     }
396     ImageModel::GetInstance()->SetImageRepeat(repeat);
397 }
398 
JsTransition(const JSCallbackInfo & info)399 void JSImage::JsTransition(const JSCallbackInfo& info)
400 {
401     if (ImageModel::GetInstance()->IsSrcSvgImage()) {
402         JSViewAbstract::JsTransition(info);
403     } else {
404         JSViewAbstract::JsTransitionPassThrough(info);
405     }
406 }
407 
JsOpacity(const JSCallbackInfo & info)408 void JSImage::JsOpacity(const JSCallbackInfo& info)
409 {
410     if (ImageModel::GetInstance()->IsSrcSvgImage()) {
411         JSViewAbstract::JsOpacity(info);
412     } else {
413         JSViewAbstract::JsOpacityPassThrough(info);
414     }
415 }
416 
JsBlur(const JSCallbackInfo & info)417 void JSImage::JsBlur(const JSCallbackInfo& info)
418 {
419 // only flutter runs special image blur
420 #ifdef ENABLE_ROSEN_BACKEND
421     JSViewAbstract::JsBlur(info);
422 #else
423     if (info.Length() < 1) {
424         return;
425     }
426     double blur = 0.0;
427     if (ParseJsDouble(info[0], blur)) {
428         ImageModel::GetInstance()->SetBlur(blur);
429     }
430 #endif
431 }
432 
SetAutoResize(bool autoResize)433 void JSImage::SetAutoResize(bool autoResize)
434 {
435     ImageModel::GetInstance()->SetAutoResize(autoResize);
436 }
437 
SetSyncLoad(const JSCallbackInfo & info)438 void JSImage::SetSyncLoad(const JSCallbackInfo& info)
439 {
440     if (info.Length() < 1) {
441         return;
442     }
443     auto tmpInfo = info[0];
444     if (!tmpInfo->IsBoolean()) {
445         return;
446     }
447     ImageModel::GetInstance()->SetSyncMode(tmpInfo->ToBoolean());
448 }
449 
ConstructorCallback(const JSCallbackInfo & args)450 void JSColorFilter::ConstructorCallback(const JSCallbackInfo& args)
451 {
452     if (args.Length() < 1) {
453         return;
454     }
455     auto tmpInfo = args[0];
456     if (!tmpInfo->IsArray()) {
457         return;
458     }
459     JSRef<JSArray> array = JSRef<JSArray>::Cast(tmpInfo);
460     if (array->Length() != COLOR_FILTER_MATRIX_SIZE) {
461         return;
462     }
463     auto jscolorfilter = Referenced::MakeRefPtr<JSColorFilter>();
464     if (jscolorfilter == nullptr) {
465         return;
466     }
467     std::vector<float> colorfilter;
468     for (size_t i = 0; i < array->Length(); i++) {
469         JSRef<JSVal> value = array->GetValueAt(i);
470         if (value->IsNumber()) {
471             colorfilter.emplace_back(value->ToNumber<float>());
472         }
473     }
474     if (colorfilter.size() != COLOR_FILTER_MATRIX_SIZE) {
475         return;
476     }
477     jscolorfilter->SetColorFilterMatrix(std::move(colorfilter));
478     jscolorfilter->IncRefCount();
479     args.SetReturnValue(Referenced::RawPtr(jscolorfilter));
480 }
481 
DestructorCallback(JSColorFilter * obj)482 void JSColorFilter::DestructorCallback(JSColorFilter* obj)
483 {
484     if (obj != nullptr) {
485         obj->DecRefCount();
486     }
487 }
488 
SetColorFilter(const JSCallbackInfo & info)489 void JSImage::SetColorFilter(const JSCallbackInfo& info)
490 {
491     if (info.Length() != 1) {
492         ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
493         return;
494     }
495     auto tmpInfo = info[0];
496     if (!tmpInfo->IsArray() && !tmpInfo->IsObject()) {
497         ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
498         return;
499     }
500     if (tmpInfo->IsObject() && !tmpInfo->IsArray()) {
501         JSColorFilter* colorFilter;
502         if (!tmpInfo->IsUndefined() && !tmpInfo->IsNull()) {
503             colorFilter = JSRef<JSObject>::Cast(tmpInfo)->Unwrap<JSColorFilter>();
504         } else {
505             ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
506             return;
507         }
508         if (colorFilter && colorFilter->GetColorFilterMatrix().size() == COLOR_FILTER_MATRIX_SIZE) {
509             ImageModel::GetInstance()->SetColorFilterMatrix(colorFilter->GetColorFilterMatrix());
510             return;
511         }
512         ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
513         return;
514     }
515     JSRef<JSArray> array = JSRef<JSArray>::Cast(tmpInfo);
516     if (array->Length() != COLOR_FILTER_MATRIX_SIZE) {
517         ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
518         return;
519     }
520     std::vector<float> colorfilter;
521     for (size_t i = 0; i < array->Length(); i++) {
522         JSRef<JSVal> value = array->GetValueAt(i);
523         if (value->IsNumber()) {
524             colorfilter.emplace_back(value->ToNumber<float>());
525         } else {
526             ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
527             return;
528         }
529     }
530     ImageModel::GetInstance()->SetColorFilterMatrix(colorfilter);
531 }
532 
SetSmoothEdge(const JSCallbackInfo & info)533 void JSImage::SetSmoothEdge(const JSCallbackInfo& info)
534 {
535     if (info.Length() != 1) {
536         ImageModel::GetInstance()->SetSmoothEdge(DEFAULT_SMOOTHEDGE_VALUE);
537         return;
538     }
539     double parseRes = DEFAULT_SMOOTHEDGE_VALUE;
540     ParseJsDouble(info[0], parseRes);
541     // Effective range : (FLOOR_SMOOTHEDGE_VALUE, CEIL_SMOOTHEDGE_VALUE]
542     // otherwise: DEFAULT_SMOOTHEDGE_VALUE
543     if (GreatNotEqual(parseRes, CEIL_SMOOTHEDGE_VALUE) || LessNotEqual(parseRes, FLOOR_SMOOTHEDGE_VALUE)) {
544         parseRes = DEFAULT_SMOOTHEDGE_VALUE;
545     }
546     ImageModel::GetInstance()->SetSmoothEdge(static_cast<float>(parseRes));
547 }
548 
JSBind(BindingTarget globalObj)549 void JSImage::JSBind(BindingTarget globalObj)
550 {
551     JSClass<JSImage>::Declare("Image");
552     MethodOptions opt = MethodOptions::NONE;
553     JSClass<JSImage>::StaticMethod("create", &JSImage::Create, opt);
554     JSClass<JSImage>::StaticMethod("alt", &JSImage::SetAlt, opt);
555     JSClass<JSImage>::StaticMethod("objectFit", &JSImage::SetObjectFit, opt);
556     JSClass<JSImage>::StaticMethod("matchTextDirection", &JSImage::SetMatchTextDirection, opt);
557     JSClass<JSImage>::StaticMethod("fitOriginalSize", &JSImage::SetFitOriginalSize, opt);
558     JSClass<JSImage>::StaticMethod("sourceSize", &JSImage::SetSourceSize, opt);
559     JSClass<JSImage>::StaticMethod("fillColor", &JSImage::SetImageFill, opt);
560     JSClass<JSImage>::StaticMethod("renderMode", &JSImage::SetImageRenderMode, opt);
561     JSClass<JSImage>::StaticMethod("objectRepeat", &JSImage::SetImageRepeat, opt);
562     JSClass<JSImage>::StaticMethod("interpolation", &JSImage::SetImageInterpolation, opt);
563     JSClass<JSImage>::StaticMethod("colorFilter", &JSImage::SetColorFilter, opt);
564     JSClass<JSImage>::StaticMethod("edgeAntialiasing", &JSImage::SetSmoothEdge, opt);
565 
566     JSClass<JSImage>::StaticMethod("border", &JSImage::JsBorder);
567     JSClass<JSImage>::StaticMethod("borderRadius", &JSImage::JsBorderRadius);
568     JSClass<JSImage>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
569     JSClass<JSImage>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
570     JSClass<JSImage>::StaticMethod("autoResize", &JSImage::SetAutoResize);
571     JSClass<JSImage>::StaticMethod("resizable", &JSImage::JsImageResizable);
572 
573     JSClass<JSImage>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
574     JSClass<JSImage>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
575     JSClass<JSImage>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
576     JSClass<JSImage>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
577     JSClass<JSImage>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
578     JSClass<JSImage>::StaticMethod("onComplete", &JSImage::OnComplete);
579     JSClass<JSImage>::StaticMethod("onError", &JSImage::OnError);
580     JSClass<JSImage>::StaticMethod("onFinish", &JSImage::OnFinish);
581     JSClass<JSImage>::StaticMethod("syncLoad", &JSImage::SetSyncLoad);
582     JSClass<JSImage>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
583     JSClass<JSImage>::StaticMethod("draggable", &JSImage::JsSetDraggable);
584     JSClass<JSImage>::StaticMethod("onDragStart", &JSImage::JsOnDragStart);
585     JSClass<JSImage>::StaticMethod("copyOption", &JSImage::SetCopyOption);
586     JSClass<JSImage>::StaticMethod("enableAnalyzer", &JSImage::EnableAnalyzer);
587     JSClass<JSImage>::StaticMethod("analyzerConfig", &JSImage::AnalyzerConfig);
588 
589     // override method
590     JSClass<JSImage>::StaticMethod("opacity", &JSImage::JsOpacity);
591     JSClass<JSImage>::StaticMethod("blur", &JSImage::JsBlur);
592     JSClass<JSImage>::StaticMethod("transition", &JSImage::JsTransition);
593     JSClass<JSImage>::StaticMethod("pointLight", &JSViewAbstract::JsPointLight, opt);
594     JSClass<JSImage>::InheritAndBind<JSViewAbstract>(globalObj);
595 
596     JSClass<JSColorFilter>::Declare("ColorFilter");
597     JSClass<JSColorFilter>::Bind(globalObj, JSColorFilter::ConstructorCallback, JSColorFilter::DestructorCallback);
598 }
599 
JsSetDraggable(bool draggable)600 void JSImage::JsSetDraggable(bool draggable)
601 {
602     ImageModel::GetInstance()->SetDraggable(draggable);
603 }
604 
JsOnDragStart(const JSCallbackInfo & info)605 void JSImage::JsOnDragStart(const JSCallbackInfo& info)
606 {
607     if (info.Length() != 1 || !info[0]->IsFunction()) {
608         return;
609     }
610     RefPtr<JsDragFunction> jsOnDragStartFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
611     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
612     auto onDragStartId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragStartFunc), node = frameNode](
613                              const RefPtr<DragEvent>& info, const std::string& extraParams) -> NG::DragDropBaseInfo {
614         NG::DragDropBaseInfo itemInfo;
615         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, itemInfo);
616         PipelineContext::SetCallBackNode(node);
617         auto ret = func->Execute(info, extraParams);
618         if (!ret->IsObject()) {
619             return itemInfo;
620         }
621         if (ParseAndUpdateDragItemInfo(ret, itemInfo)) {
622             return itemInfo;
623         }
624 
625         auto builderObj = JSRef<JSObject>::Cast(ret);
626 #if defined(PIXEL_MAP_SUPPORTED)
627         auto pixmap = builderObj->GetProperty("pixelMap");
628         itemInfo.pixelMap = CreatePixelMapFromNapiValue(pixmap);
629 #endif
630         auto extraInfo = builderObj->GetProperty("extraInfo");
631         ParseJsString(extraInfo, itemInfo.extraInfo);
632         ParseAndUpdateDragItemInfo(builderObj->GetProperty("builder"), itemInfo);
633         return itemInfo;
634     };
635     ImageModel::GetInstance()->SetOnDragStart(std::move(onDragStartId));
636 }
637 
SetCopyOption(const JSCallbackInfo & info)638 void JSImage::SetCopyOption(const JSCallbackInfo& info)
639 {
640     auto copyOptions = CopyOptions::None;
641     if (info[0]->IsNumber()) {
642         auto enumNumber = info[0]->ToNumber<int>();
643         copyOptions = static_cast<CopyOptions>(enumNumber);
644         if (copyOptions < CopyOptions::None || copyOptions > CopyOptions::Distributed) {
645             copyOptions = CopyOptions::None;
646         }
647     }
648     ImageModel::GetInstance()->SetCopyOption(copyOptions);
649 }
650 
EnableAnalyzer(bool isEnableAnalyzer)651 void JSImage::EnableAnalyzer(bool isEnableAnalyzer)
652 {
653     ImageModel::GetInstance()->EnableAnalyzer(isEnableAnalyzer);
654 }
655 
AnalyzerConfig(const JSCallbackInfo & info)656 void JSImage::AnalyzerConfig(const JSCallbackInfo &info)
657 {
658     auto configParams = info[0];
659     if (configParams->IsNull() || !configParams->IsObject()) {
660         return;
661     }
662 
663     auto paramObject = JSRef<JSObject>::Cast(configParams);
664     JSRef<JSVal> typeVal = paramObject->GetProperty("types");
665     JSRef<JSVal> showButtonVal = paramObject->GetProperty("showAIButton");
666     JSRef<JSVal> marginVal = paramObject->GetProperty("aiButtonOffset");
667     JSRef<JSVal> textOpVal = paramObject->GetProperty("textOptions");
668     JSRef<JSVal> subjectOpVal = paramObject->GetProperty("subjectOptions");
669     JSRef<JSVal> tagVal = paramObject->GetProperty("tag");
670 
671     ImageAnalyzerConfig analyzerConfig;
672     if (typeVal->IsArray()) {
673         auto array = JSRef<JSArray>::Cast(typeVal);
674         std::set<ImageAnalyzerType> types;
675         for (size_t i = 0; i < array->Length(); ++i) {
676             if (!array->GetValueAt(i)->IsNumber()) {
677                 continue;
678             }
679             int value = array->GetValueAt(i)->ToNumber<int>();
680             ImageAnalyzerType type = static_cast<ImageAnalyzerType>(value);
681             if (type != ImageAnalyzerType::SUBJECT && type != ImageAnalyzerType::TEXT) {
682                 continue;
683             }
684             types.insert(type);
685         }
686         analyzerConfig.types = std::move(types);
687     }
688     if (showButtonVal->IsBoolean()) {
689         analyzerConfig.isShowAIButton = showButtonVal->ToBoolean();
690     }
691     if (!marginVal->IsNull() && marginVal->IsObject()) {
692         auto marginValue = JSRef<JSObject>::Cast(marginVal);
693         std::optional<CalcDimension> top;
694         std::optional<CalcDimension> bottom;
695         std::optional<CalcDimension> left;
696         std::optional<CalcDimension> right;
697         ParseMarginOrPaddingCorner(marginValue, top, bottom, left, right);
698         analyzerConfig.aiButtonMargin = NG::ConvertToCalcPaddingProperty(top, bottom, left, right);
699     }
700     if (subjectOpVal->IsObject()) {
701         ParseImageAnalyzerSubjectOptions(subjectOpVal, analyzerConfig);
702     }
703     if (textOpVal->IsObject()) {
704         ParseImageAnalyzerTextOptions(textOpVal, analyzerConfig);
705     }
706     if (tagVal->IsString()) {
707         analyzerConfig.tag = tagVal->ToString();
708     }
709     ImageModel::GetInstance()->SetImageAnalyzerConfig(analyzerConfig);
710 }
711 
712 } // namespace OHOS::Ace::Framework
713