• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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