1 /*
2 * Copyright (c) 2021-2024 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.h"
17
18 #include <cstdint>
19 #include <memory>
20 #include <vector>
21 #if !defined(PREVIEW)
22 #include <dlfcn.h>
23 #endif
24
25 #include "interfaces/inner_api/ace/ai/image_analyzer.h"
26 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
27 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
28 #endif
29
30 #include "base/geometry/ng/vector.h"
31 #include "base/image/drawing_color_filter.h"
32 #include "base/image/drawing_lattice.h"
33 #include "base/image/pixel_map.h"
34 #include "base/log/ace_scoring_log.h"
35 #include "base/log/ace_trace.h"
36 #include "base/utils/utils.h"
37 #include "bridge/common/utils/engine_helper.h"
38 #include "bridge/declarative_frontend/engine/functions/js_drag_function.h"
39 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
40 #include "bridge/declarative_frontend/engine/js_types.h"
41 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
42 #include "bridge/declarative_frontend/jsview/models/image_model_impl.h"
43 #include "core/common/container.h"
44 #include "core/components/common/layout/constants.h"
45 #include "core/components/image/image_event.h"
46 #include "core/components/image/image_theme.h"
47 #include "core/components_ng/base/view_abstract_model.h"
48 #include "core/components_ng/base/view_stack_processor.h"
49 #include "core/components_ng/event/gesture_event_hub.h"
50 #include "core/components_ng/pattern/image/image_model.h"
51 #include "core/components_ng/pattern/image/image_model_ng.h"
52 #include "core/image/image_source_info.h"
53
54 namespace {
55 const std::vector<float> DEFAULT_COLORFILTER_MATRIX = { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 };
56 constexpr float CEIL_SMOOTHEDGE_VALUE = 1.333f;
57 constexpr float FLOOR_SMOOTHEDGE_VALUE = 0.334f;
58 constexpr float DEFAULT_SMOOTHEDGE_VALUE = 0.0f;
59 constexpr uint32_t FIT_MATRIX = 16;
60 } // namespace
61
62 namespace OHOS::Ace {
63
64 namespace {
CreateSourceInfo(const std::shared_ptr<std::string> & srcRef,RefPtr<PixelMap> & pixmap,const std::string & bundleName,const std::string & moduleName)65 ImageSourceInfo CreateSourceInfo(const std::shared_ptr<std::string>& srcRef, RefPtr<PixelMap>& pixmap,
66 const std::string& bundleName, const std::string& moduleName)
67 {
68 #if defined(PIXEL_MAP_SUPPORTED)
69 if (pixmap) {
70 return ImageSourceInfo(pixmap);
71 }
72 #endif
73 return { srcRef, bundleName, moduleName };
74 }
75 } // namespace
76
77 std::unique_ptr<ImageModel> ImageModel::instance_ = nullptr;
78 std::mutex ImageModel::mutex_;
79
GetInstance()80 ImageModel* __attribute__((optnone)) ImageModel::GetInstance()
81 {
82 if (!instance_) {
83 std::lock_guard<std::mutex> lock(mutex_);
84 if (!instance_) {
85 #ifdef NG_BUILD
86 instance_.reset(new NG::ImageModelNG());
87 #else
88 if (Container::IsCurrentUseNewPipeline()) {
89 instance_.reset(new NG::ImageModelNG());
90 } else {
91 instance_.reset(new Framework::ImageModelImpl());
92 }
93 #endif
94 }
95 }
96 return instance_.get();
97 }
98
99 } // namespace OHOS::Ace
100
101 namespace OHOS::Ace::Framework {
102
LoadImageSuccEventToJSValue(const LoadImageSuccessEvent & eventInfo)103 JSRef<JSVal> LoadImageSuccEventToJSValue(const LoadImageSuccessEvent& eventInfo)
104 {
105 JSRef<JSObject> obj = JSRef<JSObject>::New();
106 obj->SetProperty("width", eventInfo.GetWidth());
107 obj->SetProperty("height", eventInfo.GetHeight());
108 obj->SetProperty("componentWidth", eventInfo.GetComponentWidth());
109 obj->SetProperty("componentHeight", eventInfo.GetComponentHeight());
110 obj->SetProperty("loadingStatus", eventInfo.GetLoadingStatus());
111 obj->SetProperty("contentWidth", eventInfo.GetContentWidth());
112 obj->SetProperty("contentHeight", eventInfo.GetContentHeight());
113 obj->SetProperty("contentOffsetX", eventInfo.GetContentOffsetX());
114 obj->SetProperty("contentOffsetY", eventInfo.GetContentOffsetY());
115 return JSRef<JSVal>::Cast(obj);
116 }
117
LoadImageFailEventToJSValue(const LoadImageFailEvent & eventInfo)118 JSRef<JSVal> LoadImageFailEventToJSValue(const LoadImageFailEvent& eventInfo)
119 {
120 JSRef<JSObject> obj = JSRef<JSObject>::New();
121 obj->SetProperty("componentWidth", eventInfo.GetComponentWidth());
122 obj->SetProperty("componentHeight", eventInfo.GetComponentHeight());
123 obj->SetProperty("message", eventInfo.GetErrorMessage());
124 return JSRef<JSVal>::Cast(obj);
125 }
126
SetAlt(const JSCallbackInfo & args)127 void JSImage::SetAlt(const JSCallbackInfo& args)
128 {
129 if (ImageModel::GetInstance()->GetIsAnimation()) {
130 return;
131 }
132 if (args.Length() < 1) {
133 return;
134 }
135
136 auto context = PipelineBase::GetCurrentContext();
137 CHECK_NULL_VOID(context);
138 bool isCard = context->IsFormRender();
139
140 std::string src;
141 bool srcValid = false;
142 if (args[0]->IsString()) {
143 src = args[0]->ToString();
144 } else {
145 srcValid = ParseJsMedia(args[0], src);
146 }
147 if (ImageSourceInfo::ResolveURIType(src) == SrcType::NETWORK) {
148 return;
149 }
150 int32_t resId = 0;
151 if (args[0]->IsObject()) {
152 JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(args[0]);
153 JSRef<JSVal> tmp = jsObj->GetProperty("id");
154 if (!tmp->IsNull() && tmp->IsNumber()) {
155 resId = tmp->ToNumber<int32_t>();
156 }
157 }
158 std::string bundleName;
159 std::string moduleName;
160 GetJsMediaBundleInfo(args[0], bundleName, moduleName);
161 RefPtr<PixelMap> pixmap = nullptr;
162
163 // input is Drawable
164 if (!srcValid && !isCard) {
165 #if defined(PIXEL_MAP_SUPPORTED)
166 pixmap = CreatePixelMapFromNapiValue(args[0]);
167 #endif
168 }
169 auto srcRef = std::make_shared<std::string>(src);
170 auto srcInfo = CreateSourceInfo(srcRef, pixmap, bundleName, moduleName);
171 srcInfo.SetIsUriPureNumber((resId == -1));
172 ImageModel::GetInstance()->SetAlt(srcInfo);
173 }
174
SetObjectFit(const JSCallbackInfo & args)175 void JSImage::SetObjectFit(const JSCallbackInfo& args)
176 {
177 if (args.Length() < 1) {
178 ImageModel::GetInstance()->SetImageFit(ImageFit::COVER);
179 return;
180 }
181 int32_t parseRes = static_cast<int32_t>(ImageFit::COVER);
182 ParseJsInteger(args[0], parseRes);
183 if (parseRes < static_cast<int32_t>(ImageFit::FILL) || parseRes > static_cast<int32_t>(ImageFit::MATRIX)) {
184 parseRes = static_cast<int32_t>(ImageFit::COVER);
185 }
186 auto fit = static_cast<ImageFit>(parseRes);
187 if (parseRes == FIT_MATRIX) {
188 fit = ImageFit::MATRIX;
189 }
190 ImageModel::GetInstance()->SetImageFit(fit);
191 }
192
SetImageMatrix(const JSCallbackInfo & args)193 void JSImage::SetImageMatrix(const JSCallbackInfo& args)
194 {
195 if (args.Length() > 0) {
196 auto jsVal = args[0];
197 if (!jsVal->IsObject()) {
198 SetDefaultImageMatrix();
199 return;
200 }
201 JSRef<JSVal> array = JSRef<JSObject>::Cast(jsVal)->GetProperty(static_cast<int32_t>(ArkUIIndex::MATRIX4X4));
202 const auto matrix4Len = Matrix4::DIMENSION * Matrix4::DIMENSION;
203 if (!array->IsArray()) {
204 return;
205 }
206 JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(array);
207 if (jsArray->Length() != matrix4Len) {
208 return;
209 }
210 std::vector<float> matrix(matrix4Len);
211 for (int32_t i = 0; i < matrix4Len; i++) {
212 double value = 0.0;
213 ParseJsDouble(jsArray->GetValueAt(i), value);
214 matrix[i] = static_cast<float>(value);
215 }
216 Matrix4 setValue = Matrix4(
217 matrix[0], matrix[4], matrix[8], matrix[12],
218 matrix[1], matrix[5], matrix[9], matrix[13],
219 matrix[2], matrix[6], matrix[10], matrix[14],
220 matrix[3], matrix[7], matrix[11], matrix[15]);
221 ImageModel::GetInstance()->SetImageMatrix(setValue);
222 } else {
223 SetDefaultImageMatrix();
224 return;
225 }
226 }
227
SetDefaultImageMatrix()228 void JSImage::SetDefaultImageMatrix()
229 {
230 const auto matrix4Len = Matrix4::DIMENSION * Matrix4::DIMENSION;
231 std::vector<float> matrix(matrix4Len);
232 const int32_t initPosition = 5;
233 for (int32_t i = 0; i < matrix4Len; i = i + initPosition) {
234 matrix[i] = 1.0f;
235 }
236 Matrix4 setValue = Matrix4(
237 matrix[0], matrix[4], matrix[8], matrix[12],
238 matrix[1], matrix[5], matrix[9], matrix[13],
239 matrix[2], matrix[6], matrix[10], matrix[14],
240 matrix[3], matrix[7], matrix[11], matrix[15]);
241 ImageModel::GetInstance()->SetImageMatrix(setValue);
242 }
243
SetMatchTextDirection(bool value)244 void JSImage::SetMatchTextDirection(bool value)
245 {
246 if (ImageModel::GetInstance()->GetIsAnimation()) {
247 return;
248 }
249 ImageModel::GetInstance()->SetMatchTextDirection(value);
250 }
251
SetFitOriginalSize(bool value)252 void JSImage::SetFitOriginalSize(bool value)
253 {
254 if (ImageModel::GetInstance()->GetIsAnimation()) {
255 return;
256 }
257 ImageModel::GetInstance()->SetFitOriginSize(value);
258 }
259
SetBorder(const Border & border)260 void JSImage::SetBorder(const Border& border)
261 {
262 ImageModel::GetInstance()->SetBorder(border);
263 }
264
OnComplete(const JSCallbackInfo & args)265 void JSImage::OnComplete(const JSCallbackInfo& args)
266 {
267 if (args[0]->IsFunction()) {
268 auto jsLoadSuccFunc = AceType::MakeRefPtr<JsEventFunction<LoadImageSuccessEvent, 1>>(
269 JSRef<JSFunc>::Cast(args[0]), LoadImageSuccEventToJSValue);
270
271 auto onComplete = [execCtx = args.GetExecutionContext(), func = std::move(jsLoadSuccFunc)](
272 const LoadImageSuccessEvent& info) {
273 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
274 ACE_SCORING_EVENT("Image.onComplete");
275 func->Execute(info);
276 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
277 UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "Image.onComplete");
278 #endif
279 };
280 ImageModel::GetInstance()->SetOnComplete(std::move(onComplete));
281 }
282 }
283
OnError(const JSCallbackInfo & args)284 void JSImage::OnError(const JSCallbackInfo& args)
285 {
286 if (args[0]->IsFunction()) {
287 auto jsLoadFailFunc = AceType::MakeRefPtr<JsEventFunction<LoadImageFailEvent, 1>>(
288 JSRef<JSFunc>::Cast(args[0]), LoadImageFailEventToJSValue);
289 auto onError = [execCtx = args.GetExecutionContext(), func = std::move(jsLoadFailFunc)](
290 const LoadImageFailEvent& info) {
291 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
292 ACE_SCORING_EVENT("Image.onError");
293 func->Execute(info);
294 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
295 UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "Image.onError");
296 #endif
297 };
298
299 ImageModel::GetInstance()->SetOnError(onError);
300 }
301 }
302
OnFinish(const JSCallbackInfo & info)303 void JSImage::OnFinish(const JSCallbackInfo& info)
304 {
305 auto tmpInfo = info[0];
306 if (!tmpInfo->IsFunction()) {
307 return;
308 }
309 RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(tmpInfo));
310 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
311 auto onFinish = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
312 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
313 ACE_SCORING_EVENT("Image.onFinish");
314 PipelineContext::SetCallBackNode(node);
315 func->Execute();
316 };
317 ImageModel::GetInstance()->SetSvgAnimatorFinishEvent(onFinish);
318 }
319
Create(const JSCallbackInfo & info)320 void JSImage::Create(const JSCallbackInfo& info)
321 {
322 if (info.Length() < 1) {
323 return;
324 }
325 CreateImage(info);
326 }
327
CheckIsCard()328 bool JSImage::CheckIsCard()
329 {
330 auto container = Container::Current();
331 if (!container) {
332 TAG_LOGE(AceLogTag::ACE_IMAGE, "Container is null in CreateImage.");
333 return false;
334 }
335 return container->IsFormRender() && !container->IsDynamicRender();
336 }
337
CheckResetImage(const JSCallbackInfo & info)338 bool JSImage::CheckResetImage(const JSCallbackInfo& info)
339 {
340 int32_t parseRes = -1;
341 if (info.Length() < 1 || !ParseJsInteger(info[0], parseRes)) {
342 return false;
343 }
344 ImageModel::GetInstance()->ResetImage();
345 return true;
346 }
347
CreateImage(const JSCallbackInfo & info,bool isImageSpan)348 void JSImage::CreateImage(const JSCallbackInfo& info, bool isImageSpan)
349 {
350 if (CheckResetImage(info)) {
351 return;
352 }
353 bool isCard = CheckIsCard();
354
355 // Interim programme
356 std::string bundleName;
357 std::string moduleName;
358 std::string src;
359 auto imageInfo = info[0];
360 int32_t resId = 0;
361 bool srcValid = ParseJsMediaWithBundleName(imageInfo, src, bundleName, moduleName, resId);
362 if (isCard && imageInfo->IsString()) {
363 SrcType srcType = ImageSourceInfo::ResolveURIType(src);
364 bool notSupport = (srcType == SrcType::NETWORK || srcType == SrcType::FILE || srcType == SrcType::DATA_ABILITY);
365 if (notSupport) {
366 src.clear();
367 }
368 }
369 RefPtr<PixelMap> pixmap = nullptr;
370
371 // input is PixelMap / Drawable
372 if (!srcValid && !isCard) {
373 #if defined(PIXEL_MAP_SUPPORTED)
374 std::vector<RefPtr<PixelMap>> pixelMaps;
375 int32_t duration = -1;
376 int32_t iterations = 1;
377 if (IsDrawable(imageInfo)) {
378 if (GetPixelMapListFromAnimatedDrawable(imageInfo, pixelMaps, duration, iterations)) {
379 CreateImageAnimation(pixelMaps, duration, iterations);
380 return;
381 }
382 pixmap = GetDrawablePixmap(imageInfo);
383 } else {
384 pixmap = CreatePixelMapFromNapiValue(imageInfo);
385 }
386 #endif
387 }
388 ImageInfoConfig imageInfoConfig(
389 std::make_shared<std::string>(src), bundleName, moduleName, (resId == -1), isImageSpan);
390 ImageModel::GetInstance()->Create(imageInfoConfig, pixmap);
391
392 if (info.Length() > 1) {
393 ParseImageAIOptions(info[1]);
394 }
395 }
396
ParseImageAIOptions(const JSRef<JSVal> & jsValue)397 void JSImage::ParseImageAIOptions(const JSRef<JSVal>& jsValue)
398 {
399 if (!jsValue->IsObject()) {
400 return;
401 }
402 auto engine = EngineHelper::GetCurrentEngine();
403 CHECK_NULL_VOID(engine);
404 NativeEngine* nativeEngine = engine->GetNativeEngine();
405 panda::Local<JsiValue> value = jsValue.Get().GetLocalHandle();
406 JSValueWrapper valueWrapper = value;
407 ScopeRAII scope(reinterpret_cast<napi_env>(nativeEngine));
408 napi_value optionsValue = nativeEngine->ValueToNapiValue(valueWrapper);
409 ImageModel::GetInstance()->SetImageAIOptions(optionsValue);
410 }
411
IsDrawable(const JSRef<JSVal> & jsValue)412 bool JSImage::IsDrawable(const JSRef<JSVal>& jsValue)
413 {
414 if (!jsValue->IsObject()) {
415 return false;
416 }
417 JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
418 if (jsObj->IsUndefined()) {
419 return false;
420 }
421
422 // if jsObject has function getPixelMap, it's a DrawableDescriptor object
423 JSRef<JSVal> func = jsObj->GetProperty("getPixelMap");
424 return (!func->IsNull() && func->IsFunction());
425 }
426
JsBorder(const JSCallbackInfo & info)427 void JSImage::JsBorder(const JSCallbackInfo& info)
428 {
429 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_FOURTEEN)) {
430 JSViewAbstract::JsBorder(info);
431 ImageModel::GetInstance()->SetBackBorder();
432 return;
433 }
434 // handles generic property logic.
435 JSViewAbstract::JsBorder(info);
436 // handles the image component separately, aiming to extract and set the borderRadius property
437 if (!info[0]->IsObject()) {
438 CalcDimension borderRadius;
439 ImageModel::GetInstance()->SetBorderRadius(borderRadius);
440 return;
441 }
442 JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
443
444 auto valueRadius = object->GetProperty(static_cast<int32_t>(ArkUIIndex::RADIUS));
445 if (!valueRadius->IsUndefined()) {
446 ParseBorderRadius(valueRadius);
447 }
448 }
449
ParseBorderRadius(const JSRef<JSVal> & args)450 void JSImage::ParseBorderRadius(const JSRef<JSVal>& args)
451 {
452 CalcDimension borderRadius;
453 if (ParseJsDimensionVp(args, borderRadius)) {
454 ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius);
455 ImageModel::GetInstance()->SetBorderRadius(borderRadius);
456 } else if (args->IsObject()) {
457 JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
458 CalcDimension topLeft;
459 CalcDimension topRight;
460 CalcDimension bottomLeft;
461 CalcDimension bottomRight;
462 if (ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight)) {
463 ImageModel::GetInstance()->SetBorderRadius(
464 GetLocalizedBorderRadius(topLeft, topRight, bottomLeft, bottomRight));
465 ViewAbstractModel::GetInstance()->SetBorderRadius(
466 GetLocalizedBorderRadius(topLeft, topRight, bottomLeft, bottomRight));
467 return;
468 }
469 ImageModel::GetInstance()->SetBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
470 ViewAbstractModel::GetInstance()->SetBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
471 }
472 }
473
ParseResizableSlice(const JSRef<JSObject> & resizableObject)474 void JSImage::ParseResizableSlice(const JSRef<JSObject>& resizableObject)
475 {
476 ImageResizableSlice sliceResult;
477 if (resizableObject->IsEmpty()) {
478 ImageModel::GetInstance()->SetResizableSlice(sliceResult);
479 return;
480 }
481 auto sliceValue = resizableObject->GetProperty("slice");
482 if (!sliceValue->IsObject()) {
483 ImageModel::GetInstance()->SetResizableSlice(sliceResult);
484 return;
485 }
486 JSRef<JSObject> sliceObj = JSRef<JSObject>::Cast(sliceValue);
487 if (sliceObj->IsEmpty()) {
488 ImageModel::GetInstance()->SetResizableSlice(sliceResult);
489 return;
490 }
491 UpdateSliceResult(sliceObj, sliceResult);
492
493 ImageModel::GetInstance()->SetResizableSlice(sliceResult);
494 }
495
ParseResizableLattice(const JSRef<JSObject> & resizableObject)496 void JSImage::ParseResizableLattice(const JSRef<JSObject>& resizableObject)
497 {
498 auto latticeValue = resizableObject->GetProperty("lattice");
499 if (latticeValue->IsUndefined() || latticeValue->IsNull()) {
500 ImageModel::GetInstance()->ResetResizableLattice();
501 }
502 CHECK_NULL_VOID(latticeValue->IsObject());
503 auto drawingLattice = CreateDrawingLattice(latticeValue);
504 if (drawingLattice) {
505 ImageModel::GetInstance()->SetResizableLattice(drawingLattice);
506 } else {
507 ImageModel::GetInstance()->ResetResizableLattice();
508 }
509 }
510
JsImageResizable(const JSCallbackInfo & info)511 void JSImage::JsImageResizable(const JSCallbackInfo& info)
512 {
513 if (ImageModel::GetInstance()->GetIsAnimation()) {
514 return;
515 }
516 auto infoObj = info[0];
517 if (!infoObj->IsObject()) {
518 ImageModel::GetInstance()->SetResizableSlice(ImageResizableSlice());
519 return;
520 }
521 JSRef<JSObject> resizableObject = JSRef<JSObject>::Cast(infoObj);
522 ParseResizableSlice(resizableObject);
523 ParseResizableLattice(resizableObject);
524 }
525
UpdateSliceResult(const JSRef<JSObject> & sliceObj,ImageResizableSlice & sliceResult)526 void JSImage::UpdateSliceResult(const JSRef<JSObject>& sliceObj, ImageResizableSlice& sliceResult)
527 {
528 // creatge a array has 4 elements for paresing sliceSize
529 static std::array<int32_t, 4> keys = { static_cast<int32_t>(ArkUIIndex::LEFT),
530 static_cast<int32_t>(ArkUIIndex::RIGHT), static_cast<int32_t>(ArkUIIndex::TOP),
531 static_cast<int32_t>(ArkUIIndex::BOTTOM) };
532 for (uint32_t i = 0; i < keys.size(); i++) {
533 auto sliceSize = sliceObj->GetProperty(keys.at(i));
534 CalcDimension sliceDimension;
535 if (!ParseJsDimensionVp(sliceSize, sliceDimension)) {
536 continue;
537 }
538 if (!sliceDimension.IsValid()) {
539 continue;
540 }
541 switch (static_cast<BorderImageDirection>(i)) {
542 case BorderImageDirection::LEFT:
543 sliceResult.left = sliceDimension;
544 break;
545 case BorderImageDirection::RIGHT:
546 sliceResult.right = sliceDimension;
547 break;
548 case BorderImageDirection::TOP:
549 sliceResult.top = sliceDimension;
550 break;
551 case BorderImageDirection::BOTTOM:
552 sliceResult.bottom = sliceDimension;
553 break;
554 default:
555 break;
556 }
557 }
558 ImageModel::GetInstance()->SetResizableSlice(sliceResult);
559 }
560
JsBorderRadius(const JSCallbackInfo & info)561 void JSImage::JsBorderRadius(const JSCallbackInfo& info)
562 {
563 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_FOURTEEN)) {
564 JSViewAbstract::JsBorderRadius(info);
565 ImageModel::GetInstance()->SetBackBorder();
566 return;
567 }
568 static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
569 JSCallbackInfoType::OBJECT };
570 auto jsVal = info[0];
571 if (!CheckJSCallbackInfo("JsBorderRadius", jsVal, checkList)) {
572 ViewAbstractModel::GetInstance()->SetBorderRadius(Dimension {});
573 ImageModel::GetInstance()->SetBorderRadius(Dimension {});
574 return;
575 }
576 ParseBorderRadius(jsVal);
577 }
578
SetSourceSize(const JSCallbackInfo & info)579 void JSImage::SetSourceSize(const JSCallbackInfo& info)
580 {
581 if (ImageModel::GetInstance()->GetIsAnimation()) {
582 return;
583 }
584 ImageModel::GetInstance()->SetImageSourceSize(JSViewAbstract::ParseSize(info));
585 }
586
ParseColorContent(const JSRef<JSVal> & jsValue)587 bool JSImage::ParseColorContent(const JSRef<JSVal>& jsValue)
588 {
589 if (jsValue.IsEmpty() || jsValue->IsNull() || !jsValue->IsObject()) {
590 return false;
591 }
592 auto paramObject = JSRef<JSObject>::Cast(jsValue);
593 JSRef<JSVal> typeVal = paramObject->GetProperty("colorContent_");
594 return !typeVal.IsEmpty() && typeVal->IsString() && typeVal->ToString() == "ORIGIN";
595 }
596
SetImageFill(const JSCallbackInfo & info)597 void JSImage::SetImageFill(const JSCallbackInfo& info)
598 {
599 if (ImageModel::GetInstance()->GetIsAnimation()) {
600 return;
601 }
602 if (info.Length() < 1) {
603 return;
604 }
605
606 Color color;
607 if (!ParseJsColor(info[0], color)) {
608 if (ParseColorContent(info[0])) {
609 ImageModel::GetInstance()->ResetImageFill();
610 return;
611 }
612 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
613 return;
614 }
615 auto pipelineContext = PipelineBase::GetCurrentContext();
616 CHECK_NULL_VOID(pipelineContext);
617 auto theme = pipelineContext->GetTheme<ImageTheme>();
618 CHECK_NULL_VOID(theme);
619 color = theme->GetFillColor();
620 }
621 ImageModel::GetInstance()->SetImageFill(color);
622 }
623
SetImageRenderMode(const JSCallbackInfo & info)624 void JSImage::SetImageRenderMode(const JSCallbackInfo& info)
625 {
626 if (ImageModel::GetInstance()->GetIsAnimation()) {
627 return;
628 }
629 if (info.Length() < 1) {
630 ImageModel::GetInstance()->SetImageRenderMode(ImageRenderMode::ORIGINAL);
631 return;
632 }
633 auto jsImageRenderMode = info[0];
634 if (jsImageRenderMode->IsNumber()) {
635 auto renderMode = static_cast<ImageRenderMode>(jsImageRenderMode->ToNumber<int32_t>());
636 if (renderMode < ImageRenderMode::ORIGINAL || renderMode > ImageRenderMode::TEMPLATE) {
637 renderMode = ImageRenderMode::ORIGINAL;
638 }
639 ImageModel::GetInstance()->SetImageRenderMode(renderMode);
640 } else {
641 ImageModel::GetInstance()->SetImageRenderMode(ImageRenderMode::ORIGINAL);
642 }
643 }
644
SetImageInterpolation(int32_t imageInterpolation)645 void JSImage::SetImageInterpolation(int32_t imageInterpolation)
646 {
647 if (ImageModel::GetInstance()->GetIsAnimation()) {
648 return;
649 }
650 auto interpolation = static_cast<ImageInterpolation>(imageInterpolation);
651 if (interpolation < ImageInterpolation::NONE || interpolation > ImageInterpolation::HIGH) {
652 interpolation = ImageInterpolation::NONE;
653 }
654 ImageModel::GetInstance()->SetImageInterpolation(interpolation);
655 }
656
SetImageRepeat(int32_t imageRepeat)657 void JSImage::SetImageRepeat(int32_t imageRepeat)
658 {
659 auto repeat = static_cast<ImageRepeat>(imageRepeat);
660 if (repeat < ImageRepeat::NO_REPEAT || repeat > ImageRepeat::REPEAT) {
661 repeat = ImageRepeat::NO_REPEAT;
662 }
663 ImageModel::GetInstance()->SetImageRepeat(repeat);
664 }
665
JsTransition(const JSCallbackInfo & info)666 void JSImage::JsTransition(const JSCallbackInfo& info)
667 {
668 if (ImageModel::GetInstance()->IsSrcSvgImage()) {
669 JSViewAbstract::JsTransition(info);
670 } else {
671 JSViewAbstract::JsTransitionPassThrough(info);
672 }
673 }
674
JsOpacity(const JSCallbackInfo & info)675 void JSImage::JsOpacity(const JSCallbackInfo& info)
676 {
677 if (ImageModel::GetInstance()->IsSrcSvgImage()) {
678 JSViewAbstract::JsOpacity(info);
679 } else {
680 JSViewAbstract::JsOpacityPassThrough(info);
681 }
682 }
683
JsBlur(const JSCallbackInfo & info)684 void JSImage::JsBlur(const JSCallbackInfo& info)
685 {
686 // only flutter runs special image blur
687 #ifdef ENABLE_ROSEN_BACKEND
688 JSViewAbstract::JsBlur(info);
689 #else
690 if (info.Length() < 1) {
691 return;
692 }
693 double blur = 0.0;
694 if (ParseJsDouble(info[0], blur)) {
695 ImageModel::GetInstance()->SetBlur(blur);
696 }
697 #endif
698 }
699
SetAutoResize(bool autoResize)700 void JSImage::SetAutoResize(bool autoResize)
701 {
702 if (ImageModel::GetInstance()->GetIsAnimation()) {
703 return;
704 }
705 ImageModel::GetInstance()->SetAutoResize(autoResize);
706 }
707
SetSyncLoad(const JSCallbackInfo & info)708 void JSImage::SetSyncLoad(const JSCallbackInfo& info)
709 {
710 if (ImageModel::GetInstance()->GetIsAnimation()) {
711 return;
712 }
713 if (info.Length() < 1) {
714 return;
715 }
716 auto tmpInfo = info[0];
717 if (!tmpInfo->IsBoolean()) {
718 return;
719 }
720 ImageModel::GetInstance()->SetSyncMode(tmpInfo->ToBoolean());
721 }
722
ConstructorCallback(const JSCallbackInfo & args)723 void JSColorFilter::ConstructorCallback(const JSCallbackInfo& args)
724 {
725 if (args.Length() < 1) {
726 return;
727 }
728 auto tmpInfo = args[0];
729 if (!tmpInfo->IsArray()) {
730 return;
731 }
732 JSRef<JSArray> array = JSRef<JSArray>::Cast(tmpInfo);
733 if (array->Length() != COLOR_FILTER_MATRIX_SIZE) {
734 return;
735 }
736 auto jscolorfilter = Referenced::MakeRefPtr<JSColorFilter>();
737 if (jscolorfilter == nullptr) {
738 return;
739 }
740 std::vector<float> colorfilter;
741 for (size_t i = 0; i < array->Length(); i++) {
742 JSRef<JSVal> value = array->GetValueAt(i);
743 if (value->IsNumber()) {
744 colorfilter.emplace_back(value->ToNumber<float>());
745 }
746 }
747 if (colorfilter.size() != COLOR_FILTER_MATRIX_SIZE) {
748 return;
749 }
750 jscolorfilter->SetColorFilterMatrix(std::move(colorfilter));
751 jscolorfilter->IncRefCount();
752 args.SetReturnValue(Referenced::RawPtr(jscolorfilter));
753 }
754
DestructorCallback(JSColorFilter * obj)755 void JSColorFilter::DestructorCallback(JSColorFilter* obj)
756 {
757 if (obj != nullptr) {
758 obj->DecRefCount();
759 }
760 }
761
SetColorFilter(const JSCallbackInfo & info)762 void JSImage::SetColorFilter(const JSCallbackInfo& info)
763 {
764 if (info.Length() != 1) {
765 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
766 return;
767 }
768 auto tmpInfo = info[0];
769 if (!tmpInfo->IsArray() && !tmpInfo->IsObject()) {
770 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
771 return;
772 }
773 if (tmpInfo->IsObject() && !tmpInfo->IsArray()) {
774 auto drawingColorFilter = CreateDrawingColorFilter(tmpInfo);
775 if (drawingColorFilter) {
776 ImageModel::GetInstance()->SetDrawingColorFilter(drawingColorFilter);
777 return;
778 }
779 JSColorFilter* colorFilter;
780 if (!tmpInfo->IsUndefined() && !tmpInfo->IsNull()) {
781 colorFilter = JSRef<JSObject>::Cast(tmpInfo)->Unwrap<JSColorFilter>();
782 } else {
783 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
784 return;
785 }
786 if (colorFilter && colorFilter->GetColorFilterMatrix().size() == COLOR_FILTER_MATRIX_SIZE) {
787 ImageModel::GetInstance()->SetColorFilterMatrix(colorFilter->GetColorFilterMatrix());
788 return;
789 }
790 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
791 return;
792 }
793 JSRef<JSArray> array = JSRef<JSArray>::Cast(tmpInfo);
794 if (array->Length() != COLOR_FILTER_MATRIX_SIZE) {
795 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
796 return;
797 }
798 std::vector<float> colorfilter;
799 for (size_t i = 0; i < array->Length(); i++) {
800 JSRef<JSVal> value = array->GetValueAt(i);
801 if (value->IsNumber()) {
802 colorfilter.emplace_back(value->ToNumber<float>());
803 } else {
804 ImageModel::GetInstance()->SetColorFilterMatrix(DEFAULT_COLORFILTER_MATRIX);
805 return;
806 }
807 }
808 ImageModel::GetInstance()->SetColorFilterMatrix(colorfilter);
809 }
810
SetSmoothEdge(const JSCallbackInfo & info)811 void JSImage::SetSmoothEdge(const JSCallbackInfo& info)
812 {
813 if (info.Length() != 1) {
814 ImageModel::GetInstance()->SetSmoothEdge(DEFAULT_SMOOTHEDGE_VALUE);
815 return;
816 }
817 double parseRes = DEFAULT_SMOOTHEDGE_VALUE;
818 ParseJsDouble(info[0], parseRes);
819 // Effective range : (FLOOR_SMOOTHEDGE_VALUE, CEIL_SMOOTHEDGE_VALUE]
820 // otherwise: DEFAULT_SMOOTHEDGE_VALUE
821 if (GreatNotEqual(parseRes, CEIL_SMOOTHEDGE_VALUE) || LessNotEqual(parseRes, FLOOR_SMOOTHEDGE_VALUE)) {
822 parseRes = DEFAULT_SMOOTHEDGE_VALUE;
823 }
824 ImageModel::GetInstance()->SetSmoothEdge(static_cast<float>(parseRes));
825 }
826
SetDynamicRangeMode(const JSCallbackInfo & info)827 void JSImage::SetDynamicRangeMode(const JSCallbackInfo& info)
828 {
829 if (info.Length() < 1) {
830 ImageModel::GetInstance()->SetDynamicRangeMode(DynamicRangeMode::STANDARD);
831 return;
832 }
833 int32_t parseRes = static_cast<int32_t>(DynamicRangeMode::STANDARD);
834 ParseJsInteger(info[0], parseRes);
835 if (parseRes < static_cast<int32_t>(DynamicRangeMode::HIGH) ||
836 parseRes > static_cast<int32_t>(DynamicRangeMode::STANDARD)) {
837 parseRes = static_cast<int32_t>(DynamicRangeMode::STANDARD);
838 }
839 DynamicRangeMode dynamicRangeMode = static_cast<DynamicRangeMode>(parseRes);
840 ImageModel::GetInstance()->SetDynamicRangeMode(dynamicRangeMode);
841 }
842
SetEnhancedImageQuality(const JSCallbackInfo & info)843 void JSImage::SetEnhancedImageQuality(const JSCallbackInfo& info)
844 {
845 if (info.Length() < 1) {
846 ImageModel::GetInstance()->SetEnhancedImageQuality(AIImageQuality::LOW);
847 return;
848 }
849 int32_t parseRes = static_cast<int32_t>(AIImageQuality::LOW);
850 ParseJsInteger(info[0], parseRes);
851 if (parseRes < static_cast<int32_t>(AIImageQuality::LOW) || parseRes > static_cast<int32_t>(AIImageQuality::HIGH)) {
852 parseRes = static_cast<int32_t>(AIImageQuality::LOW);
853 }
854 AIImageQuality resolutionQuality = static_cast<AIImageQuality>(parseRes);
855 ImageModel::GetInstance()->SetEnhancedImageQuality(resolutionQuality);
856 }
857
SetOrientation(const JSCallbackInfo & info)858 void JSImage::SetOrientation(const JSCallbackInfo& info)
859 {
860 if (info.Length() < 1) {
861 ImageModel::GetInstance()->SetOrientation(ImageRotateOrientation::UP);
862 return;
863 }
864 int32_t parseRes = 0;
865 ParseJsInteger(info[0], parseRes);
866 if (parseRes < static_cast<int>(ImageRotateOrientation::AUTO) ||
867 parseRes > static_cast<int>(ImageRotateOrientation::LEFT)) {
868 parseRes = static_cast<int>(ImageRotateOrientation::UP);
869 }
870 auto res = static_cast<ImageRotateOrientation>(parseRes);
871 ImageModel::GetInstance()->SetOrientation(res);
872 }
873
CreateImageAnimation(std::vector<RefPtr<PixelMap>> & pixelMaps,int32_t duration,int32_t iterations)874 void JSImage::CreateImageAnimation(std::vector<RefPtr<PixelMap>>& pixelMaps, int32_t duration, int32_t iterations)
875 {
876 std::vector<ImageProperties> imageList;
877 for (int i = 0; i < static_cast<int32_t>(pixelMaps.size()); i++) {
878 ImageProperties image;
879 image.pixelMap = pixelMaps[i];
880 imageList.push_back(image);
881 }
882 ImageModel::GetInstance()->CreateAnimation(imageList, duration, iterations);
883 }
884
JSBind(BindingTarget globalObj)885 void JSImage::JSBind(BindingTarget globalObj)
886 {
887 JSClass<JSImage>::Declare("Image");
888 MethodOptions opt = MethodOptions::NONE;
889 JSClass<JSImage>::StaticMethod("create", &JSImage::Create, opt);
890 JSClass<JSImage>::StaticMethod("alt", &JSImage::SetAlt, opt);
891 JSClass<JSImage>::StaticMethod("objectFit", &JSImage::SetObjectFit, opt);
892 JSClass<JSImage>::StaticMethod("imageMatrix", &JSImage::SetImageMatrix, opt);
893 JSClass<JSImage>::StaticMethod("matchTextDirection", &JSImage::SetMatchTextDirection, opt);
894 JSClass<JSImage>::StaticMethod("fitOriginalSize", &JSImage::SetFitOriginalSize, opt);
895 JSClass<JSImage>::StaticMethod("sourceSize", &JSImage::SetSourceSize, opt);
896 JSClass<JSImage>::StaticMethod("fillColor", &JSImage::SetImageFill, opt);
897 JSClass<JSImage>::StaticMethod("renderMode", &JSImage::SetImageRenderMode, opt);
898 JSClass<JSImage>::StaticMethod("objectRepeat", &JSImage::SetImageRepeat, opt);
899 JSClass<JSImage>::StaticMethod("interpolation", &JSImage::SetImageInterpolation, opt);
900 JSClass<JSImage>::StaticMethod("colorFilter", &JSImage::SetColorFilter, opt);
901 JSClass<JSImage>::StaticMethod("edgeAntialiasing", &JSImage::SetSmoothEdge, opt);
902 JSClass<JSImage>::StaticMethod("dynamicRangeMode", &JSImage::SetDynamicRangeMode, opt);
903 JSClass<JSImage>::StaticMethod("enhancedImageQuality", &JSImage::SetEnhancedImageQuality, opt);
904 JSClass<JSImage>::StaticMethod("orientation", &JSImage::SetOrientation, opt);
905
906 JSClass<JSImage>::StaticMethod("border", &JSImage::JsBorder);
907 JSClass<JSImage>::StaticMethod("borderRadius", &JSImage::JsBorderRadius);
908 JSClass<JSImage>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
909 JSClass<JSImage>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
910 JSClass<JSImage>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
911 JSClass<JSImage>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
912 JSClass<JSImage>::StaticMethod("autoResize", &JSImage::SetAutoResize);
913 JSClass<JSImage>::StaticMethod("resizable", &JSImage::JsImageResizable);
914
915 JSClass<JSImage>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
916 JSClass<JSImage>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
917 JSClass<JSImage>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
918 JSClass<JSImage>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
919 JSClass<JSImage>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
920 JSClass<JSImage>::StaticMethod("onComplete", &JSImage::OnComplete);
921 JSClass<JSImage>::StaticMethod("onError", &JSImage::OnError);
922 JSClass<JSImage>::StaticMethod("onFinish", &JSImage::OnFinish);
923 JSClass<JSImage>::StaticMethod("syncLoad", &JSImage::SetSyncLoad);
924 JSClass<JSImage>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
925 JSClass<JSImage>::StaticMethod("draggable", &JSImage::JsSetDraggable);
926 JSClass<JSImage>::StaticMethod("onDragStart", &JSImage::JsOnDragStart);
927 JSClass<JSImage>::StaticMethod("copyOption", &JSImage::SetCopyOption);
928 JSClass<JSImage>::StaticMethod("enableAnalyzer", &JSImage::EnableAnalyzer);
929 JSClass<JSImage>::StaticMethod("analyzerConfig", &JSImage::AnalyzerConfig);
930
931 // override method
932 JSClass<JSImage>::StaticMethod("opacity", &JSImage::JsOpacity);
933 JSClass<JSImage>::StaticMethod("blur", &JSImage::JsBlur);
934 JSClass<JSImage>::StaticMethod("transition", &JSImage::JsTransition);
935 JSClass<JSImage>::StaticMethod("pointLight", &JSViewAbstract::JsPointLight, opt);
936 JSClass<JSImage>::InheritAndBind<JSViewAbstract>(globalObj);
937
938 JSClass<JSColorFilter>::Declare("ColorFilter");
939 JSClass<JSColorFilter>::Bind(globalObj, JSColorFilter::ConstructorCallback, JSColorFilter::DestructorCallback);
940 }
941
JsSetDraggable(bool draggable)942 void JSImage::JsSetDraggable(bool draggable)
943 {
944 ImageModel::GetInstance()->SetDraggable(draggable);
945 }
946
JsOnDragStart(const JSCallbackInfo & info)947 void JSImage::JsOnDragStart(const JSCallbackInfo& info)
948 {
949 if (!Container::LessThanAPITargetVersion(PlatformVersion::VERSION_FIFTEEN)) {
950 JSViewAbstract::JsOnDragStart(info);
951 return;
952 }
953 if (info.Length() != 1 || !info[0]->IsFunction()) {
954 return;
955 }
956 RefPtr<JsDragFunction> jsOnDragStartFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
957 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
958 auto onDragStartId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragStartFunc), node = frameNode](
959 const RefPtr<DragEvent>& info, const std::string& extraParams) -> NG::DragDropBaseInfo {
960 NG::DragDropBaseInfo itemInfo;
961 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, itemInfo);
962 PipelineContext::SetCallBackNode(node);
963 auto ret = func->Execute(info, extraParams);
964 if (!ret->IsObject()) {
965 return itemInfo;
966 }
967 if (ParseAndUpdateDragItemInfo(ret, itemInfo)) {
968 return itemInfo;
969 }
970
971 auto builderObj = JSRef<JSObject>::Cast(ret);
972 #if defined(PIXEL_MAP_SUPPORTED)
973 auto pixmap = builderObj->GetProperty("pixelMap");
974 itemInfo.pixelMap = CreatePixelMapFromNapiValue(pixmap);
975 #endif
976 auto extraInfo = builderObj->GetProperty("extraInfo");
977 ParseJsString(extraInfo, itemInfo.extraInfo);
978 ParseAndUpdateDragItemInfo(builderObj->GetProperty("builder"), itemInfo);
979 return itemInfo;
980 };
981 ImageModel::GetInstance()->SetOnDragStart(std::move(onDragStartId));
982 }
983
SetCopyOption(const JSCallbackInfo & info)984 void JSImage::SetCopyOption(const JSCallbackInfo& info)
985 {
986 if (ImageModel::GetInstance()->GetIsAnimation()) {
987 return;
988 }
989 auto copyOptions = CopyOptions::None;
990 if (info[0]->IsNumber()) {
991 auto enumNumber = info[0]->ToNumber<int>();
992 copyOptions = static_cast<CopyOptions>(enumNumber);
993 if (copyOptions < CopyOptions::None || copyOptions > CopyOptions::Distributed) {
994 copyOptions = CopyOptions::None;
995 }
996 }
997 ImageModel::GetInstance()->SetCopyOption(copyOptions);
998 }
999
EnableAnalyzer(bool isEnableAnalyzer)1000 void JSImage::EnableAnalyzer(bool isEnableAnalyzer)
1001 {
1002 if (ImageModel::GetInstance()->GetIsAnimation()) {
1003 return;
1004 }
1005 ImageModel::GetInstance()->EnableAnalyzer(isEnableAnalyzer);
1006 }
1007
AnalyzerConfig(const JSCallbackInfo & info)1008 void JSImage::AnalyzerConfig(const JSCallbackInfo& info)
1009 {
1010 auto configParams = info[0];
1011 if (configParams->IsNull() || !configParams->IsObject()) {
1012 return;
1013 }
1014 auto engine = EngineHelper::GetCurrentEngine();
1015 CHECK_NULL_VOID(engine);
1016 NativeEngine* nativeEngine = engine->GetNativeEngine();
1017 CHECK_NULL_VOID(nativeEngine);
1018 panda::Local<JsiValue> value = configParams.Get().GetLocalHandle();
1019 JSValueWrapper valueWrapper = value;
1020 ScopeRAII scope(reinterpret_cast<napi_env>(nativeEngine));
1021 napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
1022 ImageModel::GetInstance()->SetImageAnalyzerConfig(nativeValue);
1023
1024 // As an example, the function is not in effect.
1025 auto paramObject = JSRef<JSObject>::Cast(configParams);
1026 JSRef<JSVal> typeVal = paramObject->GetProperty("types");
1027 ImageAnalyzerConfig analyzerConfig;
1028 if (typeVal->IsArray()) {
1029 auto array = JSRef<JSArray>::Cast(typeVal);
1030 std::set<ImageAnalyzerType> types;
1031 for (size_t i = 0; i < array->Length(); ++i) {
1032 if (!array->GetValueAt(i)->IsNumber()) {
1033 continue;
1034 }
1035 int value = array->GetValueAt(i)->ToNumber<int>();
1036 ImageAnalyzerType type = static_cast<ImageAnalyzerType>(value);
1037 if (type != ImageAnalyzerType::SUBJECT && type != ImageAnalyzerType::TEXT) {
1038 continue;
1039 }
1040 types.insert(type);
1041 }
1042 analyzerConfig.types = std::move(types);
1043 }
1044 ImageModel::GetInstance()->SetImageAnalyzerConfig(analyzerConfig);
1045 }
1046
1047 } // namespace OHOS::Ace::Framework
1048