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