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