1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <functional>
21 #include <memory>
22 #include <optional>
23 #include <regex>
24 #include <string>
25 #include <utility>
26 #include <vector>
27 #include <unordered_map>
28 
29 #include "base/geometry/calc_dimension.h"
30 #include "base/geometry/dimension.h"
31 #include "base/geometry/matrix4.h"
32 #include "base/geometry/ng/offset_t.h"
33 #include "base/geometry/ng/vector.h"
34 #include "base/geometry/shape.h"
35 #include "base/json/json_util.h"
36 #include "base/log/ace_scoring_log.h"
37 #include "base/log/log.h"
38 #include "base/memory/ace_type.h"
39 #include "base/memory/referenced.h"
40 #include "base/utils/utils.h"
41 #include "bridge/common/utils/engine_helper.h"
42 #include "bridge/common/utils/utils.h"
43 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
44 #include "bridge/declarative_frontend/engine/functions/js_clipboard_function.h"
45 #include "bridge/declarative_frontend/engine/functions/js_drag_function.h"
46 #include "bridge/declarative_frontend/engine/functions/js_on_child_touch_test_function.h"
47 #include "bridge/declarative_frontend/engine/functions/js_focus_function.h"
48 #include "bridge/declarative_frontend/engine/functions/js_function.h"
49 #include "bridge/declarative_frontend/engine/functions/js_gesture_judge_function.h"
50 #include "bridge/declarative_frontend/engine/functions/js_hover_function.h"
51 #include "bridge/declarative_frontend/engine/functions/js_key_function.h"
52 #include "bridge/declarative_frontend/engine/functions/js_on_area_change_function.h"
53 #include "bridge/declarative_frontend/engine/functions/js_on_size_change_function.h"
54 #include "bridge/declarative_frontend/engine/functions/js_should_built_in_recognizer_parallel_with_function.h"
55 #include "bridge/declarative_frontend/engine/functions/js_touch_intercept_function.h"
56 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_utils_bridge.h"
57 #include "bridge/js_frontend/engine/jsi/ark_js_value.h"
58 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
59 #include "bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
60 #include "bridge/declarative_frontend/engine/js_converter.h"
61 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
62 #include "bridge/declarative_frontend/engine/js_types.h"
63 #include "bridge/declarative_frontend/jsview/js_animatable_arithmetic.h"
64 #include "bridge/declarative_frontend/jsview/js_grid_container.h"
65 #include "bridge/declarative_frontend/jsview/js_shape_abstract.h"
66 #include "bridge/declarative_frontend/jsview/js_utils.h"
67 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
68 #include "bridge/declarative_frontend/jsview/js_view_context.h"
69 #include "bridge/declarative_frontend/jsview/models/view_abstract_model_impl.h"
70 #include "canvas_napi/js_canvas.h"
71 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
72 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
73 #endif
74 #include "core/common/resource/resource_manager.h"
75 #include "core/common/resource/resource_object.h"
76 #include "core/components/common/layout/constants.h"
77 #include "core/components/common/layout/position_param.h"
78 #include "core/components/common/layout/screen_system_manager.h"
79 #include "core/components/common/properties/animation_option.h"
80 #include "core/components/common/properties/border_image.h"
81 #include "core/components/common/properties/color.h"
82 #include "core/components/common/properties/decoration.h"
83 #include "core/components/common/properties/shadow.h"
84 #include "core/components/common/properties/invert.h"
85 #include "core/components/common/properties/shadow_config.h"
86 #include "core/components/theme/resource_adapter.h"
87 #include "core/components/theme/shadow_theme.h"
88 #include "core/components_ng/base/view_abstract.h"
89 #include "core/components_ng/base/view_abstract_model.h"
90 #include "core/components_ng/base/view_stack_processor.h"
91 #include "core/components_ng/event/focus_box.h"
92 #include "core/components_ng/gestures/base_gesture_event.h"
93 #include "core/components_ng/pattern/menu/menu_pattern.h"
94 #include "core/components_ng/pattern/overlay/modal_style.h"
95 #include "core/components_ng/pattern/overlay/sheet_style.h"
96 #include "core/components_ng/property/grid_property.h"
97 #include "core/components_ng/property/safe_area_insets.h"
98 #include "core/gestures/gesture_info.h"
99 #include "core/image/image_source_info.h"
100 #ifdef PLUGIN_COMPONENT_SUPPORTED
101 #include "core/common/plugin_manager.h"
102 #endif
103 #include "interfaces/native/node/resource.h"
104 
105 #include "core/common/card_scope.h"
106 #include "core/common/container.h"
107 #include "core/common/resource/resource_configuration.h"
108 #include "core/components/progress/progress_theme.h"
109 #include "core/components_ng/base/view_abstract_model_ng.h"
110 #include "core/components_ng/base/view_stack_model.h"
111 #include "core/components_ng/property/progress_mask_property.h"
112 
113 namespace OHOS::Ace {
114 namespace {
115 const std::string RESOURCE_TOKEN_PATTERN = "(app|sys|\\[.+?\\])\\.(\\S+?)\\.(\\S+)";
116 const std::string RESOURCE_NAME_PATTERN = "\\[(.+?)\\]";
117 constexpr int32_t DIRECTION_COUNT = 4;
118 constexpr char JS_TEXT_MENU_ID_CLASS_NAME[] = "TextMenuItemId";
119 constexpr int NUM1 = 1;
120 const std::vector<HoverModeAreaType> HOVER_MODE_AREA_TYPE = { HoverModeAreaType::TOP_SCREEN,
121     HoverModeAreaType::BOTTOM_SCREEN };
122 } // namespace
123 
124 std::unique_ptr<ViewAbstractModel> ViewAbstractModel::instance_ = nullptr;
125 std::mutex ViewAbstractModel::mutex_;
126 using DoubleBindCallback = std::function<void(const std::string&)>;
127 
GetInstance()128 ViewAbstractModel* ViewAbstractModel::GetInstance()
129 {
130     if (!instance_) {
131         std::lock_guard<std::mutex> lock(mutex_);
132         if (!instance_) {
133 #ifdef NG_BUILD
134             instance_.reset(new NG::ViewAbstractModelNG());
135 #else
136             if (Container::IsCurrentUseNewPipeline()) {
137                 instance_.reset(new NG::ViewAbstractModelNG());
138             } else {
139                 instance_.reset(new Framework::ViewAbstractModelImpl());
140             }
141 #endif
142         }
143     }
144     return instance_.get();
145 }
146 
147 } // namespace OHOS::Ace
148 
149 namespace OHOS::Ace::Framework {
150 namespace {
151 
152 constexpr uint32_t DEFAULT_DURATION = 1000; // ms
153 constexpr int64_t MICROSEC_TO_MILLISEC = 1000;
154 constexpr uint32_t COLOR_ALPHA_OFFSET = 24;
155 constexpr uint32_t COLOR_ALPHA_VALUE = 0xFF000000;
156 constexpr uint32_t SAFE_AREA_TYPE_LIMIT = 3;
157 constexpr uint32_t SAFE_AREA_EDGE_LIMIT = 4;
158 constexpr int32_t MAX_ALIGN_VALUE = 8;
159 constexpr int32_t UNKNOWN_RESOURCE_ID = -1;
160 constexpr int32_t UNKNOWN_RESOURCE_TYPE = -1;
161 const std::regex RESOURCE_APP_STRING_PLACEHOLDER(R"(\%((\d+)(\$)){0,1}([dsf]))", std::regex::icase);
162 const std::regex FLOAT_PATTERN(R"(-?(0|[1-9]\d*)(\.\d+))", std::regex::icase);
163 constexpr double FULL_DIMENSION = 100.0;
164 constexpr double HALF_DIMENSION = 50.0;
165 constexpr double ROUND_UNIT = 360.0;
166 constexpr double VISIBLE_RATIO_MIN = 0.0;
167 constexpr double VISIBLE_RATIO_MAX = 1.0;
168 constexpr int32_t PARAMETER_LENGTH_FIRST = 1;
169 constexpr int32_t PARAMETER_LENGTH_SECOND = 2;
170 constexpr int32_t PARAMETER_LENGTH_THIRD = 3;
171 constexpr int32_t SECOND_INDEX = 2;
172 constexpr uint32_t ON_WILL_DISMISS_FIELD_COUNT = 2;
173 constexpr float DEFAULT_SCALE_LIGHT = 0.9f;
174 constexpr float DEFAULT_SCALE_MIDDLE_OR_HEAVY = 0.95f;
175 constexpr float MAX_ANGLE = 360.0f;
176 constexpr float DEFAULT_BIAS = 0.5f;
177 constexpr float DEFAULT_LAYOUT_WEIGHT = 0.0f;
178 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
179 const std::vector<std::string> TEXT_DETECT_TYPES = { "phoneNum", "url", "email", "location", "datetime" };
180 const std::vector<std::string> RESOURCE_HEADS = { "app", "sys" };
181 const std::string SHEET_HEIGHT_MEDIUM = "medium";
182 const std::string SHEET_HEIGHT_LARGE = "large";
183 const std::string SHEET_HEIGHT_AUTO = "auto";
184 const std::string SHEET_HEIGHT_FITCONTENT = "fit_content";
185 const std::string BLOOM_RADIUS_SYS_RES_NAME = "sys.float.ohos_id_point_light_bloom_radius";
186 const std::string BLOOM_COLOR_SYS_RES_NAME = "sys.color.ohos_id_point_light_bloom_color";
187 const std::string ILLUMINATED_BORDER_WIDTH_SYS_RES_NAME = "sys.float.ohos_id_point_light_illuminated_border_width";
188 const std::vector<std::string> SLICE_KEYS = { "left", "right", "top", "bottom" };
189 const std::vector<int32_t> LENGTH_METRICS_KEYS {
190     static_cast<int32_t>(ArkUIIndex::START), static_cast<int32_t>(ArkUIIndex::END),
191     static_cast<int32_t>(ArkUIIndex::TOP), static_cast<int32_t>(ArkUIIndex::BOTTOM) };
192 const char* START_PROPERTY = "start";
193 const char* END_PROPERTY = "end";
194 const char* TOP_PROPERTY = "top";
195 const char* BOTTOM_PROPERTY = "bottom";
196 const char* LEFT_PROPERTY = "left";
197 const char* RIGHT_PROPERTY = "right";
198 const char* TOP_START_PROPERTY = "topStart";
199 const char* TOP_END_PROPERTY = "topEnd";
200 const char* BOTTOM_START_PROPERTY = "bottomStart";
201 const char* BOTTOM_END_PROPERTY = "bottomEnd";
202 const char* DEBUG_LINE_INFO_LINE = "$line";
203 const char* DEBUG_LINE_INFO_PACKAGE_NAME = "$packageName";
204 
205 constexpr Dimension ARROW_ZERO_PERCENT_VALUE = 0.0_pct;
206 constexpr Dimension ARROW_HALF_PERCENT_VALUE = 0.5_pct;
207 constexpr Dimension ARROW_ONE_HUNDRED_PERCENT_VALUE = 1.0_pct;
208 
ParseJsScale(const JSRef<JSVal> & jsValue,float & scaleX,float & scaleY,float & scaleZ,CalcDimension & centerX,CalcDimension & centerY)209 void ParseJsScale(const JSRef<JSVal>& jsValue, float& scaleX, float& scaleY, float& scaleZ,
210     CalcDimension& centerX, CalcDimension& centerY)
211 {
212     double xVal = 1.0;
213     double yVal = 1.0;
214     double zVal = 1.0;
215     if (!jsValue->IsObject()) {
216         scaleX = static_cast<float>(xVal);
217         scaleY = static_cast<float>(yVal);
218         scaleZ = static_cast<float>(zVal);
219         CalcDimension length;
220         centerX = length;
221         centerY = length;
222         return;
223     }
224     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
225     JSViewAbstract::ParseJsDouble(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::X)), xVal);
226     JSViewAbstract::ParseJsDouble(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Y)), yVal);
227     JSViewAbstract::ParseJsDouble(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Z)), zVal);
228     scaleX = static_cast<float>(xVal);
229     scaleY = static_cast<float>(yVal);
230     scaleZ = static_cast<float>(zVal);
231     // if specify centerX
232     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::CENTER_X)), centerX);
233     // if specify centerY
234     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::CENTER_Y)), centerY);
235 }
236 
ParseJsTranslate(const JSRef<JSVal> & jsValue,CalcDimension & translateX,CalcDimension & translateY,CalcDimension & translateZ)237 void ParseJsTranslate(const JSRef<JSVal>& jsValue, CalcDimension& translateX, CalcDimension& translateY,
238     CalcDimension& translateZ)
239 {
240     if (!jsValue->IsObject()) {
241         return;
242     }
243     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
244     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::X)), translateX);
245     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Y)), translateY);
246     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Z)), translateZ);
247 }
248 
GetDefaultRotateVector(double & dx,double & dy,double & dz)249 void GetDefaultRotateVector(double& dx, double& dy, double& dz)
250 {
251     dx = 0.0;
252     dy = 0.0;
253     dz = 0.0;
254     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_NINE)) {
255         dz = 1.0;
256     }
257 }
258 
ParseJsRotate(const JSRef<JSVal> & jsValue,NG::RotateOptions & rotate,std::optional<float> & angle)259 void ParseJsRotate(const JSRef<JSVal>& jsValue, NG::RotateOptions& rotate, std::optional<float>& angle)
260 {
261     if (!jsValue->IsObject()) {
262         return;
263     }
264     // default: dx, dy, dz (0.0, 0.0, 0.0)
265     double dxVal = 0.0;
266     double dyVal = 0.0;
267     double dzVal = 0.0;
268     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
269     auto jsRotateX = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::X));
270     auto jsRotateY = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Y));
271     auto jsRotateZ = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Z));
272     if (jsRotateX->IsUndefined()
273         && jsRotateY->IsUndefined()
274         && jsRotateZ->IsUndefined()) {
275         GetDefaultRotateVector(dxVal, dyVal, dzVal);
276     } else {
277         JSViewAbstract::ParseJsDouble(jsRotateX, dxVal);
278         JSViewAbstract::ParseJsDouble(jsRotateY, dyVal);
279         JSViewAbstract::ParseJsDouble(jsRotateZ, dzVal);
280     }
281     rotate.xDirection = static_cast<float>(dxVal);
282     rotate.yDirection = static_cast<float>(dyVal);
283     rotate.zDirection = static_cast<float>(dzVal);
284     // if specify centerX
285     if (!JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::CENTER_X)),
286         rotate.centerX)) {
287         rotate.centerX = Dimension(0.5f, DimensionUnit::PERCENT);
288     }
289     // if specify centerY
290     if (!JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::CENTER_Y)),
291         rotate.centerY)) {
292         rotate.centerY = Dimension(0.5f, DimensionUnit::PERCENT);
293     }
294     // if specify centerZ
295     if (!JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::CENTER_Z)),
296         rotate.centerZ)) {
297         rotate.centerZ = Dimension(0.5f, DimensionUnit::PERCENT);
298     }
299     // if specify angle
300     JSViewAbstract::GetJsAngle(static_cast<int32_t>(ArkUIIndex::ANGLE), jsObj, angle);
301     rotate.perspective = 0.0f;
302     JSViewAbstract::GetJsPerspective(static_cast<int32_t>(ArkUIIndex::PERSPECTIVE), jsObj, rotate.perspective);
303 }
304 
ParseMotionPath(const JSRef<JSVal> & jsValue,MotionPathOption & option)305 bool ParseMotionPath(const JSRef<JSVal>& jsValue, MotionPathOption& option)
306 {
307     if (!jsValue->IsObject()) {
308         return false;
309     }
310 
311     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
312     auto path = jsObj->GetPropertyValue<std::string>("path", "");
313     if (path.empty()) {
314         return false;
315     }
316     option.SetPath(path);
317     double from = 0.0;
318     double to = 1.0;
319     JSViewAbstract::ParseJsDouble(jsObj->GetProperty("from"), from);
320     JSViewAbstract::ParseJsDouble(jsObj->GetProperty("to"), to);
321     if (GreatNotEqual(from, 1.0) || LessNotEqual(from, 0.0)) {
322         from = 0.0;
323     }
324     if (GreatNotEqual(to, 1.0) || LessNotEqual(to, 0.0)) {
325         to = 1.0;
326     } else if (to < from) {
327         to = from;
328     }
329     option.SetBegin(static_cast<float>(from));
330     option.SetEnd(static_cast<float>(to));
331     option.SetRotate(jsObj->GetPropertyValue<bool>("rotatable", false));
332     return true;
333 }
334 
ParseDragPreviewMode(NG::DragPreviewOption & previewOption,int32_t modeValue,bool & isAuto)335 void ParseDragPreviewMode(NG::DragPreviewOption& previewOption, int32_t modeValue, bool& isAuto)
336 {
337     if (modeValue == static_cast<int32_t>(NG::DragPreviewMode::AUTO)) {
338         previewOption.ResetDragPreviewMode();
339         isAuto = true;
340         return;
341     } else if (modeValue == static_cast<int32_t>(NG::DragPreviewMode::DISABLE_SCALE)) {
342         previewOption.isScaleEnabled = false;
343     } else if (modeValue == static_cast<int32_t>(NG::DragPreviewMode::ENABLE_DEFAULT_SHADOW)) {
344         previewOption.isDefaultShadowEnabled = true;
345     } else if (modeValue == static_cast<int32_t>(NG::DragPreviewMode::ENABLE_DEFAULT_RADIUS)) {
346         previewOption.isDefaultRadiusEnabled = true;
347     }
348     isAuto = false;
349 }
350 
SetBgImgPosition(const DimensionUnit & typeX,const DimensionUnit & typeY,const double valueX,const double valueY,BackgroundImagePosition & bgImgPosition)351 void SetBgImgPosition(const DimensionUnit& typeX, const DimensionUnit& typeY, const double valueX, const double valueY,
352     BackgroundImagePosition& bgImgPosition)
353 {
354     AnimationOption option = ViewStackModel::GetInstance()->GetImplicitAnimationOption();
355     bgImgPosition.SetSizeX(AnimatableDimension(valueX, typeX, option));
356     bgImgPosition.SetSizeY(AnimatableDimension(valueY, typeY, option));
357 }
358 
GetReplaceContentStr(int pos,const std::string & type,JSRef<JSArray> params,int32_t containCount)359 std::string GetReplaceContentStr(int pos, const std::string& type, JSRef<JSArray> params, int32_t containCount)
360 {
361     auto index = pos + containCount;
362     if (index < 0) {
363         return std::string();
364     }
365 
366     JSRef<JSVal> item = params->GetValueAt(static_cast<size_t>(index));
367     if (type == "d") {
368         if (item->IsNumber()) {
369             return std::to_string(item->ToNumber<int32_t>());
370         } else if (item->IsObject()) {
371             int32_t result = 0;
372             JSViewAbstract::ParseJsInteger(item, result);
373             return std::to_string(result);
374         }
375     } else if (type == "s") {
376         if (item->IsString()) {
377             return item->ToString();
378         } else if (item->IsObject()) {
379             std::string result;
380             JSViewAbstract::ParseJsString(item, result);
381             return result;
382         }
383     } else if (type == "f") {
384         if (item->IsNumber()) {
385             return std::to_string(item->ToNumber<float>());
386         } else if (item->IsObject()) {
387             double result = 0.0;
388             JSViewAbstract::ParseJsDouble(item, result);
389             return std::to_string(result);
390         }
391     }
392     return std::string();
393 }
394 
ReplaceHolder(std::string & originStr,JSRef<JSArray> params,int32_t containCount)395 void ReplaceHolder(std::string& originStr, JSRef<JSArray> params, int32_t containCount)
396 {
397     auto size = static_cast<int32_t>(params->Length());
398     if (containCount == size) {
399         return;
400     }
401     std::string::const_iterator start = originStr.begin();
402     std::string::const_iterator end = originStr.end();
403     std::smatch matches;
404     bool shortHolderType = false;
405     bool firstMatch = true;
406     int searchTime = 0;
407     while (std::regex_search(start, end, matches, RESOURCE_APP_STRING_PLACEHOLDER)) {
408         std::string pos = matches[2];
409         std::string type = matches[4];
410         if (firstMatch) {
411             firstMatch = false;
412             shortHolderType = pos.length() == 0;
413         } else {
414             if (shortHolderType ^ (pos.length() == 0)) {
415                 return;
416             }
417         }
418 
419         std::string replaceContentStr;
420         if (shortHolderType) {
421             replaceContentStr = GetReplaceContentStr(searchTime, type, params, containCount);
422         } else {
423             replaceContentStr = GetReplaceContentStr(StringToInt(pos) - 1, type, params, containCount);
424         }
425 
426         originStr.replace(matches[0].first - originStr.begin(), matches[0].length(), replaceContentStr);
427         start = originStr.begin() + matches.prefix().length() + replaceContentStr.length();
428         end = originStr.end();
429         searchTime++;
430     }
431 }
432 
ParseLocationProps(const JSRef<JSObject> & sizeObj,CalcDimension & x,CalcDimension & y)433 bool ParseLocationProps(const JSRef<JSObject>& sizeObj, CalcDimension& x, CalcDimension& y)
434 {
435     JSRef<JSVal> xVal = sizeObj->GetProperty(static_cast<int32_t>(ArkUIIndex::X));
436     JSRef<JSVal> yVal = sizeObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Y));
437     bool hasX = false;
438     bool hasY = false;
439     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
440         hasX = JSViewAbstract::ParseJsDimensionNG(xVal, x, DimensionUnit::VP);
441         hasY = JSViewAbstract::ParseJsDimensionNG(yVal, y, DimensionUnit::VP);
442     } else {
443         hasX = JSViewAbstract::ParseJsDimension(xVal, x, DimensionUnit::VP);
444         hasY = JSViewAbstract::ParseJsDimension(yVal, y, DimensionUnit::VP);
445     }
446     return hasX || hasY;
447 }
448 
ParseLocationPropsEdges(const JSRef<JSObject> & edgesObj,EdgesParam & edges)449 bool ParseLocationPropsEdges(const JSRef<JSObject>& edgesObj, EdgesParam& edges)
450 {
451     bool useEdges = false;
452     CalcDimension top;
453     CalcDimension left;
454     CalcDimension bottom;
455     CalcDimension right;
456     JSRef<JSVal> topVal = edgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP));
457     JSRef<JSVal> leftVal = edgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::LEFT));
458     JSRef<JSVal> bottomVal = edgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM));
459     JSRef<JSVal> rightVal = edgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::RIGHT));
460     if (JSViewAbstract::ParseJsDimensionNG(topVal, top, DimensionUnit::VP)) {
461         edges.SetTop(top);
462         useEdges = true;
463     }
464     if (JSViewAbstract::ParseJsDimensionNG(leftVal, left, DimensionUnit::VP)) {
465         edges.SetLeft(left);
466         useEdges = true;
467     }
468     if (JSViewAbstract::ParseJsDimensionNG(bottomVal, bottom, DimensionUnit::VP)) {
469         edges.SetBottom(bottom);
470         useEdges = true;
471     }
472     if (JSViewAbstract::ParseJsDimensionNG(rightVal, right, DimensionUnit::VP)) {
473         edges.SetRight(right);
474         useEdges = true;
475     }
476     return useEdges;
477 }
478 
ParseJsLengthMetrics(const JSRef<JSObject> & obj,CalcDimension & result)479 bool ParseJsLengthMetrics(const JSRef<JSObject>& obj, CalcDimension& result)
480 {
481     auto value = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::VALUE));
482     if (!value->IsNumber()) {
483         return false;
484     }
485     auto unit = DimensionUnit::VP;
486     auto jsUnit = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::UNIT));
487     if (jsUnit->IsNumber()) {
488         unit = static_cast<DimensionUnit>(jsUnit->ToNumber<int32_t>());
489     }
490     CalcDimension dimension(value->ToNumber<double>(), unit);
491     result = dimension;
492     return true;
493 }
494 
CheckLengthMetrics(const JSRef<JSObject> & object)495 bool CheckLengthMetrics(const JSRef<JSObject>& object)
496 {
497     if (object->HasProperty(static_cast<int32_t>(ArkUIIndex::START)) ||
498         object->HasProperty(static_cast<int32_t>(ArkUIIndex::END)) ||
499         object->HasProperty(static_cast<int32_t>(ArkUIIndex::TOP_START)) ||
500         object->HasProperty(static_cast<int32_t>(ArkUIIndex::TOP_END)) ||
501         object->HasProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM_START)) ||
502         object->HasProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM_END))) {
503         return true;
504     }
505     auto jsTop = object->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP));
506     if (jsTop->IsObject()) {
507         JSRef<JSObject> topObj = JSRef<JSObject>::Cast(jsTop);
508         if (topObj->HasProperty(static_cast<int32_t>(ArkUIIndex::VALUE))) {
509             return true;
510         }
511     }
512     auto jsBottom = object->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM));
513     if (jsBottom->IsObject()) {
514         JSRef<JSObject> bottomObj = JSRef<JSObject>::Cast(jsBottom);
515         if (bottomObj->HasProperty(static_cast<int32_t>(ArkUIIndex::VALUE))) {
516             return true;
517         }
518     }
519     return false;
520 }
521 
ParseLocalizedEdges(const JSRef<JSObject> & LocalizeEdgesObj,EdgesParam & edges)522 bool ParseLocalizedEdges(const JSRef<JSObject>& LocalizeEdgesObj, EdgesParam& edges)
523 {
524     bool useLocalizedEdges = false;
525     CalcDimension start;
526     CalcDimension end;
527     CalcDimension top;
528     CalcDimension bottom;
529 
530     JSRef<JSVal> startVal = LocalizeEdgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::START));
531     if (startVal->IsObject()) {
532         JSRef<JSObject> startObj = JSRef<JSObject>::Cast(startVal);
533         ParseJsLengthMetrics(startObj, start);
534         edges.SetLeft(start);
535         useLocalizedEdges = true;
536     }
537     JSRef<JSVal> endVal = LocalizeEdgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::END));
538     if (endVal->IsObject()) {
539         JSRef<JSObject> endObj = JSRef<JSObject>::Cast(endVal);
540         ParseJsLengthMetrics(endObj, end);
541         edges.SetRight(end);
542         useLocalizedEdges = true;
543     }
544     JSRef<JSVal> topVal = LocalizeEdgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP));
545     if (topVal->IsObject()) {
546         JSRef<JSObject> topObj = JSRef<JSObject>::Cast(topVal);
547         ParseJsLengthMetrics(topObj, top);
548         edges.SetTop(top);
549         useLocalizedEdges = true;
550     }
551     JSRef<JSVal> bottomVal = LocalizeEdgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM));
552     if (bottomVal->IsObject()) {
553         JSRef<JSObject> bottomObj = JSRef<JSObject>::Cast(bottomVal);
554         ParseJsLengthMetrics(bottomObj, bottom);
555         edges.SetBottom(bottom);
556         useLocalizedEdges = true;
557     }
558     return useLocalizedEdges;
559 }
560 
ParseMarkAnchorPosition(const JSRef<JSObject> & LocalizeEdgesObj,CalcDimension & x,CalcDimension & y)561 bool ParseMarkAnchorPosition(const JSRef<JSObject>& LocalizeEdgesObj, CalcDimension& x, CalcDimension& y)
562 {
563     bool useMarkAnchorPosition = false;
564     CalcDimension start;
565     CalcDimension top;
566 
567     JSRef<JSVal> startVal = LocalizeEdgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::START));
568     if (startVal->IsObject()) {
569         JSRef<JSObject> startObj = JSRef<JSObject>::Cast(startVal);
570         ParseJsLengthMetrics(startObj, start);
571         x = start;
572         useMarkAnchorPosition = true;
573     }
574     JSRef<JSVal> topVal = LocalizeEdgesObj->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP));
575     if (topVal->IsObject()) {
576         JSRef<JSObject> topObj = JSRef<JSObject>::Cast(topVal);
577         ParseJsLengthMetrics(topObj, top);
578         y = top;
579         useMarkAnchorPosition = true;
580     }
581     return useMarkAnchorPosition;
582 }
583 
ParseDragStartBuilderFunc(const JSRef<JSVal> & info)584 RefPtr<JsFunction> ParseDragStartBuilderFunc(const JSRef<JSVal>& info)
585 {
586     JSRef<JSVal> builder;
587     if (info->IsObject()) {
588         auto builderObj = JSRef<JSObject>::Cast(info);
589         builder = builderObj->GetProperty("builder");
590     } else if (info->IsFunction()) {
591         builder = info;
592     } else {
593         return nullptr;
594     }
595 
596     if (!builder->IsFunction()) {
597         return nullptr;
598     }
599 
600     return AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
601 }
602 
603 RefPtr<NG::ChainedTransitionEffect> ParseChainedTransition(
604     const JSRef<JSObject>& object, const JSExecutionContext& context);
605 
ParseChainedRotateTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)606 RefPtr<NG::ChainedTransitionEffect> ParseChainedRotateTransition(
607     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
608 {
609     RefPtr<NG::ChainedTransitionEffect> effect;
610     if (effectOption->IsObject()) {
611         NG::RotateOptions rotate(0.0f, 0.0f, 0.0f, 0.0f, 0.5_pct, 0.5_pct);
612         std::optional<float> angle;
613         ParseJsRotate(effectOption, rotate, angle);
614         if (angle.has_value()) {
615             rotate.angle = angle.value();
616             return AceType::MakeRefPtr<NG::ChainedRotateEffect>(rotate);
617         }
618     }
619     return nullptr;
620 }
621 
ParseChainedOpacityTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)622 RefPtr<NG::ChainedTransitionEffect> ParseChainedOpacityTransition(
623     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
624 {
625     double opacity = 1.0;
626     if (JSViewAbstract::ParseJsDouble(effectOption, opacity)) {
627         if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
628             if (LessNotEqual(opacity, 0.0) || opacity > 1.0) {
629                 opacity = 1.0;
630             }
631         } else {
632             opacity = std::clamp(opacity, 0.0, 1.0);
633         }
634         return AceType::MakeRefPtr<NG::ChainedOpacityEffect>(opacity);
635     }
636     return nullptr;
637 }
638 
ParseChainedTranslateTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)639 RefPtr<NG::ChainedTransitionEffect> ParseChainedTranslateTransition(
640     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
641 {
642     if (effectOption->IsObject()) {
643         // default: x, y, z (0.0, 0.0, 0.0)
644         NG::TranslateOptions translate;
645         ParseJsTranslate(effectOption, translate.x, translate.y, translate.z);
646         return AceType::MakeRefPtr<NG::ChainedTranslateEffect>(translate);
647     }
648     return nullptr;
649 }
650 
ParseChainedScaleTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)651 RefPtr<NG::ChainedTransitionEffect> ParseChainedScaleTransition(
652     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
653 {
654     if (effectOption->IsObject()) {
655         // default: x, y, z (1.0, 1.0, 1.0), centerX, centerY 50% 50%;
656         NG::ScaleOptions scale(1.0f, 1.0f, 1.0f, 0.5_pct, 0.5_pct);
657         ParseJsScale(effectOption, scale.xScale, scale.yScale, scale.zScale, scale.centerX, scale.centerY);
658         return AceType::MakeRefPtr<NG::ChainedScaleEffect>(scale);
659     }
660     return nullptr;
661 }
662 
ParseChainedMoveTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)663 RefPtr<NG::ChainedTransitionEffect> ParseChainedMoveTransition(
664     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
665 {
666     int32_t edge = 0;
667     if (JSViewAbstract::ParseJsInt32(effectOption, edge)) {
668         if (edge < static_cast<int32_t>(NG::TransitionEdge::TOP) ||
669             edge > static_cast<int32_t>(NG::TransitionEdge::END)) {
670             edge = static_cast<int32_t>(NG::TransitionEdge::START);
671         }
672         return AceType::MakeRefPtr<NG::ChainedMoveEffect>(static_cast<NG::TransitionEdge>(edge));
673     }
674     return nullptr;
675 }
676 
ParseChainedAsymmetricTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)677 RefPtr<NG::ChainedTransitionEffect> ParseChainedAsymmetricTransition(
678     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
679 {
680     if (effectOption->IsObject()) {
681         auto effectObj = JSRef<JSObject>::Cast(effectOption);
682         auto appearJsVal = effectObj->GetProperty("appear");
683         auto disappearJsVal = effectObj->GetProperty("disappear");
684         RefPtr<NG::ChainedTransitionEffect> appearEffect;
685         RefPtr<NG::ChainedTransitionEffect> disappearEffect;
686         if (appearJsVal->IsObject()) {
687             auto appearObj = JSRef<JSObject>::Cast(appearJsVal);
688             appearEffect = ParseChainedTransition(appearObj, context);
689         }
690         if (disappearJsVal->IsObject()) {
691             auto disappearObj = JSRef<JSObject>::Cast(disappearJsVal);
692             disappearEffect = ParseChainedTransition(disappearObj, context);
693         }
694         return AceType::MakeRefPtr<NG::ChainedAsymmetricEffect>(appearEffect, disappearEffect);
695     }
696     return nullptr;
697 }
698 
GetFormAnimationTimeInterval(const RefPtr<PipelineBase> & pipelineContext)699 int64_t GetFormAnimationTimeInterval(const RefPtr<PipelineBase>& pipelineContext)
700 {
701     CHECK_NULL_RETURN(pipelineContext, 0);
702     return (GetMicroTickCount() - pipelineContext->GetFormAnimationStartTime()) / MICROSEC_TO_MILLISEC;
703 }
704 
705 using ChainedTransitionEffectCreator = RefPtr<NG::ChainedTransitionEffect> (*)(
706     const JSRef<JSVal>&, const JSExecutionContext&);
707 
ParseChainedTransition(const JSRef<JSObject> & object,const JSExecutionContext & context)708 RefPtr<NG::ChainedTransitionEffect> ParseChainedTransition(
709     const JSRef<JSObject>& object, const JSExecutionContext& context)
710 {
711     auto propType = object->GetProperty("type_");
712     if (!propType->IsString()) {
713         return nullptr;
714     }
715     std::string type = propType->ToString();
716     auto propEffectOption = object->GetProperty("effect_");
717     auto propAnimationOption = object->GetProperty("animation_");
718     auto propSuccessor = object->GetProperty("successor_");
719     static const LinearMapNode<ChainedTransitionEffectCreator> creatorMap[] = {
720         { "asymmetric", ParseChainedAsymmetricTransition },
721         { "identity",
722             [](const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
723                 -> RefPtr<NG::ChainedTransitionEffect> { return AceType::MakeRefPtr<NG::ChainedIdentityEffect>(); } },
724         { "move", ParseChainedMoveTransition },
725         { "opacity", ParseChainedOpacityTransition },
726         { "rotate", ParseChainedRotateTransition },
727         { "scale", ParseChainedScaleTransition },
728         { "slideSwitch",
729             [](const JSRef<JSVal>& effectOption,
730                 const JSExecutionContext& context) -> RefPtr<NG::ChainedTransitionEffect> {
731                 return AceType::MakeRefPtr<NG::ChainedSlideSwitchEffect>();
732             } },
733         { "translate", ParseChainedTranslateTransition },
734     };
735     int64_t index = BinarySearchFindIndex(creatorMap, ArraySize(creatorMap), type.c_str());
736     if (index < 0) {
737         return nullptr;
738     }
739     RefPtr<NG::ChainedTransitionEffect> result = creatorMap[index].value(propEffectOption, context);
740     if (!result) {
741         return nullptr;
742     }
743     if (propAnimationOption->IsObject()) {
744         auto container = Container::Current();
745         CHECK_NULL_RETURN(container, nullptr);
746         auto pipelineContext = container->GetPipelineContext();
747         CHECK_NULL_RETURN(pipelineContext, nullptr);
748         auto animationOptionResult = std::make_shared<AnimationOption>(
749             JSViewContext::CreateAnimation(propAnimationOption, pipelineContext->IsFormRender()));
750         // The maximum of the form-animation-playback duration value is 1000 ms.
751         if (pipelineContext->IsFormRender() && pipelineContext->IsFormAnimation()) {
752             auto formAnimationTimeInterval = GetFormAnimationTimeInterval(pipelineContext);
753             // If the duration exceeds 1000ms, init it to 0 ms.
754             if (formAnimationTimeInterval > DEFAULT_DURATION) {
755                 animationOptionResult->SetDuration(0);
756             } else if (animationOptionResult->GetDuration() > (DEFAULT_DURATION - formAnimationTimeInterval)) {
757                 // If remaining time is less than 1000ms, check for update duration.
758                 animationOptionResult->SetDuration(DEFAULT_DURATION - formAnimationTimeInterval);
759                 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation]  Form Transition SetDuration: %{public}lld ms",
760                     static_cast<long long>(DEFAULT_DURATION - formAnimationTimeInterval));
761             }
762         }
763         auto animationOptionObj = JSRef<JSObject>::Cast(propAnimationOption);
764         JSRef<JSVal> onFinish = animationOptionObj->GetProperty("onFinish");
765         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
766         if (onFinish->IsFunction()) {
767             RefPtr<JsFunction> jsFunc =
768                 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onFinish));
769             std::function<void()> onFinishEvent = [execCtx = context, func = std::move(jsFunc),
770                                                       id = Container::CurrentId(), node = targetNode]() {
771                 ContainerScope scope(id);
772                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
773                 PipelineContext::SetCallBackNode(node);
774                 func->Execute();
775             };
776             animationOptionResult->SetOnFinishEvent(onFinishEvent);
777         }
778         result->SetAnimationOption(animationOptionResult);
779     }
780     if (propSuccessor->IsObject()) {
781         result->SetNext(ParseChainedTransition(JSRef<JSObject>::Cast(propSuccessor), context));
782     }
783     return result;
784 }
785 
786 #ifndef WEARABLE_PRODUCT
787 const std::vector<Placement> PLACEMENT = { Placement::LEFT, Placement::RIGHT, Placement::TOP, Placement::BOTTOM,
788     Placement::TOP_LEFT, Placement::TOP_RIGHT, Placement::BOTTOM_LEFT, Placement::BOTTOM_RIGHT, Placement::LEFT_TOP,
789     Placement::LEFT_BOTTOM, Placement::RIGHT_TOP, Placement::RIGHT_BOTTOM };
790 
ParseDoubleBindCallback(const JSCallbackInfo & info,const JSRef<JSObject> & callbackObj)791 DoubleBindCallback ParseDoubleBindCallback(const JSCallbackInfo& info, const JSRef<JSObject>& callbackObj)
792 {
793     JSRef<JSVal> changeEvent = callbackObj->GetProperty("changeEvent");
794     if (!changeEvent->IsFunction()) {
795         return {};
796     }
797     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEvent));
798     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
799     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
800                         const std::string& param) {
801         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
802         if (param != "true" && param != "false") {
803             return;
804         }
805         PipelineContext::SetCallBackNode(node);
806         bool newValue = StringToBool(param);
807         JSRef<JSVal> newJSVal = JSRef<JSVal>::Make(ToJSValue(newValue));
808         func->ExecuteJS(1, &newJSVal);
809     };
810     return callback;
811 }
812 
SetPopupMessageOptions(const JSRef<JSObject> messageOptionsObj,const RefPtr<PopupParam> & popupParam)813 void SetPopupMessageOptions(const JSRef<JSObject> messageOptionsObj, const RefPtr<PopupParam>& popupParam)
814 {
815     auto colorValue = messageOptionsObj->GetProperty("textColor");
816     Color textColor;
817     if (JSViewAbstract::ParseJsColor(colorValue, textColor)) {
818         if (popupParam) {
819             popupParam->SetTextColor(textColor);
820         }
821     }
822 
823     auto font = messageOptionsObj->GetProperty("font");
824     if (!font->IsNull() && font->IsObject()) {
825         JSRef<JSObject> fontObj = JSRef<JSObject>::Cast(font);
826         auto fontSizeValue = fontObj->GetProperty(static_cast<int32_t>(ArkUIIndex::SIZE));
827         CalcDimension fontSize;
828         if (JSViewAbstract::ParseJsDimensionFp(fontSizeValue, fontSize)) {
829             if (popupParam && fontSize.IsValid()) {
830                 popupParam->SetFontSize(fontSize);
831             }
832         }
833         auto fontWeightValue = fontObj->GetProperty(static_cast<int32_t>(ArkUIIndex::WEIGHT));
834         if (fontWeightValue->IsString()) {
835             if (popupParam) {
836                 popupParam->SetFontWeight(ConvertStrToFontWeight(fontWeightValue->ToString()));
837             }
838         }
839         auto fontStyleValue = fontObj->GetProperty(static_cast<int32_t>(ArkUIIndex::STYLE));
840         if (fontStyleValue->IsNumber()) {
841             int32_t value = fontStyleValue->ToNumber<int32_t>();
842             if (value < 0 || value >= static_cast<int32_t>(FONT_STYLES.size())) {
843                 return;
844             }
845             if (popupParam) {
846                 popupParam->SetFontStyle(FONT_STYLES[value]);
847             }
848         }
849     }
850 }
851 
SetPlacementOnTopVal(const JSRef<JSObject> & popupObj,const RefPtr<PopupParam> & popupParam)852 void SetPlacementOnTopVal(const JSRef<JSObject>& popupObj, const RefPtr<PopupParam>& popupParam)
853 {
854     JSRef<JSVal> placementOnTopVal = popupObj->GetProperty("placementOnTop");
855     if (placementOnTopVal->IsBoolean() && popupParam) {
856         popupParam->SetPlacement(placementOnTopVal->ToBoolean() ? Placement::TOP : Placement::BOTTOM);
857     }
858 }
859 
IsPopupCreated()860 bool IsPopupCreated()
861 {
862     auto targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
863     CHECK_NULL_RETURN(targetNode, false);
864     auto targetId = targetNode->GetId();
865     auto container = Container::Current();
866     CHECK_NULL_RETURN(container, false);
867     auto pipelineContext = container->GetPipelineContext();
868     CHECK_NULL_RETURN(pipelineContext, false);
869     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
870     CHECK_NULL_RETURN(context, false);
871     auto overlayManager = context->GetOverlayManager();
872     CHECK_NULL_RETURN(overlayManager, false);
873     auto popupInfo = overlayManager->GetPopupInfo(targetId);
874     if (popupInfo.popupId == -1 || !popupInfo.popupNode) {
875         return false;
876     }
877     return true;
878 }
879 
ParsePopupCommonParam(const JSCallbackInfo & info,const JSRef<JSObject> & popupObj,const RefPtr<PopupParam> & popupParam)880 void ParsePopupCommonParam(
881     const JSCallbackInfo& info, const JSRef<JSObject>& popupObj, const RefPtr<PopupParam>& popupParam)
882 {
883     auto arrowOffset = popupObj->GetProperty("arrowOffset");
884     CalcDimension offset;
885     if (JSViewAbstract::ParseJsDimensionVp(arrowOffset, offset)) {
886         if (popupParam) {
887             popupParam->SetArrowOffset(offset);
888         }
889     }
890 
891     auto arrowPointPosition = popupObj->GetProperty("arrowPointPosition");
892     if (arrowPointPosition->IsString()) {
893         char* pEnd = nullptr;
894         auto arrowString = arrowPointPosition->ToString();
895         std::strtod(arrowString.c_str(), &pEnd);
896         if (pEnd != nullptr) {
897             if (std::strcmp(pEnd, "Start") == 0) {
898                 offset = ARROW_ZERO_PERCENT_VALUE;
899             }
900             if (std::strcmp(pEnd, "Center") == 0) {
901                 offset = ARROW_HALF_PERCENT_VALUE;
902             }
903             if (std::strcmp(pEnd, "End") == 0) {
904                 offset = ARROW_ONE_HUNDRED_PERCENT_VALUE;
905             }
906             if (popupParam) {
907                 popupParam->SetArrowOffset(offset);
908             }
909         }
910     }
911 
912     auto targetSpace = popupObj->GetProperty("targetSpace");
913     if (!targetSpace->IsNull()) {
914         CalcDimension space;
915         if (JSViewAbstract::ParseJsDimensionVp(targetSpace, space)) {
916             if (popupParam) {
917                 popupParam->SetTargetSpace(space);
918             }
919         }
920     }
921 
922     JSRef<JSVal> showInSubWindowValue = popupObj->GetProperty("showInSubWindow");
923     if (showInSubWindowValue->IsBoolean()) {
924         bool showInSubBoolean = showInSubWindowValue->ToBoolean();
925 #if defined(PREVIEW)
926         if (showInSubBoolean) {
927             LOGI("[Engine Log] Unable to use the SubWindow in the Previewer. Use normal type instead.");
928             showInSubBoolean = false;
929         }
930 #endif
931         if (popupParam) {
932             popupParam->SetShowInSubWindow(showInSubBoolean);
933         }
934     }
935 
936     auto placementValue = popupObj->GetProperty("placement");
937     if (placementValue->IsNumber()) {
938         auto placement = placementValue->ToNumber<int32_t>();
939         if (placement >= 0 && placement <= static_cast<int32_t>(PLACEMENT.size())) {
940             popupParam->SetPlacement(PLACEMENT[placement]);
941         }
942     } else {
943         SetPlacementOnTopVal(popupObj, popupParam);
944     }
945 
946     auto enableArrowValue = popupObj->GetProperty("enableArrow");
947     if (enableArrowValue->IsBoolean()) {
948         popupParam->SetEnableArrow(enableArrowValue->ToBoolean());
949     }
950 
951     auto followTransformOfTargetValue = popupObj->GetProperty("followTransformOfTarget");
952     if (followTransformOfTargetValue->IsBoolean()) {
953         popupParam->SetFollowTransformOfTarget(followTransformOfTargetValue->ToBoolean());
954     }
955 
956     JSRef<JSVal> maskValue = popupObj->GetProperty("mask");
957     if (maskValue->IsBoolean()) {
958         if (popupParam) {
959             popupParam->SetBlockEvent(maskValue->ToBoolean());
960         }
961     }
962     if (maskValue->IsObject()) {
963         auto maskObj = JSRef<JSObject>::Cast(maskValue);
964         auto colorValue = maskObj->GetProperty("color");
965         Color maskColor;
966         if (JSViewAbstract::ParseJsColor(colorValue, maskColor)) {
967             popupParam->SetMaskColor(maskColor);
968         }
969     }
970 
971     JSRef<JSVal> onStateChangeVal = popupObj->GetProperty("onStateChange");
972     if (onStateChangeVal->IsFunction()) {
973         std::vector<std::string> keys = { "isVisible" };
974         RefPtr<JsFunction> jsFunc =
975             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onStateChangeVal));
976         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
977         if (popupParam) {
978             auto onStateChangeCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), keys,
979                                              node = targetNode](const std::string& param) {
980                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
981                 ACE_SCORING_EVENT("Popup.onStateChange");
982                 PipelineContext::SetCallBackNode(node);
983                 func->Execute(keys, param);
984             };
985             popupParam->SetOnStateChange(onStateChangeCallback);
986         }
987     }
988 
989     auto offsetVal = popupObj->GetProperty("offset");
990     if (offsetVal->IsObject()) {
991         auto offsetObj = JSRef<JSObject>::Cast(offsetVal);
992         auto xVal = offsetObj->GetProperty("x");
993         auto yVal = offsetObj->GetProperty("y");
994         Offset popupOffset;
995         CalcDimension dx;
996         CalcDimension dy;
997         if (JSViewAbstract::ParseJsDimensionVp(xVal, dx)) {
998             popupOffset.SetX(dx.ConvertToPx());
999         }
1000         if (JSViewAbstract::ParseJsDimensionVp(yVal, dy)) {
1001             popupOffset.SetY(dy.ConvertToPx());
1002         }
1003         if (popupParam) {
1004             popupParam->SetTargetOffset(popupOffset);
1005         }
1006     }
1007 
1008     Color backgroundColor;
1009     auto popupColorVal = popupObj->GetProperty("popupColor");
1010     if (JSViewAbstract::ParseJsColor(popupColorVal, backgroundColor)) {
1011         popupParam->SetBackgroundColor(backgroundColor);
1012     }
1013 
1014     auto autoCancelVal = popupObj->GetProperty("autoCancel");
1015     if (autoCancelVal->IsBoolean()) {
1016         popupParam->SetHasAction(!autoCancelVal->ToBoolean());
1017     }
1018 
1019     auto childWidthVal = popupObj->GetProperty("width");
1020     if (!childWidthVal->IsNull()) {
1021         CalcDimension width;
1022         if (JSViewAbstract::ParseJsDimensionVp(childWidthVal, width)) {
1023             if (width.Value() > 0) {
1024                 popupParam->SetChildWidth(width);
1025             }
1026         }
1027     }
1028 
1029     auto arrowWidthVal = popupObj->GetProperty("arrowWidth");
1030     if (!arrowWidthVal->IsNull()) {
1031         bool setError = true;
1032         CalcDimension arrowWidth;
1033         if (JSViewAbstract::ParseJsDimensionVp(arrowWidthVal, arrowWidth)) {
1034             if (arrowWidth.Value() > 0 && arrowWidth.Unit() != DimensionUnit::PERCENT) {
1035                 popupParam->SetArrowWidth(arrowWidth);
1036                 setError = false;
1037             }
1038         }
1039         popupParam->SetErrorArrowWidth(setError);
1040     }
1041 
1042     auto arrowHeightVal = popupObj->GetProperty("arrowHeight");
1043     if (!arrowHeightVal->IsNull()) {
1044         bool setError = true;
1045         CalcDimension arrowHeight;
1046         if (JSViewAbstract::ParseJsDimensionVp(arrowHeightVal, arrowHeight)) {
1047             if (arrowHeight.Value() > 0 && arrowHeight.Unit() != DimensionUnit::PERCENT) {
1048                 popupParam->SetArrowHeight(arrowHeight);
1049                 setError = false;
1050             }
1051         }
1052         popupParam->SetErrorArrowHeight(setError);
1053     }
1054 
1055     auto radiusVal = popupObj->GetProperty("radius");
1056     if (!radiusVal->IsNull()) {
1057         bool setError = true;
1058         CalcDimension radius;
1059         if (JSViewAbstract::ParseJsDimensionVp(radiusVal, radius)) {
1060             if (radius.Value() >= 0) {
1061                 popupParam->SetRadius(radius);
1062                 setError = false;
1063             }
1064         }
1065         popupParam->SetErrorRadius(setError);
1066     }
1067 
1068     Shadow shadow;
1069     auto shadowVal = popupObj->GetProperty("shadow");
1070     if (shadowVal->IsObject() || shadowVal->IsNumber()) {
1071         auto ret = JSViewAbstract::ParseShadowProps(shadowVal, shadow);
1072         if (!ret) {
1073             JSViewAbstract::GetShadowFromTheme(ShadowStyle::OuterDefaultMD, shadow);
1074         }
1075     } else {
1076         JSViewAbstract::GetShadowFromTheme(ShadowStyle::OuterDefaultMD, shadow);
1077     }
1078     popupParam->SetShadow(shadow);
1079 
1080     auto blurStyleValue = popupObj->GetProperty("backgroundBlurStyle");
1081     if (blurStyleValue->IsNumber()) {
1082         auto blurStyle = blurStyleValue->ToNumber<int32_t>();
1083         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
1084             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
1085             popupParam->SetBlurStyle(static_cast<BlurStyle>(blurStyle));
1086         }
1087     }
1088 
1089     auto popupTransition = popupObj->GetProperty("transition");
1090     if (popupTransition->IsObject()) {
1091         popupParam->SetHasTransition(true);
1092         auto obj = JSRef<JSObject>::Cast(popupTransition);
1093         auto effects = ParseChainedTransition(obj, info.GetExecutionContext());
1094         popupParam->SetTransitionEffects(effects);
1095     }
1096 }
1097 
ParsePopupParam(const JSCallbackInfo & info,const JSRef<JSObject> & popupObj,const RefPtr<PopupParam> & popupParam)1098 void ParsePopupParam(const JSCallbackInfo& info, const JSRef<JSObject>& popupObj, const RefPtr<PopupParam>& popupParam)
1099 {
1100     ParsePopupCommonParam(info, popupObj, popupParam);
1101     JSRef<JSVal> messageVal = popupObj->GetProperty("message");
1102     if (popupParam) {
1103         popupParam->SetMessage(messageVal->ToString());
1104     }
1105 
1106     auto messageOptions = popupObj->GetProperty("messageOptions");
1107     JSRef<JSObject> messageOptionsObj;
1108     if (!messageOptions->IsNull() && messageOptions->IsObject()) {
1109         messageOptionsObj = JSRef<JSObject>::Cast(messageOptions);
1110         SetPopupMessageOptions(messageOptionsObj, popupParam);
1111     }
1112 
1113     JSRef<JSVal> primaryButtonVal = popupObj->GetProperty("primaryButton");
1114     if (primaryButtonVal->IsObject()) {
1115         ButtonProperties properties;
1116         JSRef<JSObject> obj = JSRef<JSObject>::Cast(primaryButtonVal);
1117         JSRef<JSVal> value = obj->GetProperty("value");
1118         if (value->IsString()) {
1119             properties.value = value->ToString();
1120         }
1121 
1122         JSRef<JSVal> actionValue = obj->GetProperty("action");
1123         if (actionValue->IsFunction()) {
1124             auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(actionValue));
1125             auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1126             if (popupParam) {
1127                 auto clickCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc),
1128                                          node = targetNode](GestureEvent& info) {
1129                     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1130                     ACE_SCORING_EVENT("primaryButton.action");
1131                     PipelineContext::SetCallBackNode(node);
1132                     func->Execute(info);
1133                 };
1134                 properties.action = AceType::MakeRefPtr<NG::ClickEvent>(clickCallback);
1135             }
1136         }
1137         properties.showButton = true;
1138         if (popupParam) {
1139             popupParam->SetPrimaryButtonProperties(properties);
1140         }
1141     }
1142 
1143     JSRef<JSVal> secondaryButtonVal = popupObj->GetProperty("secondaryButton");
1144     if (secondaryButtonVal->IsObject()) {
1145         ButtonProperties properties;
1146         JSRef<JSObject> obj = JSRef<JSObject>::Cast(secondaryButtonVal);
1147         JSRef<JSVal> value = obj->GetProperty("value");
1148         if (value->IsString()) {
1149             properties.value = value->ToString();
1150         }
1151 
1152         JSRef<JSVal> actionValue = obj->GetProperty("action");
1153         if (actionValue->IsFunction()) {
1154             auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(actionValue));
1155             auto targetNode =
1156                 AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1157             if (popupParam) {
1158                 auto clickCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc),
1159                                          node = targetNode](GestureEvent& info) {
1160                     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1161                     ACE_SCORING_EVENT("secondaryButton.action");
1162                     PipelineContext::SetCallBackNode(node);
1163                     func->Execute(info);
1164                 };
1165                 properties.action = AceType::MakeRefPtr<NG::ClickEvent>(clickCallback);
1166             }
1167         }
1168         properties.showButton = true;
1169         if (popupParam) {
1170             popupParam->SetSecondaryButtonProperties(properties);
1171         }
1172     }
1173 }
1174 
ParseCustomPopupParam(const JSCallbackInfo & info,const JSRef<JSObject> & popupObj,const RefPtr<PopupParam> & popupParam)1175 void ParseCustomPopupParam(
1176     const JSCallbackInfo& info, const JSRef<JSObject>& popupObj, const RefPtr<PopupParam>& popupParam)
1177 {
1178     auto builderValue = popupObj->GetProperty("builder");
1179     if (!builderValue->IsObject()) {
1180         return;
1181     }
1182     if (!builderValue->IsFunction()) {
1183         JSRef<JSObject> builderObj;
1184         builderObj = JSRef<JSObject>::Cast(builderValue);
1185         auto builder = builderObj->GetProperty("builder");
1186         if (!builder->IsFunction()) {
1187             return;
1188         }
1189         auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
1190         if (!builderFunc) {
1191             return;
1192         }
1193     }
1194     if (popupParam) {
1195         popupParam->SetUseCustomComponent(true);
1196     }
1197 
1198     auto focusableValue = popupObj->GetProperty("focusable");
1199     if (focusableValue->IsBoolean()) {
1200         popupParam->SetFocusable(focusableValue->ToBoolean());
1201     }
1202 
1203     ParsePopupCommonParam(info, popupObj, popupParam);
1204 }
1205 #endif
1206 
GetBundleNameFromContainer()1207 std::string GetBundleNameFromContainer()
1208 {
1209     auto container = Container::Current();
1210     CHECK_NULL_RETURN(container, "");
1211     return container->GetBundleName();
1212 }
1213 
GetModuleNameFromContainer()1214 std::string GetModuleNameFromContainer()
1215 {
1216     auto container = Container::Current();
1217     CHECK_NULL_RETURN(container, "");
1218     return container->GetModuleName();
1219 }
1220 
CompleteResourceObjectFromParams(int32_t resId,JSRef<JSObject> & jsObj,std::string & targetModule,ResourceType & resType,std::string & resName)1221 void CompleteResourceObjectFromParams(
1222     int32_t resId, JSRef<JSObject>& jsObj, std::string& targetModule, ResourceType& resType, std::string& resName)
1223 {
1224     JSRef<JSVal> type = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::TYPE));
1225     int32_t typeNum = -1;
1226     if (type->IsNumber()) {
1227         typeNum = type->ToNumber<int32_t>();
1228     }
1229 
1230     JSRef<JSVal> args = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::PARAMS));
1231     if (!args->IsArray()) {
1232         return;
1233     }
1234     JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
1235     if (resId != UNKNOWN_RESOURCE_ID) {
1236         return;
1237     }
1238     JSRef<JSVal> identity = params->GetValueAt(0);
1239 
1240     bool isParseDollarResourceSuccess =
1241         JSViewAbstract::ParseDollarResource(identity, targetModule, resType, resName, typeNum == UNKNOWN_RESOURCE_TYPE);
1242     if (!isParseDollarResourceSuccess) {
1243         return;
1244     }
1245 
1246     std::regex resNameRegex(RESOURCE_NAME_PATTERN);
1247     std::smatch resNameResults;
1248     if (std::regex_match(targetModule, resNameResults, resNameRegex)) {
1249         jsObj->SetProperty<std::string>(static_cast<int32_t>(ArkUIIndex::MODULE_NAME), resNameResults[1]);
1250     }
1251 
1252     if (typeNum == UNKNOWN_RESOURCE_TYPE) {
1253         jsObj->SetProperty<int32_t>(static_cast<int32_t>(ArkUIIndex::TYPE), static_cast<int32_t>(resType));
1254     }
1255 }
1256 
CompleteResourceObjectFromId(JSRef<JSVal> & type,JSRef<JSObject> & jsObj,ResourceType & resType,const std::string & resName)1257 void CompleteResourceObjectFromId(
1258     JSRef<JSVal>& type, JSRef<JSObject>& jsObj, ResourceType& resType, const std::string& resName)
1259 {
1260     JSRef<JSVal> args = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::PARAMS));
1261     if (!args->IsArray()) {
1262         return;
1263     }
1264     JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
1265     auto paramCount = params->Length();
1266     JSRef<JSVal> name = JSRef<JSVal>::Make(ToJSValue(resName));
1267     if (resType == ResourceType::PLURAL || resType == ResourceType::STRING) {
1268         std::vector<JSRef<JSVal>> tmpParams;
1269         for (uint32_t i = 0; i < paramCount; i++) {
1270             auto param = params->GetValueAt(i);
1271             tmpParams.insert(tmpParams.end(), param);
1272         }
1273         params->SetValueAt(0, name);
1274         uint32_t paramIndex = 1;
1275         if (!type->IsEmpty()) {
1276             params->SetValueAt(paramIndex, type);
1277             paramIndex++;
1278         }
1279         for (auto tmpParam : tmpParams) {
1280             params->SetValueAt(paramIndex, tmpParam);
1281             paramIndex++;
1282         }
1283     } else {
1284         params->SetValueAt(0, name);
1285     }
1286     jsObj->SetProperty<int32_t>(static_cast<int32_t>(ArkUIIndex::ID), UNKNOWN_RESOURCE_ID);
1287     jsObj->SetProperty<int32_t>(static_cast<int32_t>(ArkUIIndex::TYPE), static_cast<int32_t>(resType));
1288     if (!jsObj->HasProperty(static_cast<int32_t>(ArkUIIndex::BUNDLE_NAME))) {
1289         jsObj->SetProperty<std::string>(static_cast<int32_t>(ArkUIIndex::BUNDLE_NAME), "");
1290     }
1291     if (!jsObj->HasProperty(static_cast<int32_t>(ArkUIIndex::MODULE_NAME))) {
1292         jsObj->SetProperty<std::string>(static_cast<int32_t>(ArkUIIndex::MODULE_NAME), "");
1293     }
1294 }
1295 
CheckDimensionUnit(CalcDimension & checkDimension,bool notPercent,bool notNegative)1296 void CheckDimensionUnit(CalcDimension& checkDimension, bool notPercent, bool notNegative)
1297 {
1298     if (notPercent && checkDimension.Unit() == DimensionUnit::PERCENT) {
1299         checkDimension.Reset();
1300         return;
1301     }
1302     if (notNegative && checkDimension.IsNegative()) {
1303         checkDimension.Reset();
1304         return;
1305     }
1306 }
1307 
ParseEdgeColors(const JSRef<JSObject> & object,CommonColor & commonColor)1308 void ParseEdgeColors(const JSRef<JSObject>& object, CommonColor& commonColor)
1309 {
1310     Color left;
1311     if (JSViewAbstract::ParseJsColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::LEFT)), left)) {
1312         commonColor.left = left;
1313     }
1314     Color right;
1315     if (JSViewAbstract::ParseJsColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::RIGHT)), right)) {
1316         commonColor.right = right;
1317     }
1318     Color top;
1319     if (JSViewAbstract::ParseJsColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP)), top)) {
1320         commonColor.top = top;
1321     }
1322     Color bottom;
1323     if (JSViewAbstract::ParseJsColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM)), bottom)) {
1324         commonColor.bottom = bottom;
1325     }
1326 }
1327 
ParseLocalizedEdgeColors(const JSRef<JSObject> & object,LocalizedColor & localizedColor)1328 void ParseLocalizedEdgeColors(const JSRef<JSObject>& object, LocalizedColor& localizedColor)
1329 {
1330     Color start;
1331     if (JSViewAbstract::ParseJsColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::START)), start)) {
1332         localizedColor.start = start;
1333     }
1334     Color end;
1335     if (JSViewAbstract::ParseJsColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::END)), end)) {
1336         localizedColor.end = end;
1337     }
1338     Color top;
1339     if (JSViewAbstract::ParseJsColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP)), top)) {
1340         localizedColor.top = top;
1341     }
1342     Color bottom;
1343     if (JSViewAbstract::ParseJsColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM)), bottom)) {
1344         localizedColor.bottom = bottom;
1345     }
1346 }
1347 
ParseCommonEdgeColors(const JSRef<JSObject> & object,CommonColor & commonColor)1348 bool ParseCommonEdgeColors(const JSRef<JSObject>& object, CommonColor& commonColor)
1349 {
1350     if (object->HasProperty(static_cast<int32_t>(ArkUIIndex::START)) ||
1351         object->HasProperty(static_cast<int32_t>(ArkUIIndex::END))) {
1352         LocalizedColor localizedColor;
1353         ParseLocalizedEdgeColors(object, localizedColor);
1354         commonColor.top = localizedColor.top;
1355         commonColor.bottom = localizedColor.bottom;
1356         commonColor.left = localizedColor.start;
1357         commonColor.right = localizedColor.end;
1358         return true;
1359     }
1360     ParseEdgeColors(object, commonColor);
1361     return false;
1362 }
1363 
ParseEdgeWidths(const JSRef<JSObject> & object,CommonCalcDimension & commonCalcDimension,bool notNegative)1364 void ParseEdgeWidths(const JSRef<JSObject>& object, CommonCalcDimension& commonCalcDimension, bool notNegative)
1365 {
1366     CalcDimension left;
1367     if (JSViewAbstract::ParseJsDimensionVp(object->GetProperty(LEFT_PROPERTY), left)) {
1368         CheckDimensionUnit(left, true, notNegative);
1369         commonCalcDimension.left = left;
1370     }
1371     CalcDimension right;
1372     if (JSViewAbstract::ParseJsDimensionVp(object->GetProperty(RIGHT_PROPERTY), right)) {
1373         CheckDimensionUnit(right, true, notNegative);
1374         commonCalcDimension.right = right;
1375     }
1376     CalcDimension top;
1377     if (JSViewAbstract::ParseJsDimensionVp(object->GetProperty(TOP_PROPERTY), top)) {
1378         CheckDimensionUnit(top, true, notNegative);
1379         commonCalcDimension.top = top;
1380     }
1381     CalcDimension bottom;
1382     if (JSViewAbstract::ParseJsDimensionVp(object->GetProperty(BOTTOM_PROPERTY), bottom)) {
1383         CheckDimensionUnit(bottom, true, notNegative);
1384         commonCalcDimension.bottom = bottom;
1385     }
1386 }
1387 
ParseEdgeWidthsProps(const JSRef<JSObject> & object,CommonCalcDimension & commonCalcDimension,bool notPercent,bool notNegative,CalcDimension defaultValue)1388 void ParseEdgeWidthsProps(const JSRef<JSObject>& object, CommonCalcDimension& commonCalcDimension, bool notPercent,
1389     bool notNegative, CalcDimension defaultValue)
1390 {
1391     CalcDimension left;
1392     if (JSViewAbstract::ParseJsDimensionVpNG(object->GetProperty(LEFT_PROPERTY), left, true)) {
1393         CheckDimensionUnit(left, notPercent, notNegative);
1394         commonCalcDimension.left = left;
1395     } else {
1396         commonCalcDimension.left = defaultValue;
1397     }
1398     CalcDimension right;
1399     if (JSViewAbstract::ParseJsDimensionVpNG(object->GetProperty(RIGHT_PROPERTY), right, true)) {
1400         CheckDimensionUnit(right, notPercent, notNegative);
1401         commonCalcDimension.right = right;
1402     } else {
1403         commonCalcDimension.right = defaultValue;
1404     }
1405     CalcDimension top;
1406     if (JSViewAbstract::ParseJsDimensionVpNG(object->GetProperty(TOP_PROPERTY), top, true)) {
1407         CheckDimensionUnit(top, notPercent, notNegative);
1408         commonCalcDimension.top = top;
1409     } else {
1410         commonCalcDimension.top = defaultValue;
1411     }
1412     CalcDimension bottom;
1413     if (JSViewAbstract::ParseJsDimensionVpNG(object->GetProperty(BOTTOM_PROPERTY), bottom, true)) {
1414         CheckDimensionUnit(bottom, false, true);
1415         commonCalcDimension.bottom = bottom;
1416     } else {
1417         commonCalcDimension.bottom = defaultValue;
1418     }
1419 }
1420 
ParseLocalizedEdgeWidths(const JSRef<JSObject> & object,LocalizedCalcDimension & localizedCalcDimension,bool notNegative)1421 void ParseLocalizedEdgeWidths(const JSRef<JSObject>& object, LocalizedCalcDimension& localizedCalcDimension,
1422                               bool notNegative)
1423 {
1424     auto jsStart = object->GetProperty(static_cast<int32_t>(ArkUIIndex::START));
1425     if (jsStart->IsObject()) {
1426         JSRef<JSObject> startObj = JSRef<JSObject>::Cast(jsStart);
1427         CalcDimension calcDimension;
1428         if (ParseJsLengthMetrics(startObj, calcDimension)) {
1429             CheckDimensionUnit(calcDimension, true, notNegative);
1430             localizedCalcDimension.start = calcDimension;
1431         }
1432     }
1433     auto jsEnd = object->GetProperty(static_cast<int32_t>(ArkUIIndex::END));
1434     if (jsEnd->IsObject()) {
1435         JSRef<JSObject> endObj = JSRef<JSObject>::Cast(jsEnd);
1436         CalcDimension calcDimension;
1437         if (ParseJsLengthMetrics(endObj, calcDimension)) {
1438             CheckDimensionUnit(calcDimension, true, notNegative);
1439             localizedCalcDimension.end = calcDimension;
1440         }
1441     }
1442     auto jsTop = object->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP));
1443     if (jsTop->IsObject()) {
1444         JSRef<JSObject> topObj = JSRef<JSObject>::Cast(jsTop);
1445         CalcDimension calcDimension;
1446         if (ParseJsLengthMetrics(topObj, calcDimension)) {
1447             CheckDimensionUnit(calcDimension, true, notNegative);
1448             localizedCalcDimension.top = calcDimension;
1449         }
1450     }
1451     auto jsBottom = object->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM));
1452     if (jsBottom->IsObject()) {
1453         JSRef<JSObject> bottomObj = JSRef<JSObject>::Cast(jsBottom);
1454         CalcDimension calcDimension;
1455         if (ParseJsLengthMetrics(bottomObj, calcDimension)) {
1456             CheckDimensionUnit(calcDimension, true, notNegative);
1457             localizedCalcDimension.bottom = calcDimension;
1458         }
1459     }
1460 }
1461 
ParseLocalizedEdgeWidthsProps(const JSRef<JSObject> & object,LocalizedCalcDimension & localizedCalcDimension)1462 void ParseLocalizedEdgeWidthsProps(const JSRef<JSObject>& object, LocalizedCalcDimension& localizedCalcDimension)
1463 {
1464     if (object->HasProperty(START_PROPERTY) && object->GetProperty(START_PROPERTY)->IsObject()) {
1465         JSRef<JSObject> startObj = JSRef<JSObject>::Cast(object->GetProperty(START_PROPERTY));
1466         CalcDimension calcDimension;
1467         if (ParseJsLengthMetrics(startObj, calcDimension)) {
1468             CheckDimensionUnit(calcDimension, false, true);
1469             localizedCalcDimension.start = calcDimension;
1470         }
1471     }
1472     if (object->HasProperty(END_PROPERTY) && object->GetProperty(END_PROPERTY)->IsObject()) {
1473         JSRef<JSObject> endObj = JSRef<JSObject>::Cast(object->GetProperty(END_PROPERTY));
1474         CalcDimension calcDimension;
1475         if (ParseJsLengthMetrics(endObj, calcDimension)) {
1476             CheckDimensionUnit(calcDimension, false, true);
1477             localizedCalcDimension.end = calcDimension;
1478         }
1479     }
1480     if (object->HasProperty(TOP_PROPERTY) && object->GetProperty(TOP_PROPERTY)->IsObject()) {
1481         JSRef<JSObject> topObj = JSRef<JSObject>::Cast(object->GetProperty(TOP_PROPERTY));
1482         CalcDimension calcDimension;
1483         if (ParseJsLengthMetrics(topObj, calcDimension)) {
1484             CheckDimensionUnit(calcDimension, false, true);
1485             localizedCalcDimension.top = calcDimension;
1486         }
1487     }
1488     if (object->HasProperty(BOTTOM_PROPERTY) && object->GetProperty(BOTTOM_PROPERTY)->IsObject()) {
1489         JSRef<JSObject> bottomObj = JSRef<JSObject>::Cast(object->GetProperty(BOTTOM_PROPERTY));
1490         CalcDimension calcDimension;
1491         if (ParseJsLengthMetrics(bottomObj, calcDimension)) {
1492             CheckDimensionUnit(calcDimension, false, true);
1493             localizedCalcDimension.bottom = calcDimension;
1494         }
1495     }
1496 }
1497 
ParseCommonEdgeWidths(const JSRef<JSObject> & object,CommonCalcDimension & commonCalcDimension,bool notNegative)1498 bool ParseCommonEdgeWidths(const JSRef<JSObject>& object, CommonCalcDimension& commonCalcDimension, bool notNegative)
1499 {
1500     if (CheckLengthMetrics(object)) {
1501         LocalizedCalcDimension localizedCalcDimension;
1502         ParseLocalizedEdgeWidths(object, localizedCalcDimension, notNegative);
1503         commonCalcDimension.top = localizedCalcDimension.top;
1504         commonCalcDimension.bottom = localizedCalcDimension.bottom;
1505         commonCalcDimension.left = localizedCalcDimension.start;
1506         commonCalcDimension.right = localizedCalcDimension.end;
1507         return true;
1508     }
1509     ParseEdgeWidths(object, commonCalcDimension, notNegative);
1510     return false;
1511 }
1512 
ParseCommonEdgeWidthsForDashParams(const JSRef<JSObject> & object,CommonCalcDimension & commonCalcDimension)1513 void ParseCommonEdgeWidthsForDashParams(const JSRef<JSObject>& object, CommonCalcDimension& commonCalcDimension)
1514 {
1515     if (CheckLengthMetrics(object)) {
1516         LocalizedCalcDimension localizedCalcDimension;
1517         ParseLocalizedEdgeWidths(object, localizedCalcDimension, false);
1518         auto isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
1519         commonCalcDimension.top = localizedCalcDimension.top;
1520         commonCalcDimension.bottom = localizedCalcDimension.bottom;
1521         commonCalcDimension.left = isRightToLeft ? localizedCalcDimension.end : localizedCalcDimension.start;
1522         commonCalcDimension.right = isRightToLeft ? localizedCalcDimension.start : localizedCalcDimension.end;
1523         return;
1524     }
1525     ParseEdgeWidthsProps(object, commonCalcDimension, true, false, static_cast<CalcDimension>(-1));
1526 }
1527 
ParseCommonEdgeWidthsProps(const JSRef<JSObject> & object,CommonCalcDimension & commonCalcDimension)1528 void ParseCommonEdgeWidthsProps(const JSRef<JSObject>& object, CommonCalcDimension& commonCalcDimension)
1529 {
1530     if (CheckLengthMetrics(object)) {
1531         LocalizedCalcDimension localizedCalcDimension;
1532         ParseLocalizedEdgeWidthsProps(object, localizedCalcDimension);
1533         auto isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
1534         commonCalcDimension.top = localizedCalcDimension.top;
1535         commonCalcDimension.bottom = localizedCalcDimension.bottom;
1536         commonCalcDimension.left = isRightToLeft ? localizedCalcDimension.end : localizedCalcDimension.start;
1537         commonCalcDimension.right = isRightToLeft ? localizedCalcDimension.start : localizedCalcDimension.end;
1538         return;
1539     }
1540     ParseEdgeWidthsProps(object, commonCalcDimension, false, true, 0.0_vp);
1541 }
1542 
ParseTransitionCallback(const JSRef<JSFunc> & jsFunc,const JSExecutionContext & context)1543 std::function<void(bool)> ParseTransitionCallback(const JSRef<JSFunc>& jsFunc, const JSExecutionContext& context)
1544 {
1545     auto jsFuncFinish = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(jsFunc));
1546     auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1547     auto finishCallback = [execCtx = context, jsFuncFinish, targetNode](bool isTransitionIn) {
1548         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1549         NG::PipelineContext::SetCallBackNode(targetNode);
1550         JSRef<JSVal> newJSVal = JSRef<JSVal>::Make(ToJSValue(isTransitionIn));
1551         jsFuncFinish->ExecuteJS(1, &newJSVal);
1552     };
1553     return finishCallback;
1554 }
1555 } // namespace
1556 
GetResourceObject(const JSRef<JSObject> & jsObj)1557 RefPtr<ResourceObject> GetResourceObject(const JSRef<JSObject>& jsObj)
1558 {
1559     auto id = jsObj->GetProperty("id")->ToNumber<int32_t>();
1560     auto type = jsObj->GetProperty("type")->ToNumber<int32_t>();
1561     auto args = jsObj->GetProperty("params");
1562 
1563     std::string bundleName;
1564     std::string moduleName;
1565     auto bundle = jsObj->GetProperty("bundleName");
1566     auto module = jsObj->GetProperty("moduleName");
1567     if (bundle->IsString() && module->IsString()) {
1568         bundleName = bundle->ToString();
1569         moduleName = module->ToString();
1570     }
1571     if (!args->IsArray()) {
1572         return nullptr;
1573     }
1574     JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
1575     std::vector<ResourceObjectParams> resObjParamsList;
1576     auto size = static_cast<int32_t>(params->Length());
1577     for (int32_t i = 0; i < size; i++) {
1578         auto item = params->GetValueAt(i);
1579         ResourceObjectParams resObjParams { .value = item->ToString().c_str() };
1580         if (item->IsString()) {
1581             resObjParams.type = ResourceObjectParamType::STRING;
1582         } else if (item->IsNumber()) {
1583             if (std::regex_match(item->ToString(), FLOAT_PATTERN)) {
1584                 resObjParams.type = ResourceObjectParamType::FLOAT;
1585             } else {
1586                 resObjParams.type = ResourceObjectParamType::INT;
1587             }
1588         }
1589         resObjParamsList.push_back(resObjParams);
1590     }
1591     auto resourceObject = AceType::MakeRefPtr<ResourceObject>(id, type, resObjParamsList, bundleName, moduleName);
1592     return resourceObject;
1593 }
1594 
GetResourceObjectByBundleAndModule(const JSRef<JSObject> & jsObj)1595 RefPtr<ResourceObject> GetResourceObjectByBundleAndModule(const JSRef<JSObject>& jsObj)
1596 {
1597     auto bundleName = jsObj->GetPropertyValue<std::string>(static_cast<int32_t>(ArkUIIndex::BUNDLE_NAME), "");
1598     auto moduleName = jsObj->GetPropertyValue<std::string>(static_cast<int32_t>(ArkUIIndex::MODULE_NAME), "");
1599     auto resourceObject = AceType::MakeRefPtr<ResourceObject>(bundleName, moduleName);
1600     return resourceObject;
1601 }
1602 
CreateResourceWrapper(const JSRef<JSObject> & jsObj,RefPtr<ResourceObject> & resourceObject)1603 RefPtr<ResourceWrapper> CreateResourceWrapper(const JSRef<JSObject>& jsObj, RefPtr<ResourceObject>& resourceObject)
1604 {
1605     RefPtr<ResourceAdapter> resourceAdapter = nullptr;
1606     RefPtr<ThemeConstants> themeConstants = nullptr;
1607     if (SystemProperties::GetResourceDecoupling()) {
1608         resourceAdapter = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resourceObject);
1609         if (!resourceAdapter) {
1610             return nullptr;
1611         }
1612     } else {
1613         themeConstants = JSViewAbstract::GetThemeConstants(jsObj);
1614         if (!themeConstants) {
1615             return nullptr;
1616         }
1617     }
1618     auto resourceWrapper = AceType::MakeRefPtr<ResourceWrapper>(themeConstants, resourceAdapter);
1619     return resourceWrapper;
1620 }
1621 
CreateResourceWrapper()1622 RefPtr<ResourceWrapper> CreateResourceWrapper()
1623 {
1624     RefPtr<ResourceAdapter> resourceAdapter = nullptr;
1625     RefPtr<ThemeConstants> themeConstants = nullptr;
1626     if (SystemProperties::GetResourceDecoupling()) {
1627         resourceAdapter = ResourceManager::GetInstance().GetResourceAdapter();
1628         if (!resourceAdapter) {
1629             return nullptr;
1630         }
1631     } else {
1632         themeConstants = JSViewAbstract::GetThemeConstants();
1633         if (!themeConstants) {
1634             return nullptr;
1635         }
1636     }
1637     auto resourceWrapper = AceType::MakeRefPtr<ResourceWrapper>(themeConstants, resourceAdapter);
1638     return resourceWrapper;
1639 }
1640 
ColorAlphaAdapt(uint32_t origin)1641 uint32_t ColorAlphaAdapt(uint32_t origin)
1642 {
1643     uint32_t result = origin;
1644     if (origin >> COLOR_ALPHA_OFFSET == 0) {
1645         result = origin | COLOR_ALPHA_VALUE;
1646     }
1647     return result;
1648 }
1649 
JsScale(const JSCallbackInfo & info)1650 void JSViewAbstract::JsScale(const JSCallbackInfo& info)
1651 {
1652     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
1653     auto jsVal = info[0];
1654     if (!CheckJSCallbackInfo("JsScale", jsVal, checkList)) {
1655         SetDefaultScale();
1656         return;
1657     }
1658 
1659     if (jsVal->IsObject()) {
1660         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsVal);
1661         if (jsObj->HasProperty(static_cast<int32_t>(ArkUIIndex::X)) ||
1662             jsObj->HasProperty(static_cast<int32_t>(ArkUIIndex::Y)) ||
1663             jsObj->HasProperty(static_cast<int32_t>(ArkUIIndex::Z))) {
1664             // default: x, y, z (1.0, 1.0, 1.0)
1665             auto scaleX = 1.0f;
1666             auto scaleY = 1.0f;
1667             auto scaleZ = 1.0f;
1668             // default centerX, centerY 50% 50%;
1669             CalcDimension centerX = 0.5_pct;
1670             CalcDimension centerY = 0.5_pct;
1671             ParseJsScale(jsVal, scaleX, scaleY, scaleZ, centerX, centerY);
1672             ViewAbstractModel::GetInstance()->SetScale(scaleX, scaleY, scaleZ);
1673             ViewAbstractModel::GetInstance()->SetPivot(centerX, centerY, 0.0_vp);
1674             return;
1675         } else {
1676             SetDefaultScale();
1677         }
1678     }
1679     double scale = 0.0;
1680     if (ParseJsDouble(jsVal, scale)) {
1681         ViewAbstractModel::GetInstance()->SetScale(scale, scale, 1.0f);
1682     }
1683 }
1684 
SetDefaultScale()1685 void JSViewAbstract::SetDefaultScale()
1686 {
1687     ViewAbstractModel::GetInstance()->SetScale(1.0f, 1.0f, 1.0f);
1688     ViewAbstractModel::GetInstance()->SetPivot(0.5_pct, 0.5_pct, 0.0_vp);
1689 }
1690 
JsScaleX(const JSCallbackInfo & info)1691 void JSViewAbstract::JsScaleX(const JSCallbackInfo& info)
1692 {
1693     double scaleVal = 0.0;
1694     if (!ParseJsDouble(info[0], scaleVal)) {
1695         return;
1696     }
1697     ViewAbstractModel::GetInstance()->SetScale(scaleVal, 1.0f, 1.0f);
1698 }
1699 
JsScaleY(const JSCallbackInfo & info)1700 void JSViewAbstract::JsScaleY(const JSCallbackInfo& info)
1701 {
1702     double scaleVal = 0.0;
1703     if (!ParseJsDouble(info[0], scaleVal)) {
1704         return;
1705     }
1706     ViewAbstractModel::GetInstance()->SetScale(1.0f, scaleVal, 1.0f);
1707 }
1708 
JsOpacity(const JSCallbackInfo & info)1709 void JSViewAbstract::JsOpacity(const JSCallbackInfo& info)
1710 {
1711     double opacity = 0.0;
1712     if (!ParseJsDouble(info[0], opacity)) {
1713         ViewAbstractModel::GetInstance()->SetOpacity(1.0f);
1714         return;
1715     }
1716     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1717         opacity = std::clamp(opacity, 0.0, 1.0);
1718     } else {
1719         if (opacity > 1.0 || LessNotEqual(opacity, 0.0)) {
1720             opacity = 1.0;
1721         }
1722     }
1723     ViewAbstractModel::GetInstance()->SetOpacity(opacity);
1724 }
1725 
JsTranslate(const JSCallbackInfo & info)1726 void JSViewAbstract::JsTranslate(const JSCallbackInfo& info)
1727 {
1728     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
1729         JSCallbackInfoType::OBJECT };
1730     auto jsVal = info[0];
1731     if (!CheckJSCallbackInfo("JsTranslate", jsVal, checkList)) {
1732         SetDefaultTranslate();
1733         return;
1734     }
1735 
1736     if (jsVal->IsObject()) {
1737         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsVal);
1738         if (jsObj->HasProperty(static_cast<int32_t>(ArkUIIndex::X)) ||
1739             jsObj->HasProperty(static_cast<int32_t>(ArkUIIndex::Y)) ||
1740             jsObj->HasProperty(static_cast<int32_t>(ArkUIIndex::Z))) {
1741             // default: x, y, z (0.0, 0.0, 0.0)
1742             auto translateX = CalcDimension(0.0);
1743             auto translateY = CalcDimension(0.0);
1744             auto translateZ = CalcDimension(0.0);
1745             ParseJsTranslate(jsVal, translateX, translateY, translateZ);
1746             ViewAbstractModel::GetInstance()->SetTranslate(translateX, translateY, translateZ);
1747             return;
1748         } else {
1749             SetDefaultTranslate();
1750         }
1751     }
1752     CalcDimension value;
1753     if (ParseJsDimensionVp(jsVal, value)) {
1754         ViewAbstractModel::GetInstance()->SetTranslate(value, value, value);
1755     }
1756 }
1757 
SetDefaultTranslate()1758 void JSViewAbstract::SetDefaultTranslate()
1759 {
1760     ViewAbstractModel::GetInstance()->SetTranslate(CalcDimension(0.0), CalcDimension(0.0), CalcDimension(0.0));
1761 }
1762 
JsTranslateX(const JSCallbackInfo & info)1763 void JSViewAbstract::JsTranslateX(const JSCallbackInfo& info)
1764 {
1765     CalcDimension value;
1766     if (!ParseJsDimensionVp(info[0], value)) {
1767         return;
1768     }
1769     ViewAbstractModel::GetInstance()->SetTranslate(value, 0.0_px, 0.0_px);
1770 }
1771 
JsTranslateY(const JSCallbackInfo & info)1772 void JSViewAbstract::JsTranslateY(const JSCallbackInfo& info)
1773 {
1774     CalcDimension value;
1775     if (!ParseJsDimensionVp(info[0], value)) {
1776         return;
1777     }
1778     ViewAbstractModel::GetInstance()->SetTranslate(0.0_px, value, 0.0_px);
1779 }
1780 
JsRotate(const JSCallbackInfo & info)1781 void JSViewAbstract::JsRotate(const JSCallbackInfo& info)
1782 {
1783     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
1784     auto jsVal = info[0];
1785     if (!CheckJSCallbackInfo("JsRotate", jsVal, checkList)) {
1786         SetDefaultRotate();
1787         return;
1788     }
1789 
1790     if (jsVal->IsObject()) {
1791         NG::RotateOptions rotate(0.0f, 0.0f, 0.0f, 0.0f, 0.5_pct, 0.5_pct);
1792         std::optional<float> angle;
1793         ParseJsRotate(jsVal, rotate, angle);
1794         if (angle) {
1795             ViewAbstractModel::GetInstance()->SetRotate(
1796                 rotate.xDirection, rotate.yDirection, rotate.zDirection, angle.value(), rotate.perspective);
1797             ViewAbstractModel::GetInstance()->SetPivot(rotate.centerX, rotate.centerY, rotate.centerZ);
1798         } else {
1799             SetDefaultRotate();
1800         }
1801         return;
1802     }
1803     double rotateZ;
1804     if (ParseJsDouble(jsVal, rotateZ)) {
1805         ViewAbstractModel::GetInstance()->SetRotate(0.0f, 0.0f, 1.0f, rotateZ);
1806     }
1807 }
1808 
SetDefaultRotate()1809 void JSViewAbstract::SetDefaultRotate()
1810 {
1811     NG::RotateOptions rotate(0.0f, 0.0f, 0.0f, 0.0f, 0.5_pct, 0.5_pct, 0.0f, 0.0f);
1812     ViewAbstractModel::GetInstance()->SetRotate(
1813         rotate.xDirection, rotate.yDirection, rotate.zDirection, 0.0f, rotate.perspective);
1814     ViewAbstractModel::GetInstance()->SetPivot(rotate.centerX, rotate.centerY, rotate.centerZ);
1815 }
1816 
JsRotateX(const JSCallbackInfo & info)1817 void JSViewAbstract::JsRotateX(const JSCallbackInfo& info)
1818 {
1819     double rotateVal = 0.0;
1820     if (!ParseJsDouble(info[0], rotateVal)) {
1821         return;
1822     }
1823     ViewAbstractModel::GetInstance()->SetRotate(1.0f, 0.0f, 0.0f, rotateVal);
1824 }
1825 
JsRotateY(const JSCallbackInfo & info)1826 void JSViewAbstract::JsRotateY(const JSCallbackInfo& info)
1827 {
1828     double rotateVal = 0.0;
1829     if (!ParseJsDouble(info[0], rotateVal)) {
1830         return;
1831     }
1832     ViewAbstractModel::GetInstance()->SetRotate(0.0f, 1.0f, 0.0f, rotateVal);
1833 }
1834 
JsTransform(const JSCallbackInfo & info)1835 void JSViewAbstract::JsTransform(const JSCallbackInfo& info)
1836 {
1837     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
1838     auto jsVal = info[0];
1839     if (!CheckJSCallbackInfo("JsTransform", jsVal, checkList)) {
1840         SetDefaultTransform();
1841         return;
1842     }
1843     JSRef<JSVal> array = JSRef<JSObject>::Cast(jsVal)->GetProperty(static_cast<int32_t>(ArkUIIndex::MATRIX4X4));
1844     const auto matrix4Len = Matrix4::DIMENSION * Matrix4::DIMENSION;
1845     if (!array->IsArray()) {
1846         return;
1847     }
1848     JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(array);
1849     if (jsArray->Length() != matrix4Len) {
1850         return;
1851     }
1852     std::vector<float> matrix(matrix4Len);
1853     for (int32_t i = 0; i < matrix4Len; i++) {
1854         double value = 0.0;
1855         ParseJsDouble(jsArray->GetValueAt(i), value);
1856         matrix[i] = static_cast<float>(value);
1857     }
1858     ViewAbstractModel::GetInstance()->SetTransformMatrix(matrix);
1859 }
1860 
SetDefaultTransform()1861 void JSViewAbstract::SetDefaultTransform()
1862 {
1863     const auto matrix4Len = Matrix4::DIMENSION * Matrix4::DIMENSION;
1864     std::vector<float> matrix(matrix4Len);
1865     const int32_t initPosition = 5;
1866     for (int32_t i = 0; i < matrix4Len; i = i + initPosition) {
1867         double value = 1.0;
1868         matrix[i] = static_cast<float>(value);
1869     }
1870     ViewAbstractModel::GetInstance()->SetTransformMatrix(matrix);
1871 }
1872 
ParseJsTransition(const JSRef<JSObject> & jsObj)1873 NG::TransitionOptions JSViewAbstract::ParseJsTransition(const JSRef<JSObject>& jsObj)
1874 {
1875     NG::TransitionOptions transitionOption;
1876     bool hasEffect = false;
1877     transitionOption.Type = ParseTransitionType(jsObj->GetPropertyValue<std::string>("type", "All"));
1878     if (jsObj->HasProperty("opacity")) {
1879         double opacity = 1.0;
1880         ParseJsDouble(jsObj->GetProperty("opacity"), opacity);
1881         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1882             if (opacity > 1.0 || LessNotEqual(opacity, 0.0)) {
1883                 opacity = 1.0;
1884             }
1885         } else {
1886             opacity = std::clamp(opacity, 0.0, 1.0);
1887         }
1888         transitionOption.UpdateOpacity(static_cast<float>(opacity));
1889         hasEffect = true;
1890     }
1891     if (jsObj->HasProperty("translate")) {
1892         // default: x, y, z (0.0, 0.0, 0.0)
1893         NG::TranslateOptions translate;
1894         ParseJsTranslate(jsObj->GetProperty("translate"), translate.x, translate.y, translate.z);
1895         transitionOption.UpdateTranslate(translate);
1896         hasEffect = true;
1897     }
1898     if (jsObj->HasProperty("scale")) {
1899         // default: x, y, z (1.0, 1.0, 1.0), centerX, centerY 50% 50%;
1900         NG::ScaleOptions scale(1.0f, 1.0f, 1.0f, 0.5_pct, 0.5_pct);
1901         ParseJsScale(jsObj->GetProperty("scale"), scale.xScale, scale.yScale, scale.zScale,
1902             scale.centerX, scale.centerY);
1903         transitionOption.UpdateScale(scale);
1904         hasEffect = true;
1905     }
1906     if (jsObj->HasProperty("rotate")) {
1907         // default: dx, dy, dz (0.0, 0.0, 0.0), angle 0, centerX, centerY 50% 50%;
1908         NG::RotateOptions rotate(0.0f, 0.0f, 0.0f, 0.0f, 0.5_pct, 0.5_pct);
1909         std::optional<float> angle;
1910         ParseJsRotate(jsObj->GetProperty("rotate"), rotate, angle);
1911         if (angle.has_value()) {
1912             rotate.angle = angle.value();
1913             transitionOption.UpdateRotate(rotate);
1914             hasEffect = true;
1915         }
1916     }
1917     if (!hasEffect) {
1918         // default transition
1919         transitionOption = NG::TransitionOptions::GetDefaultTransition(transitionOption.Type);
1920     }
1921     return transitionOption;
1922 }
1923 
ParseJsTransitionEffect(const JSCallbackInfo & info)1924 RefPtr<NG::ChainedTransitionEffect> JSViewAbstract::ParseJsTransitionEffect(const JSCallbackInfo& info)
1925 {
1926     JSRef<JSVal> arg = info[0];
1927     if (!arg->IsObject()) {
1928         return nullptr;
1929     }
1930     auto obj = JSRef<JSObject>::Cast(arg);
1931     auto transitionVal = obj->GetProperty("transition");
1932 
1933     if (!transitionVal->IsObject()) {
1934         return nullptr;
1935     }
1936 
1937     auto transitionObj = JSRef<JSObject>::Cast(transitionVal);
1938     auto chainedEffect = ParseChainedTransition(transitionObj, info.GetExecutionContext());
1939     return chainedEffect;
1940 }
1941 
ParseNapiChainedTransition(const JSRef<JSObject> & object,const JSExecutionContext & context)1942 RefPtr<NG::ChainedTransitionEffect> JSViewAbstract::ParseNapiChainedTransition(const JSRef<JSObject>& object,
1943     const JSExecutionContext& context)
1944 {
1945     auto chainedEffect = ParseChainedTransition(object, context);
1946     return chainedEffect;
1947 }
1948 
JsTransition(const JSCallbackInfo & info)1949 void JSViewAbstract::JsTransition(const JSCallbackInfo& info)
1950 {
1951     if (info.Length() < 1 || !info[0]->IsObject()) {
1952         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1953             ViewAbstractModel::GetInstance()->CleanTransition();
1954             ViewAbstractModel::GetInstance()->SetChainedTransition(nullptr, nullptr);
1955         }
1956         return;
1957     }
1958     auto obj = JSRef<JSObject>::Cast(info[0]);
1959     if (!obj->GetProperty("successor_")->IsUndefined()) {
1960         auto chainedEffect = ParseChainedTransition(obj, info.GetExecutionContext());
1961         std::function<void(bool)> finishCallback;
1962         if (info.Length() > 1 && info[1]->IsFunction()) {
1963             finishCallback = ParseTransitionCallback(JSRef<JSFunc>::Cast(info[1]), info.GetExecutionContext());
1964         }
1965         ViewAbstractModel::GetInstance()->SetChainedTransition(chainedEffect, std::move(finishCallback));
1966         return;
1967     }
1968     auto options = ParseJsTransition(obj);
1969     ViewAbstractModel::GetInstance()->SetTransition(options);
1970 }
1971 
JsWidth(const JSCallbackInfo & info)1972 void JSViewAbstract::JsWidth(const JSCallbackInfo& info)
1973 {
1974     JsWidth(info[0]);
1975 }
1976 
JsWidth(const JSRef<JSVal> & jsValue)1977 bool JSViewAbstract::JsWidth(const JSRef<JSVal>& jsValue)
1978 {
1979     CalcDimension value;
1980     if (jsValue->IsUndefined()) {
1981         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(true);
1982         return true;
1983     }
1984     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
1985         if (!ParseJsDimensionVpNG(jsValue, value)) {
1986             ViewAbstractModel::GetInstance()->ClearWidthOrHeight(true);
1987             return false;
1988         }
1989     } else if (!ParseJsDimensionVp(jsValue, value)) {
1990         return false;
1991     }
1992 
1993     if (LessNotEqual(value.Value(), 0.0)) {
1994         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1995             ViewAbstractModel::GetInstance()->ClearWidthOrHeight(true);
1996             return true;
1997         } else {
1998             value.SetValue(0.0);
1999         }
2000     }
2001 
2002     ViewAbstractModel::GetInstance()->SetWidth(value);
2003     return true;
2004 }
2005 
JsHeight(const JSCallbackInfo & info)2006 void JSViewAbstract::JsHeight(const JSCallbackInfo& info)
2007 {
2008     JsHeight(info[0]);
2009 }
2010 
JsHeight(const JSRef<JSVal> & jsValue)2011 bool JSViewAbstract::JsHeight(const JSRef<JSVal>& jsValue)
2012 {
2013     CalcDimension value;
2014     if (jsValue->IsUndefined()) {
2015         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(false);
2016         return true;
2017     }
2018     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
2019         if (!ParseJsDimensionVpNG(jsValue, value)) {
2020             ViewAbstractModel::GetInstance()->ClearWidthOrHeight(false);
2021             return false;
2022         }
2023     } else if (!ParseJsDimensionVp(jsValue, value)) {
2024         return false;
2025     }
2026 
2027     if (LessNotEqual(value.Value(), 0.0)) {
2028         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
2029             ViewAbstractModel::GetInstance()->ClearWidthOrHeight(false);
2030             return true;
2031         } else {
2032             value.SetValue(0.0);
2033         }
2034     }
2035 
2036     ViewAbstractModel::GetInstance()->SetHeight(value);
2037     return true;
2038 }
2039 
JsResponseRegion(const JSCallbackInfo & info)2040 void JSViewAbstract::JsResponseRegion(const JSCallbackInfo& info)
2041 {
2042     std::vector<DimensionRect> result;
2043     if (!JSViewAbstract::ParseJsResponseRegionArray(info[0], result)) {
2044         ViewAbstractModel::GetInstance()->SetResponseRegion({});
2045         return;
2046     }
2047 
2048     ViewAbstractModel::GetInstance()->SetResponseRegion(result);
2049 }
2050 
JsMouseResponseRegion(const JSCallbackInfo & info)2051 void JSViewAbstract::JsMouseResponseRegion(const JSCallbackInfo& info)
2052 {
2053     std::vector<DimensionRect> result;
2054     if (!JSViewAbstract::ParseJsResponseRegionArray(info[0], result)) {
2055         ViewAbstractModel::GetInstance()->SetMouseResponseRegion({});
2056         return;
2057     }
2058     ViewAbstractModel::GetInstance()->SetMouseResponseRegion(result);
2059 }
2060 
ParseJsDimensionRect(const JSRef<JSVal> & jsValue,DimensionRect & result)2061 bool JSViewAbstract::ParseJsDimensionRect(const JSRef<JSVal>& jsValue, DimensionRect& result)
2062 {
2063     result.SetOffset(DimensionOffset(CalcDimension(0, DimensionUnit::VP), CalcDimension(0, DimensionUnit::VP)));
2064     result.SetSize(DimensionSize(CalcDimension(1, DimensionUnit::PERCENT), CalcDimension(1, DimensionUnit::PERCENT)));
2065     if (!jsValue->IsObject()) {
2066         return true;
2067     }
2068 
2069     JSRef<JSObject> obj = JSRef<JSObject>::Cast(jsValue);
2070     JSRef<JSVal> x = obj->GetProperty("x");
2071     JSRef<JSVal> y = obj->GetProperty("y");
2072     JSRef<JSVal> width = obj->GetProperty("width");
2073     JSRef<JSVal> height = obj->GetProperty("height");
2074     CalcDimension xDimen = result.GetOffset().GetX();
2075     CalcDimension yDimen = result.GetOffset().GetY();
2076     CalcDimension widthDimen = result.GetWidth();
2077     CalcDimension heightDimen = result.GetHeight();
2078     auto s1 = width->ToString();
2079     auto s2 = height->ToString();
2080     if (s1.find('-') != std::string::npos) {
2081         width = JSRef<JSVal>::Make(ToJSValue("100%"));
2082     }
2083     if (s2.find('-') != std::string::npos) {
2084         height = JSRef<JSVal>::Make(ToJSValue("100%"));
2085     }
2086     if (ParseJsDimensionNG(x, xDimen, DimensionUnit::VP)) {
2087         auto offset = result.GetOffset();
2088         offset.SetX(xDimen);
2089         result.SetOffset(offset);
2090     }
2091     if (ParseJsDimensionNG(y, yDimen, DimensionUnit::VP)) {
2092         auto offset = result.GetOffset();
2093         offset.SetY(yDimen);
2094         result.SetOffset(offset);
2095     }
2096     if (ParseJsDimensionNG(width, widthDimen, DimensionUnit::VP)) {
2097         if (widthDimen.Unit() == DimensionUnit::PERCENT && widthDimen.Value() < 0) {
2098             return true;
2099         }
2100         result.SetWidth(widthDimen);
2101     }
2102     if (ParseJsDimensionNG(height, heightDimen, DimensionUnit::VP)) {
2103         if (heightDimen.Unit() == DimensionUnit::PERCENT && heightDimen.Value() < 0) {
2104             return true;
2105         }
2106         result.SetHeight(heightDimen);
2107     }
2108     return true;
2109 }
2110 
ParseJsResponseRegionArray(const JSRef<JSVal> & jsValue,std::vector<DimensionRect> & result)2111 bool JSViewAbstract::ParseJsResponseRegionArray(const JSRef<JSVal>& jsValue, std::vector<DimensionRect>& result)
2112 {
2113     if (!jsValue->IsArray() && !jsValue->IsObject()) {
2114         return false;
2115     }
2116 
2117     if (jsValue->IsArray()) {
2118         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
2119         for (size_t i = 0; i < array->Length(); i++) {
2120             CalcDimension xDimen = CalcDimension(0.0, DimensionUnit::VP);
2121             CalcDimension yDimen = CalcDimension(0.0, DimensionUnit::VP);
2122             CalcDimension widthDimen = CalcDimension(1, DimensionUnit::PERCENT);
2123             CalcDimension heightDimen = CalcDimension(1, DimensionUnit::PERCENT);
2124             DimensionOffset offsetDimen(xDimen, yDimen);
2125             DimensionRect dimenRect(widthDimen, heightDimen, offsetDimen);
2126             if (ParseJsDimensionRect(array->GetValueAt(i), dimenRect)) {
2127                 result.emplace_back(dimenRect);
2128             } else {
2129                 return false;
2130             }
2131         }
2132         return true;
2133     }
2134 
2135     CalcDimension xDimen = CalcDimension(0.0, DimensionUnit::VP);
2136     CalcDimension yDimen = CalcDimension(0.0, DimensionUnit::VP);
2137     CalcDimension widthDimen = CalcDimension(1, DimensionUnit::PERCENT);
2138     CalcDimension heightDimen = CalcDimension(1, DimensionUnit::PERCENT);
2139     DimensionOffset offsetDimen(xDimen, yDimen);
2140     DimensionRect dimenRect(widthDimen, heightDimen, offsetDimen);
2141     if (ParseJsDimensionRect(jsValue, dimenRect)) {
2142         result.emplace_back(dimenRect);
2143         return true;
2144     } else {
2145         return false;
2146     }
2147 }
2148 
JsSize(const JSCallbackInfo & info)2149 void JSViewAbstract::JsSize(const JSCallbackInfo& info)
2150 {
2151     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
2152     auto jsVal = info[0];
2153     if (!CheckJSCallbackInfo("JsSize", jsVal, checkList)) {
2154         return;
2155     }
2156 
2157     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(jsVal);
2158     JsWidth(sizeObj->GetProperty(static_cast<int32_t>(ArkUIIndex::WIDTH)));
2159     JsHeight(sizeObj->GetProperty(static_cast<int32_t>(ArkUIIndex::HEIGHT)));
2160 }
2161 
JsConstraintSize(const JSCallbackInfo & info)2162 void JSViewAbstract::JsConstraintSize(const JSCallbackInfo& info)
2163 {
2164     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
2165     auto jsVal = info[0];
2166     if (!CheckJSCallbackInfo("JsConstraintSize", jsVal, checkList)) {
2167         ViewAbstractModel::GetInstance()->ResetMaxSize(true);
2168         ViewAbstractModel::GetInstance()->ResetMinSize(true);
2169         ViewAbstractModel::GetInstance()->ResetMaxSize(false);
2170         ViewAbstractModel::GetInstance()->ResetMinSize(false);
2171         return;
2172     }
2173 
2174     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(jsVal);
2175 
2176     JSRef<JSVal> minWidthValue = sizeObj->GetProperty("minWidth");
2177     CalcDimension minWidth;
2178     JSRef<JSVal> maxWidthValue = sizeObj->GetProperty("maxWidth");
2179     CalcDimension maxWidth;
2180     JSRef<JSVal> minHeightValue = sizeObj->GetProperty("minHeight");
2181     CalcDimension minHeight;
2182     JSRef<JSVal> maxHeightValue = sizeObj->GetProperty("maxHeight");
2183     CalcDimension maxHeight;
2184     bool version10OrLarger = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN);
2185     if (ParseJsDimensionVp(minWidthValue, minWidth)) {
2186         ViewAbstractModel::GetInstance()->SetMinWidth(minWidth);
2187     } else if (version10OrLarger) {
2188         ViewAbstractModel::GetInstance()->ResetMinSize(true);
2189     }
2190 
2191     if (ParseJsDimensionVp(maxWidthValue, maxWidth)) {
2192         ViewAbstractModel::GetInstance()->SetMaxWidth(maxWidth);
2193     } else if (version10OrLarger) {
2194         ViewAbstractModel::GetInstance()->ResetMaxSize(true);
2195     }
2196 
2197     if (ParseJsDimensionVp(minHeightValue, minHeight)) {
2198         ViewAbstractModel::GetInstance()->SetMinHeight(minHeight);
2199     } else if (version10OrLarger) {
2200         ViewAbstractModel::GetInstance()->ResetMinSize(false);
2201     }
2202 
2203     if (ParseJsDimensionVp(maxHeightValue, maxHeight)) {
2204         ViewAbstractModel::GetInstance()->SetMaxHeight(maxHeight);
2205     } else if (version10OrLarger) {
2206         ViewAbstractModel::GetInstance()->ResetMaxSize(false);
2207     }
2208 }
2209 
JsLayoutPriority(const JSCallbackInfo & info)2210 void JSViewAbstract::JsLayoutPriority(const JSCallbackInfo& info)
2211 {
2212     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER };
2213     auto jsVal = info[0];
2214     if (!CheckJSCallbackInfo("JsLayoutPriority", jsVal, checkList)) {
2215         return;
2216     }
2217 
2218     int32_t priority;
2219     if (jsVal->IsNumber()) {
2220         priority = jsVal->ToNumber<int32_t>();
2221     } else {
2222         priority = static_cast<int32_t>(StringUtils::StringToUint(jsVal->ToString()));
2223     }
2224     ViewAbstractModel::GetInstance()->SetLayoutPriority(priority);
2225 }
2226 
JsPixelRound(const JSCallbackInfo & info)2227 void JSViewAbstract::JsPixelRound(const JSCallbackInfo& info)
2228 {
2229     uint16_t value = 0;
2230     JSRef<JSVal> arg = info[0];
2231     if (!arg->IsObject()) {
2232         return;
2233     }
2234     JSRef<JSObject> object = JSRef<JSObject>::Cast(arg);
2235     JSRef<JSVal> jsStartValue = object->GetProperty("start");
2236     if (jsStartValue->IsNumber()) {
2237         int32_t startValue = jsStartValue->ToNumber<int32_t>();
2238         if (PixelRoundCalcPolicy::FORCE_CEIL == static_cast<PixelRoundCalcPolicy>(startValue)) {
2239             value |= static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_START);
2240         } else if (PixelRoundCalcPolicy::FORCE_FLOOR == static_cast<PixelRoundCalcPolicy>(startValue)) {
2241             value |= static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_START);
2242         } else if (PixelRoundCalcPolicy::NO_FORCE_ROUND == static_cast<PixelRoundCalcPolicy>(startValue)) {
2243             value |= static_cast<uint16_t>(PixelRoundPolicy::NO_FORCE_ROUND_START);
2244         }
2245     }
2246     JSRef<JSVal> jsTopValue = object->GetProperty("top");
2247     if (jsTopValue->IsNumber()) {
2248         int32_t topValue = jsTopValue->ToNumber<int32_t>();
2249         if (PixelRoundCalcPolicy::FORCE_CEIL == static_cast<PixelRoundCalcPolicy>(topValue)) {
2250             value |= static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_TOP);
2251         } else if (PixelRoundCalcPolicy::FORCE_FLOOR == static_cast<PixelRoundCalcPolicy>(topValue)) {
2252             value |= static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_TOP);
2253         } else if (PixelRoundCalcPolicy::NO_FORCE_ROUND == static_cast<PixelRoundCalcPolicy>(topValue)) {
2254             value |= static_cast<uint16_t>(PixelRoundPolicy::NO_FORCE_ROUND_TOP);
2255         }
2256     }
2257     JSRef<JSVal> jsEndValue = object->GetProperty("end");
2258     if (jsEndValue->IsNumber()) {
2259         int32_t endValue = jsEndValue->ToNumber<int32_t>();
2260         if (PixelRoundCalcPolicy::FORCE_CEIL == static_cast<PixelRoundCalcPolicy>(endValue)) {
2261             value |= static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_END);
2262         } else if (PixelRoundCalcPolicy::FORCE_FLOOR == static_cast<PixelRoundCalcPolicy>(endValue)) {
2263             value |= static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_END);
2264         } else if (PixelRoundCalcPolicy::NO_FORCE_ROUND == static_cast<PixelRoundCalcPolicy>(endValue)) {
2265             value |= static_cast<uint16_t>(PixelRoundPolicy::NO_FORCE_ROUND_END);
2266         }
2267     }
2268     JSRef<JSVal> jsBottomValue = object->GetProperty("bottom");
2269     if (jsBottomValue->IsNumber()) {
2270         int32_t bottomValue = jsBottomValue->ToNumber<int32_t>();
2271         if (PixelRoundCalcPolicy::FORCE_CEIL == static_cast<PixelRoundCalcPolicy>(bottomValue)) {
2272             value |= static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_BOTTOM);
2273         } else if (PixelRoundCalcPolicy::FORCE_FLOOR == static_cast<PixelRoundCalcPolicy>(bottomValue)) {
2274             value |= static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_BOTTOM);
2275         } else if (PixelRoundCalcPolicy::NO_FORCE_ROUND == static_cast<PixelRoundCalcPolicy>(bottomValue)) {
2276             value |= static_cast<uint16_t>(PixelRoundPolicy::NO_FORCE_ROUND_BOTTOM);
2277         }
2278     }
2279     ViewAbstractModel::GetInstance()->SetPixelRound(value);
2280 }
2281 
JsLayoutWeight(const JSCallbackInfo & info)2282 void JSViewAbstract::JsLayoutWeight(const JSCallbackInfo& info)
2283 {
2284     float value = 0.0f;
2285     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER };
2286     auto jsVal = info[0];
2287     if (!CheckJSCallbackInfo("JsLayoutWeight", jsVal, checkList)) {
2288         if (!jsVal->IsUndefined()) {
2289             return;
2290         }
2291     }
2292 
2293     if (jsVal->IsNumber()) {
2294         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
2295             value = jsVal->ToNumber<float>();
2296         } else {
2297             value = jsVal->ToNumber<int32_t>();
2298         }
2299     } else {
2300         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
2301             value = static_cast<float>(StringUtils::StringToUintCheck(jsVal->ToString()));
2302         } else {
2303             value = static_cast<int32_t>(StringUtils::StringToUintCheck(jsVal->ToString()));
2304         }
2305     }
2306 
2307     ViewAbstractModel::GetInstance()->SetLayoutWeight(value);
2308 }
2309 
JsChainWeight(const JSCallbackInfo & info)2310 void JSViewAbstract::JsChainWeight(const JSCallbackInfo& info)
2311 {
2312     NG::LayoutWeightPair layoutWeightPair(DEFAULT_LAYOUT_WEIGHT, DEFAULT_LAYOUT_WEIGHT);
2313     auto jsVal = info[0];
2314     if (jsVal->IsObject()) {
2315         JSRef<JSObject> val = JSRef<JSObject>::Cast(jsVal);
2316         auto weightX = val->GetProperty("horizontal");
2317         auto weightY = val->GetProperty("vertical");
2318         if (weightX->IsNumber()) {
2319             layoutWeightPair.first = weightX->ToNumber<float>();
2320         }
2321         if (weightY->IsNumber()) {
2322             layoutWeightPair.second = weightY->ToNumber<float>();
2323         }
2324     }
2325     ViewAbstractModel::GetInstance()->SetLayoutWeight(layoutWeightPair);
2326 }
2327 
JsAlign(const JSCallbackInfo & info)2328 void JSViewAbstract::JsAlign(const JSCallbackInfo& info)
2329 {
2330     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
2331     auto jsVal = info[0];
2332     if (!CheckJSCallbackInfo("JsAlign", jsVal, checkList) &&
2333         Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
2334         ViewAbstractModel::GetInstance()->SetAlign(Alignment::CENTER);
2335         return;
2336     }
2337     auto value = jsVal->ToNumber<int32_t>();
2338     Alignment alignment = ParseAlignment(value);
2339     ViewAbstractModel::GetInstance()->SetAlign(alignment);
2340 }
2341 
JsPosition(const JSCallbackInfo & info)2342 void JSViewAbstract::JsPosition(const JSCallbackInfo& info)
2343 {
2344     CalcDimension x;
2345     CalcDimension y;
2346     OHOS::Ace::EdgesParam edges;
2347 
2348     auto jsArg = info[0];
2349     if (jsArg->IsObject()) {
2350         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsArg);
2351         if (ParseLocationProps(jsObj, x, y)) {
2352             return ViewAbstractModel::GetInstance()->SetPosition(x, y);
2353         } else if (ParseLocalizedEdges(jsObj, edges)) {
2354             ViewAbstractModel::GetInstance()->SetPositionLocalizedEdges(true);
2355             return ViewAbstractModel::GetInstance()->SetPositionEdges(edges);
2356         } else if (ParseLocationPropsEdges(jsObj, edges)) {
2357             return ViewAbstractModel::GetInstance()->SetPositionEdges(edges);
2358         }
2359     }
2360     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
2361         ViewAbstractModel::GetInstance()->ResetPosition();
2362     } else {
2363         ViewAbstractModel::GetInstance()->SetPosition(0.0_vp, 0.0_vp);
2364     }
2365 }
2366 
JsMarkAnchor(const JSCallbackInfo & info)2367 void JSViewAbstract::JsMarkAnchor(const JSCallbackInfo& info)
2368 {
2369     CalcDimension x;
2370     CalcDimension y;
2371 
2372     auto jsArg = info[0];
2373     if (jsArg->IsObject()) {
2374         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsArg);
2375         if (ParseMarkAnchorPosition(jsObj, x, y)) {
2376             ViewAbstractModel::GetInstance()->SetLocalizedMarkAnchor(true);
2377             return ViewAbstractModel::GetInstance()->MarkAnchor(x, y);
2378         } else if (ParseLocationProps(jsObj, x, y)) {
2379             return ViewAbstractModel::GetInstance()->MarkAnchor(x, y);
2380         }
2381     }
2382     ViewAbstractModel::GetInstance()->MarkAnchor(0.0_vp, 0.0_vp);
2383 }
2384 
JsOffset(const JSCallbackInfo & info)2385 void JSViewAbstract::JsOffset(const JSCallbackInfo& info)
2386 {
2387     CalcDimension x;
2388     CalcDimension y;
2389     OHOS::Ace::EdgesParam edges;
2390     auto jsArg = info[0];
2391     if (jsArg->IsObject()) {
2392         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsArg);
2393         if (ParseLocalizedEdges(jsObj, edges)) {
2394             ViewAbstractModel::GetInstance()->SetOffsetLocalizedEdges(true);
2395             return ViewAbstractModel::GetInstance()->SetOffsetEdges(edges);
2396         } else if (ParseLocationProps(jsObj, x, y)) {
2397             return ViewAbstractModel::GetInstance()->SetOffset(x, y);
2398         } else if (ParseLocationPropsEdges(jsObj, edges)) {
2399             return ViewAbstractModel::GetInstance()->SetOffsetEdges(edges);
2400         }
2401     }
2402 
2403     ViewAbstractModel::GetInstance()->SetOffset(0.0_vp, 0.0_vp);
2404 }
2405 
JsEnabled(const JSCallbackInfo & info)2406 void JSViewAbstract::JsEnabled(const JSCallbackInfo& info)
2407 {
2408     auto arg = info[0];
2409     if (!arg->IsBoolean()) {
2410         ViewAbstractModel::GetInstance()->SetEnabled(true);
2411     } else {
2412         ViewAbstractModel::GetInstance()->SetEnabled(arg->ToBoolean());
2413     }
2414 }
2415 
JsAspectRatio(const JSCallbackInfo & info)2416 void JSViewAbstract::JsAspectRatio(const JSCallbackInfo& info)
2417 {
2418     double value = 0.0;
2419     auto jsAspectRatio = info[0];
2420     if (!ParseJsDouble(jsAspectRatio, value)) {
2421         // add version protection, undefined use default value
2422         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN) &&
2423             (jsAspectRatio->IsNull() || jsAspectRatio->IsUndefined())) {
2424             ViewAbstractModel::GetInstance()->ResetAspectRatio();
2425             return;
2426         } else {
2427             return;
2428         }
2429     }
2430 
2431     // negative use default value.
2432     if (LessOrEqual(value, 0.0)) {
2433         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
2434             ViewAbstractModel::GetInstance()->ResetAspectRatio();
2435             return;
2436         } else {
2437             value = 1.0;
2438         }
2439     }
2440 
2441     ViewAbstractModel::GetInstance()->SetAspectRatio(static_cast<float>(value));
2442 }
2443 
ParseOverlayFirstParam(const JSCallbackInfo & info,std::optional<Alignment> & align,std::optional<CalcDimension> & offsetX,std::optional<CalcDimension> & offsetY)2444 void ParseOverlayFirstParam(const JSCallbackInfo& info, std::optional<Alignment>& align,
2445     std::optional<CalcDimension>& offsetX, std::optional<CalcDimension>& offsetY)
2446 {
2447     if (info[0]->IsString()) {
2448         std::string text = info[0]->ToString();
2449         ViewAbstractModel::GetInstance()->SetOverlay(
2450             text, nullptr, nullptr, align, offsetX, offsetY, NG::OverlayType::TEXT);
2451     } else if (info[0]->IsObject()) {
2452         JSRef<JSObject> overlayObject = JSRef<JSObject>::Cast(info[0]);
2453         auto builder = overlayObject->GetProperty("builder");
2454         if (builder->IsFunction()) {
2455             auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
2456             CHECK_NULL_VOID(builderFunc);
2457             auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
2458             auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc),
2459                               node = targetNode]() {
2460                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
2461                 ACE_SCORING_EVENT("Overlay");
2462                 PipelineContext::SetCallBackNode(node);
2463                 func->Execute();
2464             };
2465             ViewAbstractModel::GetInstance()->SetOverlay(
2466                 "", std::move(buildFunc), nullptr, align, offsetX, offsetY, NG::OverlayType::BUILDER);
2467             return;
2468         }
2469 
2470         JSRef<JSVal> builderNode = overlayObject->GetProperty("builderNode_");
2471         if (!builderNode->IsObject()) {
2472             return;
2473         }
2474         auto builderNodeObj = JSRef<JSObject>::Cast(builderNode);
2475         JSRef<JSVal> nodePtr = builderNodeObj->GetProperty("nodePtr_");
2476         if (nodePtr.IsEmpty()) {
2477             return;
2478         }
2479         const auto* vm = nodePtr->GetEcmaVM();
2480         auto* node = nodePtr->GetLocalHandle()->ToNativePointer(vm)->Value();
2481         auto* frameNode = reinterpret_cast<NG::FrameNode*>(node);
2482         CHECK_NULL_VOID(frameNode);
2483         RefPtr<NG::FrameNode> contentNode = AceType::Claim(frameNode);
2484         ViewAbstractModel::GetInstance()->SetOverlay(
2485             "", nullptr, contentNode, align, offsetX, offsetY, NG::OverlayType::COMPONENT_CONTENT);
2486     }
2487 }
2488 
JsOverlay(const JSCallbackInfo & info)2489 void JSViewAbstract::JsOverlay(const JSCallbackInfo& info)
2490 {
2491     if (info.Length() > 0 && (info[0]->IsUndefined())) {
2492         ViewAbstractModel::GetInstance()->SetOverlay(
2493             "", nullptr, nullptr, Alignment::TOP_LEFT, CalcDimension(0), CalcDimension(0), NG::OverlayType::RESET);
2494         return;
2495     }
2496 
2497     if (info.Length() <= 0 || (!info[0]->IsString() && !info[0]->IsObject())) {
2498         return;
2499     }
2500     std::optional<Alignment> align;
2501     std::optional<CalcDimension> offsetX;
2502     std::optional<CalcDimension> offsetY;
2503 
2504     if (info[1]->IsObject()) {
2505         JSRef<JSObject> optionObj = JSRef<JSObject>::Cast(info[1]);
2506         JSRef<JSVal> alignVal = optionObj->GetProperty("align");
2507         auto value = alignVal->ToNumber<int32_t>();
2508         Alignment alignment = ParseAlignment(value);
2509         align = alignment;
2510 
2511         JSRef<JSVal> val = optionObj->GetProperty("offset");
2512         if (val->IsObject()) {
2513             JSRef<JSObject> offsetObj = JSRef<JSObject>::Cast(val);
2514             JSRef<JSVal> xVal = offsetObj->GetProperty("x");
2515             CalcDimension x;
2516             if (ParseJsDimensionVp(xVal, x)) {
2517                 offsetX = x;
2518             }
2519             JSRef<JSVal> yVal = offsetObj->GetProperty("y");
2520             CalcDimension y;
2521             if (ParseJsDimensionVp(yVal, y)) {
2522                 offsetY = y;
2523             }
2524         }
2525     }
2526 
2527     ParseOverlayFirstParam(info, align, offsetX, offsetY);
2528 }
2529 
ParseAlignment(int32_t align)2530 Alignment JSViewAbstract::ParseAlignment(int32_t align)
2531 {
2532     Alignment alignment = Alignment::CENTER;
2533     switch (align) {
2534         case 0:
2535             alignment = Alignment::TOP_LEFT;
2536             break;
2537         case 1:
2538             alignment = Alignment::TOP_CENTER;
2539             break;
2540         case 2:
2541             alignment = Alignment::TOP_RIGHT;
2542             break;
2543         case 3:
2544             alignment = Alignment::CENTER_LEFT;
2545             break;
2546         case 4:
2547             alignment = Alignment::CENTER;
2548             break;
2549         case 5:
2550             alignment = Alignment::CENTER_RIGHT;
2551             break;
2552         case 6:
2553             alignment = Alignment::BOTTOM_LEFT;
2554             break;
2555         case 7:
2556             alignment = Alignment::BOTTOM_CENTER;
2557             break;
2558         case 8:
2559             alignment = Alignment::BOTTOM_RIGHT;
2560             break;
2561         default:
2562             break;
2563     }
2564     return alignment;
2565 }
2566 
SetVisibility(const JSCallbackInfo & info)2567 void JSViewAbstract::SetVisibility(const JSCallbackInfo& info)
2568 {
2569     int32_t visible = 0;
2570     JSRef<JSVal> arg = info[0];
2571     if (arg->IsNull() || arg->IsUndefined()) {
2572         // undefined value use default value.
2573         visible = 0;
2574     } else if (!arg->IsNumber()) {
2575         return;
2576     } else {
2577         visible = arg->ToNumber<int32_t>();
2578     }
2579 
2580     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
2581         (visible < static_cast<int32_t>(VisibleType::VISIBLE) || visible > static_cast<int32_t>(VisibleType::GONE))) {
2582         visible = 0;
2583     }
2584 
2585     if (info.Length() > 1 && info[1]->IsFunction()) {
2586         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[1]));
2587         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
2588         auto onVisibilityChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
2589                                       int32_t visible) {
2590             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
2591             ACE_SCORING_EVENT("onVisibilityChange");
2592             PipelineContext::SetCallBackNode(node);
2593             JSRef<JSVal> newJSVal = JSRef<JSVal>::Make(ToJSValue(visible));
2594             func->ExecuteJS(1, &newJSVal);
2595         };
2596         ViewAbstractModel::GetInstance()->SetVisibility(
2597             static_cast<VisibleType>(visible), std::move(onVisibilityChange));
2598     } else {
2599         ViewAbstractModel::GetInstance()->SetVisibility(static_cast<VisibleType>(visible), [](int32_t visible) {});
2600     }
2601 }
2602 
JsSetFreeze(const JSCallbackInfo & info)2603 void JSViewAbstract::JsSetFreeze(const JSCallbackInfo& info)
2604 {
2605     if (info[0]->IsBoolean()) {
2606         ViewAbstractModel::GetInstance()->SetFreeze(info[0]->ToBoolean());
2607     }
2608 }
2609 
JsFlexBasis(const JSCallbackInfo & info)2610 void JSViewAbstract::JsFlexBasis(const JSCallbackInfo& info)
2611 {
2612     CalcDimension value;
2613     if (!ParseJsDimensionVp(info[0], value)) {
2614         value.SetUnit(DimensionUnit::AUTO);
2615     }
2616     // flexbasis don't support percent case.
2617     if (value.Unit() == DimensionUnit::PERCENT) {
2618         value.SetUnit(DimensionUnit::AUTO);
2619     }
2620     ViewAbstractModel::GetInstance()->SetFlexBasis(value);
2621 }
2622 
JsFlexGrow(const JSCallbackInfo & info)2623 void JSViewAbstract::JsFlexGrow(const JSCallbackInfo& info)
2624 {
2625     double value = 0.0;
2626     if (!ParseJsDouble(info[0], value)) {
2627         if (info[0]->IsNull() || info[0]->IsUndefined()) {
2628             // undefined use default value.
2629             value = 0.0;
2630         } else {
2631             return;
2632         }
2633     }
2634     // negative use default value.
2635     if (value < 0.0) {
2636         value = 0.0;
2637     }
2638     ViewAbstractModel::GetInstance()->SetFlexGrow(static_cast<float>(value));
2639 }
2640 
JsFlexShrink(const JSCallbackInfo & info)2641 void JSViewAbstract::JsFlexShrink(const JSCallbackInfo& info)
2642 {
2643     double value = 0.0;
2644     if (!ParseJsDouble(info[0], value)) {
2645         if (info[0]->IsNull() || info[0]->IsUndefined()) {
2646             // undefined use default value.
2647             ViewAbstractModel::GetInstance()->ResetFlexShrink();
2648             return;
2649         } else {
2650             return;
2651         }
2652     }
2653     // negative use default value.
2654     if (value < 0.0) {
2655         ViewAbstractModel::GetInstance()->ResetFlexShrink();
2656         return;
2657     }
2658     ViewAbstractModel::GetInstance()->SetFlexShrink(static_cast<float>(value));
2659 }
2660 
JsDisplayPriority(const JSCallbackInfo & info)2661 void JSViewAbstract::JsDisplayPriority(const JSCallbackInfo& info)
2662 {
2663     double value = 0.0;
2664     if (!ParseJsDouble(info[0], value)) {
2665         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
2666             ViewAbstractModel::GetInstance()->SetDisplayIndex(0);
2667         }
2668         return;
2669     }
2670     ViewAbstractModel::GetInstance()->SetDisplayIndex(static_cast<int32_t>(value));
2671 }
2672 
JsSharedTransition(const JSCallbackInfo & info)2673 void JSViewAbstract::JsSharedTransition(const JSCallbackInfo& info)
2674 {
2675     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING };
2676     auto jsVal = info[0];
2677     if (!CheckJSCallbackInfo("JsSharedTransition", jsVal, checkList)) {
2678         return;
2679     }
2680     // id
2681     auto id = jsVal->ToString();
2682     if (id.empty()) {
2683         return;
2684     }
2685     std::shared_ptr<SharedTransitionOption> sharedOption;
2686 
2687     // options
2688     if (info.Length() > 1 && info[1]->IsObject()) {
2689         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[1]);
2690         sharedOption = std::make_shared<SharedTransitionOption>();
2691         // default: duration: 1000
2692         sharedOption->duration = jsObj->GetPropertyValue<int32_t>("duration", DEFAULT_DURATION);
2693         if (sharedOption->duration < 0) {
2694             sharedOption->duration = DEFAULT_DURATION;
2695         }
2696         // default: delay: 0
2697         sharedOption->delay = jsObj->GetPropertyValue<int32_t>("delay", 0);
2698         if (sharedOption->delay < 0) {
2699             sharedOption->delay = 0;
2700         }
2701         // default: LinearCurve
2702         RefPtr<Curve> curve;
2703         JSRef<JSVal> curveArgs = jsObj->GetProperty("curve");
2704         if (curveArgs->IsString()) {
2705             curve = CreateCurve(jsObj->GetPropertyValue<std::string>("curve", "linear"), false);
2706         } else if (curveArgs->IsObject()) {
2707             JSRef<JSVal> curveString = JSRef<JSObject>::Cast(curveArgs)->GetProperty("__curveString");
2708             if (!curveString->IsString()) {
2709                 return;
2710             }
2711             curve = CreateCurve(curveString->ToString(), false);
2712         }
2713         if (!curve) {
2714             curve = Curves::LINEAR;
2715         }
2716         sharedOption->curve = curve;
2717         // motionPath
2718         if (jsObj->HasProperty("motionPath")) {
2719             MotionPathOption motionPathOption;
2720             if (ParseMotionPath(jsObj->GetProperty("motionPath"), motionPathOption)) {
2721                 sharedOption->motionPathOption = motionPathOption;
2722             }
2723         }
2724         // zIndex
2725         sharedOption->zIndex = jsObj->GetPropertyValue<int32_t>("zIndex", 0);
2726         // type
2727         int32_t type = jsObj->GetPropertyValue<int32_t>("type",
2728             static_cast<int32_t>(SharedTransitionEffectType::SHARED_EFFECT_EXCHANGE));
2729         sharedOption->type = static_cast<SharedTransitionEffectType>(type);
2730     }
2731     ViewAbstractModel::GetInstance()->SetSharedTransition(id, sharedOption);
2732 }
2733 
JsGeometryTransition(const JSCallbackInfo & info)2734 void JSViewAbstract::JsGeometryTransition(const JSCallbackInfo& info)
2735 {
2736     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING };
2737     auto jsVal = info[0];
2738     if (!CheckJSCallbackInfo("JsGeometryTransition", jsVal, checkList)) {
2739         return;
2740     }
2741     // id
2742     auto id = jsVal->ToString();
2743     // follow flag
2744     bool followWithOutTransition = false;
2745     // hierarchy flag
2746     bool doRegisterSharedTransition = true;
2747     if (info.Length() >= PARAMETER_LENGTH_SECOND && info[1]->IsObject()) {
2748         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[1]);
2749         ParseJsBool(jsOption->GetProperty("follow"), followWithOutTransition);
2750 
2751         auto transitionHierarchyStrategy = static_cast<int32_t>(TransitionHierarchyStrategy::ADAPTIVE);
2752         ParseJsInt32(jsOption->GetProperty("hierarchyStrategy"), transitionHierarchyStrategy);
2753         switch (transitionHierarchyStrategy) {
2754             case static_cast<int32_t>(TransitionHierarchyStrategy::NONE):
2755                 doRegisterSharedTransition = false;
2756                 break;
2757             case static_cast<int32_t>(TransitionHierarchyStrategy::ADAPTIVE):
2758                 doRegisterSharedTransition = true;
2759                 break;
2760             default:
2761                 break;
2762         }
2763     }
2764     ViewAbstractModel::GetInstance()->SetGeometryTransition(id, followWithOutTransition, doRegisterSharedTransition);
2765 }
2766 
JsAlignSelf(const JSCallbackInfo & info)2767 void JSViewAbstract::JsAlignSelf(const JSCallbackInfo& info)
2768 {
2769     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
2770     auto jsVal = info[0];
2771     if (!CheckJSCallbackInfo("JsAlignSelf", jsVal, checkList)) {
2772         ViewAbstractModel::GetInstance()->SetAlignSelf(FlexAlign::AUTO);
2773         return;
2774     }
2775     auto alignVal = jsVal->ToNumber<int32_t>();
2776 
2777     if (alignVal >= 0 && alignVal <= MAX_ALIGN_VALUE) {
2778         ViewAbstractModel::GetInstance()->SetAlignSelf(static_cast<FlexAlign>(alignVal));
2779     }
2780 }
2781 
JsBackgroundColor(const JSCallbackInfo & info)2782 void JSViewAbstract::JsBackgroundColor(const JSCallbackInfo& info)
2783 {
2784     Color backgroundColor;
2785     if (!ParseJsColor(info[0], backgroundColor)) {
2786         backgroundColor = Color::TRANSPARENT;
2787     }
2788 
2789     ViewAbstractModel::GetInstance()->SetBackgroundColor(backgroundColor);
2790 }
2791 
JsBackgroundImage(const JSCallbackInfo & info)2792 void JSViewAbstract::JsBackgroundImage(const JSCallbackInfo& info)
2793 {
2794     int32_t resId = 0;
2795     std::string src;
2796     std::string bundle;
2797     std::string module;
2798     RefPtr<PixelMap> pixmap = nullptr;
2799     auto jsBackgroundImage = info[0];
2800     GetJsMediaBundleInfo(jsBackgroundImage, bundle, module);
2801     if (jsBackgroundImage->IsString()) {
2802         src = jsBackgroundImage->ToString();
2803         ViewAbstractModel::GetInstance()->SetBackgroundImage(
2804             ImageSourceInfo { src, bundle, module }, GetThemeConstants());
2805     } else if (ParseJsMediaWithBundleName(jsBackgroundImage, src, bundle, module, resId)) {
2806         ViewAbstractModel::GetInstance()->SetBackgroundImage(ImageSourceInfo { src, bundle, module }, nullptr);
2807     } else {
2808 #if defined(PIXEL_MAP_SUPPORTED)
2809         if (IsDrawable(jsBackgroundImage)) {
2810             pixmap = GetDrawablePixmap(jsBackgroundImage);
2811         } else {
2812             pixmap = CreatePixelMapFromNapiValue(jsBackgroundImage);
2813         }
2814 #endif
2815         ViewAbstractModel::GetInstance()->SetBackgroundImage(ImageSourceInfo { pixmap }, nullptr);
2816     }
2817 
2818     int32_t repeatIndex = 0;
2819     if (info.Length() == 2) {
2820         auto jsImageRepeat = info[1];
2821         if (jsImageRepeat->IsNumber()) {
2822             repeatIndex = jsImageRepeat->ToNumber<int32_t>();
2823         }
2824     }
2825     auto repeat = static_cast<ImageRepeat>(repeatIndex);
2826     ViewAbstractModel::GetInstance()->SetBackgroundImageRepeat(repeat);
2827 }
2828 
ParseBlurOption(const JSRef<JSObject> & jsBlurOption,BlurOption & blurOption)2829 void JSViewAbstract::ParseBlurOption(const JSRef<JSObject>& jsBlurOption, BlurOption& blurOption)
2830 {
2831     if (jsBlurOption->GetProperty("grayscale")->IsArray()) {
2832         JSRef<JSArray> params = JSRef<JSArray>::Cast(jsBlurOption->GetProperty("grayscale"));
2833         auto grey1 = params->GetValueAt(0)->ToNumber<uint32_t>();
2834         auto grey2 = params->GetValueAt(1)->ToNumber<uint32_t>();
2835         std::vector<float> greyVec(2); // 2 number
2836         greyVec[0] = grey1;
2837         greyVec[1] = grey2;
2838         blurOption.grayscale = greyVec;
2839     }
2840 }
2841 
ParseBlurStyleOption(const JSRef<JSObject> & jsOption,BlurStyleOption & styleOption)2842 void JSViewAbstract::ParseBlurStyleOption(const JSRef<JSObject>& jsOption, BlurStyleOption& styleOption)
2843 {
2844     auto colorMode = static_cast<int32_t>(ThemeColorMode::SYSTEM);
2845     ParseJsInt32(jsOption->GetProperty("colorMode"), colorMode);
2846     if (colorMode >= static_cast<int32_t>(ThemeColorMode::SYSTEM) &&
2847         colorMode <= static_cast<int32_t>(ThemeColorMode::DARK)) {
2848         styleOption.colorMode = static_cast<ThemeColorMode>(colorMode);
2849     }
2850     auto adaptiveColor = static_cast<int32_t>(AdaptiveColor::DEFAULT);
2851     ParseJsInt32(jsOption->GetProperty("adaptiveColor"), adaptiveColor);
2852     if (adaptiveColor >= static_cast<int32_t>(AdaptiveColor::DEFAULT) &&
2853         adaptiveColor <= static_cast<int32_t>(AdaptiveColor::AVERAGE)) {
2854         styleOption.adaptiveColor = static_cast<AdaptiveColor>(adaptiveColor);
2855     }
2856 
2857     // policy
2858     auto policy = static_cast<int32_t>(BlurStyleActivePolicy::ALWAYS_ACTIVE);
2859     ParseJsInt32(jsOption->GetProperty("policy"), policy);
2860     if (policy >= static_cast<int32_t>(BlurStyleActivePolicy::FOLLOWS_WINDOW_ACTIVE_STATE) &&
2861         policy <= static_cast<int32_t>(BlurStyleActivePolicy::ALWAYS_INACTIVE)) {
2862         styleOption.policy = static_cast<BlurStyleActivePolicy>(policy);
2863     }
2864 
2865     // blurType
2866     auto blurType = static_cast<int32_t>(BlurType::WITHIN_WINDOW);
2867     ParseJsInt32(jsOption->GetProperty("type"), blurType);
2868     if (blurType >= static_cast<int32_t>(BlurType::WITHIN_WINDOW) &&
2869         blurType <= static_cast<int32_t>(BlurType::BEHIND_WINDOW)) {
2870         styleOption.blurType = static_cast<BlurType>(blurType);
2871     }
2872 
2873     // inactiveColor
2874     if (ParseJsColor(jsOption->GetProperty("inactiveColor"), styleOption.inactiveColor)) {
2875         styleOption.isValidColor = true;
2876     }
2877 
2878     // scale
2879     if (jsOption->GetProperty("scale")->IsNumber()) {
2880         double scale = jsOption->GetProperty("scale")->ToNumber<double>();
2881         styleOption.scale = std::clamp(scale, 0.0, 1.0);
2882     }
2883 
2884     if (jsOption->GetProperty("blurOptions")->IsObject()) {
2885         JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(jsOption->GetProperty("blurOptions"));
2886         BlurOption blurOption;
2887         ParseBlurOption(jsBlurOption, blurOption);
2888         styleOption.blurOption = blurOption;
2889     }
2890 }
2891 
JsBackgroundBlurStyle(const JSCallbackInfo & info)2892 void JSViewAbstract::JsBackgroundBlurStyle(const JSCallbackInfo& info)
2893 {
2894     if (info.Length() == 0) {
2895         return;
2896     }
2897     BlurStyleOption styleOption;
2898     if (info[0]->IsNumber()) {
2899         auto blurStyle = info[0]->ToNumber<int32_t>();
2900         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
2901             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
2902             styleOption.blurStyle = static_cast<BlurStyle>(blurStyle);
2903         }
2904     }
2905     if (info.Length() > 1 && info[1]->IsObject()) {
2906         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[1]);
2907         ParseBlurStyleOption(jsOption, styleOption);
2908     }
2909     ViewAbstractModel::GetInstance()->SetBackgroundBlurStyle(styleOption);
2910 }
2911 
ParseBrightnessOption(const JSRef<JSObject> & jsOption,BrightnessOption & brightnessOption)2912 void JSViewAbstract::ParseBrightnessOption(const JSRef<JSObject>& jsOption, BrightnessOption& brightnessOption)
2913 {
2914     double rate = 1.0f;
2915     if (jsOption->GetProperty("rate")->IsNumber()) {
2916         rate = jsOption->GetProperty("rate")->ToNumber<double>();
2917     }
2918     double lightUpDegree = 0.0f;
2919     if (jsOption->GetProperty("lightUpDegree")->IsNumber()) {
2920         lightUpDegree = jsOption->GetProperty("lightUpDegree")->ToNumber<double>();
2921     }
2922     double cubicCoeff = 0.0f;
2923     if (jsOption->GetProperty("cubicCoeff")->IsNumber()) {
2924         cubicCoeff = jsOption->GetProperty("cubicCoeff")->ToNumber<double>();
2925     }
2926     double quadCoeff = 0.0f;
2927     if (jsOption->GetProperty("quadCoeff")->IsNumber()) {
2928         quadCoeff = jsOption->GetProperty("quadCoeff")->ToNumber<double>();
2929     }
2930     double saturation = 1.0f;
2931     if (jsOption->GetProperty("saturation")->IsNumber()) {
2932         saturation = jsOption->GetProperty("saturation")->ToNumber<double>();
2933     }
2934     std::vector<float> posRGB(3, 0.0);
2935     if (jsOption->GetProperty("posRGB")->IsArray()) {
2936         JSRef<JSArray> params = JSRef<JSArray>::Cast(jsOption->GetProperty("posRGB"));
2937         auto r = params->GetValueAt(0)->ToNumber<double>();
2938         auto g = params->GetValueAt(1)->ToNumber<double>();
2939         auto b = params->GetValueAt(2)->ToNumber<double>();
2940         posRGB[0] = r;
2941         posRGB[1] = g;
2942         posRGB[2] = b;
2943     }
2944     std::vector<float> negRGB(3, 0.0);
2945     if (jsOption->GetProperty("negRGB")->IsArray()) {
2946         JSRef<JSArray> params = JSRef<JSArray>::Cast(jsOption->GetProperty("negRGB"));
2947         auto r = params->GetValueAt(0)->ToNumber<double>();
2948         auto g = params->GetValueAt(1)->ToNumber<double>();
2949         auto b = params->GetValueAt(2)->ToNumber<double>();
2950         negRGB[0] = r;
2951         negRGB[1] = g;
2952         negRGB[2] = b;
2953     }
2954     double fraction = 1.0f;
2955     if (jsOption->GetProperty("fraction")->IsNumber()) {
2956         fraction = jsOption->GetProperty("fraction")->ToNumber<double>();
2957         fraction = std::clamp(fraction, 0.0, 1.0);
2958     }
2959     brightnessOption = { rate, lightUpDegree, cubicCoeff, quadCoeff, saturation, posRGB, negRGB, fraction };
2960 }
2961 
ParseEffectOption(const JSRef<JSObject> & jsOption,EffectOption & effectOption)2962 void JSViewAbstract::ParseEffectOption(const JSRef<JSObject>& jsOption, EffectOption& effectOption)
2963 {
2964     CalcDimension radius;
2965     if (!ParseJsDimensionVp(jsOption->GetProperty("radius"), radius) || LessNotEqual(radius.Value(), 0.0f)) {
2966         radius.SetValue(0.0f);
2967     }
2968     effectOption.radius = radius;
2969 
2970     double saturation = 1.0f;
2971     if (jsOption->GetProperty("saturation")->IsNumber()) {
2972         saturation = jsOption->GetProperty("saturation")->ToNumber<double>();
2973         saturation = (saturation > 0.0f || NearZero(saturation)) ? saturation : 1.0f;
2974     }
2975     effectOption.saturation = saturation;
2976 
2977     double brightness = 1.0f;
2978     if (jsOption->GetProperty("brightness")->IsNumber()) {
2979         brightness = jsOption->GetProperty("brightness")->ToNumber<double>();
2980         brightness = (brightness > 0.0f || NearZero(brightness)) ? brightness : 1.0f;
2981     }
2982     effectOption.brightness = brightness;
2983 
2984     ParseJsColor(jsOption->GetProperty("color"), effectOption.color);
2985 
2986     auto adaptiveColorValue = static_cast<int32_t>(AdaptiveColor::DEFAULT);
2987     auto adaptiveColor = AdaptiveColor::DEFAULT;
2988     ParseJsInt32(jsOption->GetProperty("adaptiveColor"), adaptiveColorValue);
2989     if (adaptiveColorValue >= static_cast<int32_t>(AdaptiveColor::DEFAULT) &&
2990         adaptiveColorValue <= static_cast<int32_t>(AdaptiveColor::AVERAGE)) {
2991         adaptiveColor = static_cast<AdaptiveColor>(adaptiveColorValue);
2992     }
2993     effectOption.adaptiveColor = adaptiveColor;
2994 
2995     // policy
2996     auto policy = static_cast<int32_t>(BlurStyleActivePolicy::ALWAYS_ACTIVE);
2997     ParseJsInt32(jsOption->GetProperty("policy"), policy);
2998     if (policy >= static_cast<int32_t>(BlurStyleActivePolicy::FOLLOWS_WINDOW_ACTIVE_STATE) &&
2999         policy <= static_cast<int32_t>(BlurStyleActivePolicy::ALWAYS_INACTIVE)) {
3000         effectOption.policy = static_cast<BlurStyleActivePolicy>(policy);
3001     }
3002 
3003     // blurType
3004     auto blurType = static_cast<int32_t>(BlurType::WITHIN_WINDOW);
3005     ParseJsInt32(jsOption->GetProperty("type"), blurType);
3006     if (blurType >= static_cast<int32_t>(BlurType::WITHIN_WINDOW) &&
3007         blurType <= static_cast<int32_t>(BlurType::BEHIND_WINDOW)) {
3008         effectOption.blurType = static_cast<BlurType>(blurType);
3009     }
3010 
3011     // inactiveColor
3012     if (ParseJsColor(jsOption->GetProperty("inactiveColor"), effectOption.inactiveColor)) {
3013         effectOption.isValidColor = true;
3014     }
3015 
3016     BlurOption blurOption;
3017     if (jsOption->GetProperty("blurOptions")->IsObject()) {
3018         JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(jsOption->GetProperty("blurOptions"));
3019         ParseBlurOption(jsBlurOption, blurOption);
3020         effectOption.blurOption = blurOption;
3021     }
3022 }
3023 
JsForegroundEffect(const JSCallbackInfo & info)3024 void JSViewAbstract::JsForegroundEffect(const JSCallbackInfo& info)
3025 {
3026     if (info.Length() == 0) {
3027         return;
3028     }
3029     float radius = 0.0;
3030     if (info[0]->IsObject()) {
3031         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[0]);
3032         if (jsOption->GetProperty("radius")->IsNumber()) {
3033             radius = jsOption->GetProperty("radius")->ToNumber<float>();
3034         }
3035     }
3036     radius = std::max(radius, 0.0f);
3037     ViewAbstractModel::GetInstance()->SetForegroundEffect(radius);
3038 }
3039 
JsBackgroundEffect(const JSCallbackInfo & info)3040 void JSViewAbstract::JsBackgroundEffect(const JSCallbackInfo& info)
3041 {
3042     if (info.Length() == 0) {
3043         return;
3044     }
3045     EffectOption option;
3046     if (info[0]->IsObject()) {
3047         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[0]);
3048         ParseEffectOption(jsOption, option);
3049     }
3050     ViewAbstractModel::GetInstance()->SetBackgroundEffect(option);
3051 }
3052 
JsForegroundBlurStyle(const JSCallbackInfo & info)3053 void JSViewAbstract::JsForegroundBlurStyle(const JSCallbackInfo& info)
3054 {
3055     if (info.Length() == 0) {
3056         return;
3057     }
3058     BlurStyleOption styleOption;
3059     if (info[0]->IsNumber()) {
3060         auto blurStyle = info[0]->ToNumber<int32_t>();
3061         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
3062             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
3063             styleOption.blurStyle = static_cast<BlurStyle>(blurStyle);
3064         }
3065     }
3066     if (info.Length() > 1 && info[1]->IsObject()) {
3067         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[1]);
3068         auto colorMode = static_cast<int32_t>(ThemeColorMode::SYSTEM);
3069         ParseJsInt32(jsOption->GetProperty("colorMode"), colorMode);
3070         if (colorMode >= static_cast<int32_t>(ThemeColorMode::SYSTEM) &&
3071             colorMode <= static_cast<int32_t>(ThemeColorMode::DARK)) {
3072             styleOption.colorMode = static_cast<ThemeColorMode>(colorMode);
3073         }
3074         auto adaptiveColor = static_cast<int32_t>(AdaptiveColor::DEFAULT);
3075         ParseJsInt32(jsOption->GetProperty("adaptiveColor"), adaptiveColor);
3076         if (adaptiveColor >= static_cast<int32_t>(AdaptiveColor::DEFAULT) &&
3077             adaptiveColor <= static_cast<int32_t>(AdaptiveColor::AVERAGE)) {
3078             styleOption.adaptiveColor = static_cast<AdaptiveColor>(adaptiveColor);
3079         }
3080         if (jsOption->GetProperty("scale")->IsNumber()) {
3081             double scale = jsOption->GetProperty("scale")->ToNumber<double>();
3082             styleOption.scale = std::clamp(scale, 0.0, 1.0);
3083         }
3084 
3085         if (jsOption->GetProperty("blurOptions")->IsObject()) {
3086             JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(jsOption->GetProperty("blurOptions"));
3087             BlurOption blurOption;
3088             ParseBlurOption(jsBlurOption, blurOption);
3089             styleOption.blurOption = blurOption;
3090         }
3091     }
3092     ViewAbstractModel::GetInstance()->SetForegroundBlurStyle(styleOption);
3093 }
3094 
JsSphericalEffect(const JSCallbackInfo & info)3095 void JSViewAbstract::JsSphericalEffect(const JSCallbackInfo& info)
3096 {
3097     auto radio = 0.0;
3098     if (info[0]->IsNumber()) {
3099         radio = info[0]->ToNumber<double>();
3100     }
3101     ViewAbstractModel::GetInstance()->SetSphericalEffect(std::clamp(radio, 0.0, 1.0));
3102 }
3103 
JsPixelStretchEffect(const JSCallbackInfo & info)3104 void JSViewAbstract::JsPixelStretchEffect(const JSCallbackInfo& info)
3105 {
3106     if (!info[0]->IsObject()) {
3107         PixStretchEffectOption option;
3108         option.ResetValue();
3109         ViewAbstractModel::GetInstance()->SetPixelStretchEffect(option);
3110         return;
3111     }
3112     auto jsObject = JSRef<JSObject>::Cast(info[0]);
3113     CalcDimension left;
3114     ParseJsDimensionVp(jsObject->GetProperty("left"), left);
3115     CalcDimension right;
3116     ParseJsDimensionVp(jsObject->GetProperty("right"), right);
3117     CalcDimension top;
3118     ParseJsDimensionVp(jsObject->GetProperty("top"), top);
3119     CalcDimension bottom;
3120     ParseJsDimensionVp(jsObject->GetProperty("bottom"), bottom);
3121 
3122     PixStretchEffectOption option;
3123     bool illegalInput = false;
3124     if (left.Unit() == DimensionUnit::PERCENT || right.Unit() == DimensionUnit::PERCENT ||
3125         top.Unit() == DimensionUnit::PERCENT || bottom.Unit() == DimensionUnit::PERCENT) {
3126         if ((NearEqual(left.Value(), 0.0) || left.Unit() == DimensionUnit::PERCENT) &&
3127             (NearEqual(top.Value(), 0.0) || top.Unit() == DimensionUnit::PERCENT) &&
3128             (NearEqual(right.Value(), 0.0) || right.Unit() == DimensionUnit::PERCENT) &&
3129             (NearEqual(bottom.Value(), 0.0) || bottom.Unit() == DimensionUnit::PERCENT)) {
3130             left.SetUnit(DimensionUnit::PERCENT);
3131             top.SetUnit(DimensionUnit::PERCENT);
3132             right.SetUnit(DimensionUnit::PERCENT);
3133             bottom.SetUnit(DimensionUnit::PERCENT);
3134         } else {
3135             illegalInput = true;
3136         }
3137     }
3138     if ((left.IsNonNegative() && top.IsNonNegative() && right.IsNonNegative() && bottom.IsNonNegative()) ||
3139         (left.IsNonPositive() && top.IsNonPositive() && right.IsNonPositive() && bottom.IsNonPositive())) {
3140         option.left = left;
3141         option.top = top;
3142         option.right = right;
3143         option.bottom = bottom;
3144     } else {
3145         illegalInput = true;
3146     }
3147     if (illegalInput) {
3148         option.ResetValue();
3149     }
3150     ViewAbstractModel::GetInstance()->SetPixelStretchEffect(option);
3151 }
3152 
JsLightUpEffect(const JSCallbackInfo & info)3153 void JSViewAbstract::JsLightUpEffect(const JSCallbackInfo& info)
3154 {
3155     auto radio = 1.0;
3156     if (info[0]->IsNumber()) {
3157         radio = info[0]->ToNumber<double>();
3158     }
3159     ViewAbstractModel::GetInstance()->SetLightUpEffect(std::clamp(radio, 0.0, 1.0));
3160 }
3161 
JsBackgroundImageSize(const JSCallbackInfo & info)3162 void JSViewAbstract::JsBackgroundImageSize(const JSCallbackInfo& info)
3163 {
3164     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
3165     BackgroundImageSize bgImgSize;
3166     auto jsVal = info[0];
3167     if (!CheckJSCallbackInfo("JsBackgroundImageSize", jsVal, checkList)) {
3168         bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
3169         bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
3170         ViewAbstractModel::GetInstance()->SetBackgroundImageSize(bgImgSize);
3171         return;
3172     }
3173     if (jsVal->IsNumber()) {
3174         auto sizeType = static_cast<BackgroundImageSizeType>(jsVal->ToNumber<int32_t>());
3175         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
3176             (sizeType < BackgroundImageSizeType::CONTAIN || sizeType > BackgroundImageSizeType::FILL)) {
3177             sizeType = BackgroundImageSizeType::AUTO;
3178         }
3179         bgImgSize.SetSizeTypeX(sizeType);
3180         bgImgSize.SetSizeTypeY(sizeType);
3181     } else {
3182         CalcDimension width;
3183         CalcDimension height;
3184         JSRef<JSObject> object = JSRef<JSObject>::Cast(jsVal);
3185         ParseJsDimensionVp(object->GetProperty("width"), width);
3186         ParseJsDimensionVp(object->GetProperty("height"), height);
3187         double valueWidth = width.ConvertToPx();
3188         double valueHeight = height.ConvertToPx();
3189         BackgroundImageSizeType typeWidth = BackgroundImageSizeType::LENGTH;
3190         BackgroundImageSizeType typeHeight = BackgroundImageSizeType::LENGTH;
3191         if (width.Unit() == DimensionUnit::PERCENT) {
3192             typeWidth = BackgroundImageSizeType::PERCENT;
3193             valueWidth = width.Value() * FULL_DIMENSION;
3194         }
3195         if (height.Unit() == DimensionUnit::PERCENT) {
3196             typeHeight = BackgroundImageSizeType::PERCENT;
3197             valueHeight = height.Value() * FULL_DIMENSION;
3198         }
3199         bgImgSize.SetSizeTypeX(typeWidth);
3200         bgImgSize.SetSizeValueX(valueWidth);
3201         bgImgSize.SetSizeTypeY(typeHeight);
3202         bgImgSize.SetSizeValueY(valueHeight);
3203     }
3204 
3205     ViewAbstractModel::GetInstance()->SetBackgroundImageSize(bgImgSize);
3206 }
3207 
SetBgImgPositionWithAlign(BackgroundImagePosition & bgImgPosition,int32_t align)3208 void SetBgImgPositionWithAlign(BackgroundImagePosition& bgImgPosition, int32_t align)
3209 {
3210     if (align > 8 || align < 0) {
3211         return;
3212     }
3213     std::vector<std::pair<double, double>> vec = { { 0.0, 0.0 }, { HALF_DIMENSION, 0.0 }, { FULL_DIMENSION, 0.0 },
3214         { 0.0, HALF_DIMENSION }, { HALF_DIMENSION, HALF_DIMENSION }, { FULL_DIMENSION, HALF_DIMENSION },
3215         { 0.0, FULL_DIMENSION }, { HALF_DIMENSION, FULL_DIMENSION }, { FULL_DIMENSION, FULL_DIMENSION } };
3216     SetBgImgPosition(
3217                 DimensionUnit::PERCENT, DimensionUnit::PERCENT, vec[align].first, vec[align].second, bgImgPosition);
3218 }
3219 
JsBackgroundImagePosition(const JSCallbackInfo & info)3220 void JSViewAbstract::JsBackgroundImagePosition(const JSCallbackInfo& info)
3221 {
3222     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
3223     BackgroundImagePosition bgImgPosition;
3224     auto jsVal = info[0];
3225     if (!CheckJSCallbackInfo("JsBackgroundImagePosition", jsVal, checkList)) {
3226         SetBgImgPosition(DimensionUnit::PX, DimensionUnit::PX, 0.0, 0.0, bgImgPosition);
3227         ViewAbstractModel::GetInstance()->SetBackgroundImagePosition(bgImgPosition);
3228         return;
3229     }
3230     if (jsVal->IsNumber()) {
3231         int32_t align = jsVal->ToNumber<int32_t>();
3232         bgImgPosition.SetIsAlign(true);
3233         SetBgImgPositionWithAlign(bgImgPosition, align);
3234     } else {
3235         CalcDimension x;
3236         CalcDimension y;
3237         JSRef<JSObject> object = JSRef<JSObject>::Cast(jsVal);
3238         ParseJsDimensionVp(object->GetProperty("x"), x);
3239         ParseJsDimensionVp(object->GetProperty("y"), y);
3240         double valueX = x.Value();
3241         double valueY = y.Value();
3242         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
3243             valueX = x.ConvertToPx();
3244             valueY = y.ConvertToPx();
3245         }
3246         DimensionUnit typeX = DimensionUnit::PX;
3247         DimensionUnit typeY = DimensionUnit::PX;
3248         if (x.Unit() == DimensionUnit::PERCENT) {
3249             valueX = x.Value();
3250             typeX = DimensionUnit::PERCENT;
3251         }
3252         if (y.Unit() == DimensionUnit::PERCENT) {
3253             valueY = y.Value();
3254             typeY = DimensionUnit::PERCENT;
3255         }
3256         SetBgImgPosition(typeX, typeY, valueX, valueY, bgImgPosition);
3257     }
3258 
3259     ViewAbstractModel::GetInstance()->SetBackgroundImagePosition(bgImgPosition);
3260 }
3261 
ParseBindOptionParam(const JSCallbackInfo & info,size_t optionIndex)3262 std::vector<NG::OptionParam> ParseBindOptionParam(const JSCallbackInfo& info, size_t optionIndex)
3263 {
3264     JSRef<JSVal> arg = info[optionIndex];
3265     if (!arg->IsArray()) {
3266         return std::vector<NG::OptionParam>();
3267     }
3268     auto paramArray = JSRef<JSArray>::Cast(arg);
3269     auto paramArrayLength = paramArray->Length();
3270     std::vector<NG::OptionParam> params(paramArrayLength);
3271     // parse paramArray
3272     for (size_t i = 0; i < paramArrayLength; ++i) {
3273         if (!paramArray->GetValueAt(i)->IsObject()) {
3274             return std::vector<NG::OptionParam>();
3275         }
3276         auto indexObject = JSRef<JSObject>::Cast(paramArray->GetValueAt(i));
3277         JSViewAbstract::ParseJsString(indexObject->GetProperty(static_cast<int32_t>(ArkUIIndex::VALUE)),
3278             params[i].value);
3279         auto actionFunc = indexObject->GetProperty(static_cast<int32_t>(ArkUIIndex::ACTION));
3280         if (!actionFunc->IsFunction()) {
3281             return params;
3282         }
3283         auto action = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(actionFunc));
3284         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
3285         // set onClick function
3286         params[i].action = [func = std::move(action), context = info.GetExecutionContext(), node = targetNode]() {
3287             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context);
3288             ACE_SCORING_EVENT("menu.action");
3289             PipelineContext::SetCallBackNode(node);
3290             if (func) {
3291                 func->Execute();
3292             }
3293         };
3294         std::string iconPath;
3295         if (JSViewAbstract::ParseJsMedia(indexObject->GetProperty(static_cast<int32_t>(ArkUIIndex::ICON)), iconPath)) {
3296             params[i].icon = iconPath;
3297         }
3298         if (indexObject->GetProperty(static_cast<int32_t>(ArkUIIndex::SYMBOL_ICON))->IsObject()) {
3299             std::function<void(WeakPtr<NG::FrameNode>)> symbolApply;
3300             JSViewAbstract::SetSymbolOptionApply(info, symbolApply,
3301                 indexObject->GetProperty(static_cast<int32_t>(ArkUIIndex::SYMBOL_ICON)));
3302             params[i].symbol = symbolApply;
3303         }
3304         auto enabled = indexObject->GetProperty(static_cast<int32_t>(ArkUIIndex::ENABLED));
3305         if (enabled->IsBoolean()) {
3306             params[i].enabled = enabled->ToBoolean();
3307         }
3308     }
3309     return params;
3310 }
3311 
ParseMenuBorderRadius(const JSRef<JSObject> & menuOptions,NG::MenuParam & menuParam)3312 void ParseMenuBorderRadius(const JSRef<JSObject>& menuOptions, NG::MenuParam& menuParam)
3313 {
3314     auto borderRadiusValue = menuOptions->GetProperty(static_cast<int32_t>(ArkUIIndex::BORDER_RADIUS));
3315     NG::BorderRadiusProperty menuBorderRadius;
3316     CalcDimension borderRadius;
3317     if (JSViewAbstract::ParseJsDimensionVp(borderRadiusValue, borderRadius)) {
3318         if (borderRadius.Unit() != DimensionUnit::PERCENT && GreatOrEqual(borderRadius.Value(), 0.0f)) {
3319             menuBorderRadius.SetRadius(borderRadius);
3320             menuBorderRadius.multiValued = false;
3321             menuParam.borderRadius = menuBorderRadius;
3322         };
3323     } else if (borderRadiusValue->IsObject()) {
3324         JSRef<JSObject> object = JSRef<JSObject>::Cast(borderRadiusValue);
3325         CalcDimension topLeft;
3326         CalcDimension topRight;
3327         CalcDimension bottomLeft;
3328         CalcDimension bottomRight;
3329         bool hasSetBorderRadius =
3330             JSViewAbstract::ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight);
3331         if (LessNotEqual(topLeft.Value(), 0.0f)) {
3332             topLeft.Reset();
3333         }
3334         if (LessNotEqual(topRight.Value(), 0.0f)) {
3335             topRight.Reset();
3336         }
3337         if (LessNotEqual(bottomLeft.Value(), 0.0f)) {
3338             bottomLeft.Reset();
3339         }
3340         if (LessNotEqual(bottomRight.Value(), 0.0f)) {
3341             bottomRight.Reset();
3342         }
3343         auto isRtl = hasSetBorderRadius && AceApplicationInfo::GetInstance().IsRightToLeft();
3344         menuBorderRadius.radiusTopLeft = isRtl ? topRight : topLeft;
3345         menuBorderRadius.radiusTopRight = isRtl ? topLeft : topRight;
3346         menuBorderRadius.radiusBottomLeft = isRtl ? bottomRight : bottomLeft;
3347         menuBorderRadius.radiusBottomRight = isRtl ? bottomLeft : bottomRight;
3348         menuBorderRadius.multiValued = true;
3349         menuParam.borderRadius = menuBorderRadius;
3350     }
3351 }
3352 
ParseMenuArrowParam(const JSRef<JSObject> & menuOptions,NG::MenuParam & menuParam)3353 void ParseMenuArrowParam(const JSRef<JSObject>& menuOptions, NG::MenuParam& menuParam)
3354 {
3355     auto enableArrowValue = menuOptions->GetProperty("enableArrow");
3356     if (enableArrowValue->IsBoolean()) {
3357         menuParam.enableArrow = enableArrowValue->ToBoolean();
3358     }
3359 
3360     auto arrowOffset = menuOptions->GetProperty("arrowOffset");
3361     CalcDimension offset;
3362     if (JSViewAbstract::ParseJsDimensionVp(arrowOffset, offset)) {
3363         menuParam.arrowOffset = offset;
3364     }
3365 
3366     // if enableArrow is true and placement not set, set placement default value to top.
3367     if (menuParam.enableArrow.has_value() && !menuParam.placement.has_value() && menuParam.enableArrow.value()) {
3368         menuParam.placement = Placement::TOP;
3369     }
3370 }
3371 
ParseLayoutRegionMargin(const JSRef<JSVal> & jsValue,std::optional<CalcDimension> & calcDimension)3372 void ParseLayoutRegionMargin(const JSRef<JSVal>& jsValue, std::optional<CalcDimension>& calcDimension)
3373 {
3374     CalcDimension dimension;
3375     if (!JSViewAbstract::ParseJsDimensionVpNG(jsValue, dimension, true)) {
3376         return;
3377     }
3378 
3379     if (dimension.IsNonNegative() && dimension.CalcValue().find("calc") == std::string::npos) {
3380         calcDimension = dimension;
3381     }
3382 }
3383 
ParseMenuLayoutRegionMarginParam(const JSRef<JSObject> & menuOptions,NG::MenuParam & menuParam)3384 void ParseMenuLayoutRegionMarginParam(const JSRef<JSObject>& menuOptions, NG::MenuParam& menuParam)
3385 {
3386     auto marginVal = menuOptions->GetProperty("layoutRegionMargin");
3387     if (!marginVal->IsObject()) {
3388         return;
3389     }
3390 
3391     CommonCalcDimension commonCalcDimension;
3392     auto object = JSRef<JSObject>::Cast(marginVal);
3393     ParseLayoutRegionMargin(object->GetProperty(TOP_PROPERTY), commonCalcDimension.top);
3394     ParseLayoutRegionMargin(object->GetProperty(BOTTOM_PROPERTY), commonCalcDimension.bottom);
3395     ParseLayoutRegionMargin(object->GetProperty(LEFT_PROPERTY), commonCalcDimension.left);
3396     ParseLayoutRegionMargin(object->GetProperty(RIGHT_PROPERTY), commonCalcDimension.right);
3397 
3398     if (commonCalcDimension.left.has_value() || commonCalcDimension.right.has_value() ||
3399         commonCalcDimension.top.has_value() || commonCalcDimension.bottom.has_value()) {
3400         menuParam.layoutRegionMargin = JSViewAbstract::GetLocalizedPadding(
3401             commonCalcDimension.top, commonCalcDimension.bottom, commonCalcDimension.left, commonCalcDimension.right);
3402     }
3403 }
3404 
GetMenuShowInSubwindow(NG::MenuParam & menuParam)3405 void GetMenuShowInSubwindow(NG::MenuParam& menuParam)
3406 {
3407     menuParam.isShowInSubWindow = false;
3408     auto pipeline = PipelineBase::GetCurrentContext();
3409     CHECK_NULL_VOID(pipeline);
3410     auto theme = pipeline->GetTheme<SelectTheme>();
3411     CHECK_NULL_VOID(theme);
3412     menuParam.isShowInSubWindow = theme->GetExpandDisplay();
3413 }
3414 
ParseMenuParam(const JSCallbackInfo & info,const JSRef<JSObject> & menuOptions,NG::MenuParam & menuParam)3415 void ParseMenuParam(const JSCallbackInfo& info, const JSRef<JSObject>& menuOptions, NG::MenuParam& menuParam)
3416 {
3417     auto offsetVal = menuOptions->GetProperty("offset");
3418     if (offsetVal->IsObject()) {
3419         auto offsetObj = JSRef<JSObject>::Cast(offsetVal);
3420         JSRef<JSVal> xVal = offsetObj->GetProperty(static_cast<int32_t>(ArkUIIndex::X));
3421         JSRef<JSVal> yVal = offsetObj->GetProperty(static_cast<int32_t>(ArkUIIndex::Y));
3422         CalcDimension dx;
3423         CalcDimension dy;
3424         if (JSViewAbstract::ParseJsDimensionVp(xVal, dx)) {
3425             menuParam.positionOffset.SetX(dx.ConvertToPx());
3426         }
3427         if (JSViewAbstract::ParseJsDimensionVp(yVal, dy)) {
3428             menuParam.positionOffset.SetY(dy.ConvertToPx());
3429         }
3430     }
3431 
3432     auto placementValue = menuOptions->GetProperty("placement");
3433     if (placementValue->IsNumber()) {
3434         auto placement = placementValue->ToNumber<int32_t>();
3435         if (placement >= 0 && placement < static_cast<int32_t>(PLACEMENT.size())) {
3436             menuParam.placement = PLACEMENT[placement];
3437         }
3438     }
3439 
3440     auto backgroundColorValue = menuOptions->GetProperty(static_cast<int32_t>(ArkUIIndex::BACKGROUND_COLOR));
3441     Color backgroundColor;
3442     if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
3443         menuParam.backgroundColor = backgroundColor;
3444     }
3445 
3446     auto backgroundBlurStyle = menuOptions->GetProperty(static_cast<int32_t>(ArkUIIndex::BACKGROUND_BLUR_STYLE));
3447     if (backgroundBlurStyle->IsNumber()) {
3448         auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
3449         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
3450             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
3451             menuParam.backgroundBlurStyle = blurStyle;
3452         }
3453     }
3454     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
3455     auto onAppearValue = menuOptions->GetProperty("onAppear");
3456     if (onAppearValue->IsFunction()) {
3457         RefPtr<JsFunction> jsOnAppearFunc =
3458             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAppearValue));
3459         auto onAppear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAppearFunc), node = frameNode]() {
3460             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
3461             ACE_SCORING_EVENT("onAppear");
3462             PipelineContext::SetCallBackNode(node);
3463             func->Execute();
3464         };
3465         menuParam.onAppear = std::move(onAppear);
3466     }
3467 
3468     auto onDisappearValue = menuOptions->GetProperty("onDisappear");
3469     if (onDisappearValue->IsFunction()) {
3470         RefPtr<JsFunction> jsOnDisAppearFunc =
3471             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDisappearValue));
3472         auto onDisappear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDisAppearFunc),
3473                                node = frameNode]() {
3474             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
3475             ACE_SCORING_EVENT("onDisappear");
3476             PipelineContext::SetCallBackNode(node);
3477             func->Execute();
3478         };
3479         menuParam.onDisappear = std::move(onDisappear);
3480     }
3481     auto aboutToAppearValue = menuOptions->GetProperty("aboutToAppear");
3482     if (aboutToAppearValue->IsFunction()) {
3483         RefPtr<JsFunction> jsAboutToAppearFunc =
3484             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(aboutToAppearValue));
3485         auto aboutToAppear = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToAppearFunc),
3486                             node = frameNode]() {
3487             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
3488             ACE_SCORING_EVENT("aboutToAppear");
3489             PipelineContext::SetCallBackNode(node);
3490             func->Execute();
3491         };
3492         menuParam.aboutToAppear = std::move(aboutToAppear);
3493     }
3494 
3495     auto aboutToDisAppearValue = menuOptions->GetProperty("aboutToDisappear");
3496     if (aboutToDisAppearValue->IsFunction()) {
3497         RefPtr<JsFunction> jsAboutToDisAppearFunc =
3498             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(aboutToDisAppearValue));
3499         auto aboutToDisappear = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToDisAppearFunc),
3500                                node = frameNode]() {
3501             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
3502             ACE_SCORING_EVENT("aboutToDisappear");
3503             PipelineContext::SetCallBackNode(node);
3504             func->Execute();
3505         };
3506         menuParam.aboutToDisappear = std::move(aboutToDisappear);
3507     }
3508 
3509     auto menuTransition = menuOptions->GetProperty("transition");
3510     menuParam.hasTransitionEffect = false;
3511     if (menuTransition->IsObject()) {
3512         auto obj = JSRef<JSObject>::Cast(menuTransition);
3513         menuParam.hasTransitionEffect = true;
3514         menuParam.transition = ParseChainedTransition(obj, info.GetExecutionContext());
3515     }
3516 
3517     JSRef<JSVal> showInSubWindowValue = menuOptions->GetProperty("showInSubWindow");
3518     GetMenuShowInSubwindow(menuParam);
3519     if (menuParam.isShowInSubWindow) {
3520         if (showInSubWindowValue->IsBoolean()) {
3521             menuParam.isShowInSubWindow = showInSubWindowValue->ToBoolean();
3522         }
3523     }
3524     ParseMenuArrowParam(menuOptions, menuParam);
3525     ParseMenuBorderRadius(menuOptions, menuParam);
3526     ParseMenuLayoutRegionMarginParam(menuOptions, menuParam);
3527 }
3528 
ParseBindOptionParam(const JSCallbackInfo & info,NG::MenuParam & menuParam,size_t optionIndex)3529 void ParseBindOptionParam(const JSCallbackInfo& info, NG::MenuParam& menuParam, size_t optionIndex)
3530 {
3531     if (!info[optionIndex]->IsObject()) {
3532         return;
3533     }
3534     auto menuOptions = JSRef<JSObject>::Cast(info[optionIndex]);
3535     JSViewAbstract::ParseJsString(menuOptions->GetProperty("title"), menuParam.title);
3536     ParseMenuParam(info, menuOptions, menuParam);
3537 }
3538 
ParseAnimationScaleArray(const JSRef<JSArray> & scaleArray,MenuPreviewAnimationOptions & options)3539 void ParseAnimationScaleArray(const JSRef<JSArray>& scaleArray, MenuPreviewAnimationOptions& options)
3540 {
3541     constexpr int scaleArraySize = 2;
3542     if (scaleArray->Length() == scaleArraySize) {
3543         auto scalePropertyFrom = scaleArray->GetValueAt(0);
3544         if (scalePropertyFrom->IsNumber()) {
3545             auto scaleFrom = scalePropertyFrom->ToNumber<float>();
3546             options.scaleFrom = LessOrEqual(scaleFrom, 0.0) ? -1.0f : scaleFrom;
3547         }
3548         auto scalePropertyTo = scaleArray->GetValueAt(1);
3549         if (scalePropertyTo->IsNumber()) {
3550             auto scaleTo = scalePropertyTo->ToNumber<float>();
3551             options.scaleTo = LessOrEqual(scaleTo, 0.0) ? -1.0f : scaleTo;
3552         }
3553     }
3554 }
3555 
ParseContentPreviewAnimationOptionsParam(const JSCallbackInfo & info,const JSRef<JSObject> & menuContentOptions,NG::MenuParam & menuParam)3556 void ParseContentPreviewAnimationOptionsParam(const JSCallbackInfo& info, const JSRef<JSObject>& menuContentOptions,
3557     NG::MenuParam& menuParam)
3558 {
3559     menuParam.previewAnimationOptions.scaleFrom = -1.0f;
3560     menuParam.previewAnimationOptions.scaleTo = -1.0f;
3561 
3562     auto animationOptions = menuContentOptions->GetProperty("previewAnimationOptions");
3563     if (!animationOptions->IsEmpty() && animationOptions->IsObject()) {
3564         auto animationOptionsObj = JSRef<JSObject>::Cast(animationOptions);
3565         auto scaleProperty = animationOptionsObj->GetProperty("scale");
3566         if (!scaleProperty->IsEmpty() && scaleProperty->IsArray()) {
3567             JSRef<JSArray> scaleArray = JSRef<JSArray>::Cast(scaleProperty);
3568             ParseAnimationScaleArray(scaleArray, menuParam.previewAnimationOptions);
3569         }
3570         auto previewTransition = animationOptionsObj->GetProperty("transition");
3571         menuParam.hasPreviewTransitionEffect = false;
3572         if (previewTransition->IsObject()) {
3573             auto obj = JSRef<JSObject>::Cast(previewTransition);
3574             menuParam.hasPreviewTransitionEffect = true;
3575             menuParam.previewTransition = ParseChainedTransition(obj, info.GetExecutionContext());
3576         }
3577         if (menuParam.previewMode != MenuPreviewMode::CUSTOM ||
3578             menuParam.hasPreviewTransitionEffect || menuParam.hasTransitionEffect ||
3579             menuParam.contextMenuRegisterType == NG::ContextMenuRegisterType::CUSTOM_TYPE) {
3580             return;
3581         }
3582         auto hoverScaleProperty = animationOptionsObj->GetProperty("hoverScale");
3583         menuParam.isShowHoverImage = false;
3584         menuParam.hoverImageAnimationOptions.scaleFrom = -1.0f;
3585         menuParam.hoverImageAnimationOptions.scaleTo = -1.0f;
3586         if (!hoverScaleProperty->IsEmpty() && hoverScaleProperty->IsArray()) {
3587             JSRef<JSArray> hoverScaleArray = JSRef<JSArray>::Cast(hoverScaleProperty);
3588             ParseAnimationScaleArray(hoverScaleArray, menuParam.hoverImageAnimationOptions);
3589             menuParam.isShowHoverImage = true;
3590         }
3591     }
3592 }
3593 
ParseBindContentOptionParam(const JSCallbackInfo & info,const JSRef<JSVal> & args,NG::MenuParam & menuParam,std::function<void ()> & previewBuildFunc)3594 void ParseBindContentOptionParam(const JSCallbackInfo& info, const JSRef<JSVal>& args, NG::MenuParam& menuParam,
3595     std::function<void()>& previewBuildFunc)
3596 {
3597     if (!args->IsObject()) {
3598         return;
3599     }
3600     auto menuContentOptions = JSRef<JSObject>::Cast(args);
3601     ParseMenuParam(info, menuContentOptions, menuParam);
3602     RefPtr<JsFunction> previewBuilderFunc;
3603     auto preview = menuContentOptions->GetProperty("preview");
3604     if (!preview->IsFunction() && !preview->IsNumber()) {
3605         return;
3606     }
3607 
3608     if (preview->IsNumber()) {
3609         if (preview->ToNumber<int32_t>() == 1) {
3610             menuParam.previewMode = MenuPreviewMode::IMAGE;
3611             ParseContentPreviewAnimationOptionsParam(info, menuContentOptions, menuParam);
3612         }
3613     } else {
3614         previewBuilderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(preview));
3615         CHECK_NULL_VOID(previewBuilderFunc);
3616         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
3617         previewBuildFunc = [execCtx = info.GetExecutionContext(), func = std::move(previewBuilderFunc),
3618                                node = frameNode]() {
3619             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
3620             ACE_SCORING_EVENT("BuildContextMenuPreviwer");
3621             PipelineContext::SetCallBackNode(node);
3622             func->Execute();
3623         };
3624         menuParam.previewMode = MenuPreviewMode::CUSTOM;
3625         ParseContentPreviewAnimationOptionsParam(info, menuContentOptions, menuParam);
3626     }
3627 }
3628 
ParseBindContextMenuShow(const JSCallbackInfo & info,NG::MenuParam & menuParam)3629 uint32_t ParseBindContextMenuShow(const JSCallbackInfo& info, NG::MenuParam& menuParam)
3630 {
3631     size_t builderIndex = 0;
3632     if (info[0]->IsBoolean()) {
3633         menuParam.isShow = info[0]->ToBoolean();
3634         menuParam.contextMenuRegisterType = NG::ContextMenuRegisterType::CUSTOM_TYPE;
3635         menuParam.placement = Placement::BOTTOM_LEFT;
3636         builderIndex = 1;
3637     } else if (info[0]->IsObject()) {
3638         JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(info[0]);
3639         menuParam.onStateChange = ParseDoubleBindCallback(info, callbackObj);
3640         auto isShowObj = callbackObj->GetProperty("value");
3641         if (isShowObj->IsBoolean()) {
3642             menuParam.isShow = isShowObj->IsBoolean();
3643             menuParam.contextMenuRegisterType = NG::ContextMenuRegisterType::CUSTOM_TYPE;
3644             builderIndex = 1;
3645         }
3646     }
3647     return builderIndex;
3648 }
3649 
JsBindMenu(const JSCallbackInfo & info)3650 void JSViewAbstract::JsBindMenu(const JSCallbackInfo& info)
3651 {
3652     NG::MenuParam menuParam;
3653     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
3654         menuParam.placement = Placement::BOTTOM_LEFT;
3655     }
3656     size_t builderIndex = 0;
3657     GetMenuShowInSubwindow(menuParam);
3658     if (info.Length() > PARAMETER_LENGTH_FIRST) {
3659         auto jsVal = info[0];
3660         if (jsVal->IsBoolean()) {
3661             menuParam.isShow = jsVal->ToBoolean();
3662             menuParam.setShow = true;
3663             builderIndex = 1;
3664             if (info.Length() > PARAMETER_LENGTH_SECOND) {
3665                 ParseBindOptionParam(info, menuParam, builderIndex + 1);
3666             }
3667         } else if (jsVal->IsUndefined()) {
3668             menuParam.setShow = true;
3669             menuParam.isShow = false;
3670             builderIndex = 1;
3671             if (info.Length() > PARAMETER_LENGTH_SECOND) {
3672                 ParseBindOptionParam(info, menuParam, builderIndex + 1);
3673             }
3674         } else if (jsVal->IsObject()) {
3675             JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(jsVal);
3676             menuParam.onStateChange = ParseDoubleBindCallback(info, callbackObj);
3677             auto isShowObj = callbackObj->GetProperty(static_cast<int32_t>(ArkUIIndex::VALUE));
3678             if (isShowObj->IsBoolean()) {
3679                 menuParam.isShow = isShowObj->ToBoolean();
3680                 menuParam.setShow = true;
3681                 builderIndex = 1;
3682                 if (info.Length() > PARAMETER_LENGTH_SECOND) {
3683                     ParseBindOptionParam(info, menuParam, builderIndex + 1);
3684                 }
3685             } else {
3686                 builderIndex = 0;
3687                 ParseBindOptionParam(info, menuParam, builderIndex + 1);
3688             }
3689         }
3690     }
3691 
3692     if (info[builderIndex]->IsArray()) {
3693         std::vector<NG::OptionParam> optionsParam = ParseBindOptionParam(info, builderIndex);
3694         ViewAbstractModel::GetInstance()->BindMenu(std::move(optionsParam), nullptr, menuParam);
3695     } else if (info[builderIndex]->IsObject()) {
3696         // CustomBuilder
3697         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[builderIndex]);
3698         auto builder = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::BUILDER));
3699         if (!builder->IsFunction()) {
3700             return;
3701         }
3702         auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
3703 
3704         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
3705         CHECK_NULL_VOID(builderFunc);
3706         auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = frameNode]() {
3707             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
3708             ACE_SCORING_EVENT("BuildMenu");
3709             auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
3710             func->Execute();
3711         };
3712         ViewAbstractModel::GetInstance()->BindMenu({}, std::move(buildFunc), menuParam);
3713     }
3714 }
3715 
JsPadding(const JSCallbackInfo & info)3716 void JSViewAbstract::JsPadding(const JSCallbackInfo& info)
3717 {
3718     ParseMarginOrPadding(info, EdgeType::PADDING);
3719 }
3720 
JsMargin(const JSCallbackInfo & info)3721 void JSViewAbstract::JsMargin(const JSCallbackInfo& info)
3722 {
3723     ParseMarginOrPadding(info, EdgeType::MARGIN);
3724 }
3725 
ParseMarginOrPadding(const JSCallbackInfo & info,EdgeType type)3726 void JSViewAbstract::ParseMarginOrPadding(const JSCallbackInfo& info, EdgeType type)
3727 {
3728     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT, JSCallbackInfoType::STRING,
3729         JSCallbackInfoType::NUMBER };
3730     auto jsVal = info[0];
3731     if (!CheckJSCallbackInfo("MarginOrPadding", jsVal, checkList)) {
3732         auto resetDimension = CalcDimension(0.0);
3733         if (type == EdgeType::MARGIN) {
3734             ViewAbstractModel::GetInstance()->SetMargin(resetDimension);
3735         } else if (type == EdgeType::PADDING) {
3736             ViewAbstractModel::GetInstance()->SetPadding(resetDimension);
3737         } else if (type == EdgeType::SAFE_AREA_PADDING) {
3738             ViewAbstractModel::GetInstance()->ResetSafeAreaPadding();
3739         }
3740         return;
3741     }
3742 
3743     if (jsVal->IsObject()) {
3744         JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(jsVal);
3745 
3746         CalcDimension length;
3747         if (type == EdgeType::SAFE_AREA_PADDING && ParseJsLengthMetrics(paddingObj, length)) {
3748             ViewAbstractModel::GetInstance()->SetSafeAreaPadding(length);
3749             return;
3750         }
3751 
3752         CommonCalcDimension commonCalcDimension;
3753         auto useLengthMetrics = ParseCommonMarginOrPaddingCorner(paddingObj, commonCalcDimension);
3754         if (commonCalcDimension.left.has_value() || commonCalcDimension.right.has_value() ||
3755             commonCalcDimension.top.has_value() || commonCalcDimension.bottom.has_value()) {
3756             if (type == EdgeType::MARGIN)  {
3757                 if (useLengthMetrics) {
3758                     ViewAbstractModel::GetInstance()->SetMargins(GetLocalizedPadding(commonCalcDimension.top,
3759                         commonCalcDimension.bottom, commonCalcDimension.left, commonCalcDimension.right));
3760                 } else {
3761                     ViewAbstractModel::GetInstance()->SetMargins(commonCalcDimension.top, commonCalcDimension.bottom,
3762                         commonCalcDimension.left, commonCalcDimension.right);
3763                 }
3764             } else if (type == EdgeType::PADDING) {
3765                 if (useLengthMetrics) {
3766                     ViewAbstractModel::GetInstance()->SetPaddings(GetLocalizedPadding(commonCalcDimension.top,
3767                         commonCalcDimension.bottom, commonCalcDimension.left, commonCalcDimension.right));
3768                 } else {
3769                     ViewAbstractModel::GetInstance()->SetPaddings(commonCalcDimension.top, commonCalcDimension.bottom,
3770                         commonCalcDimension.left, commonCalcDimension.right);
3771                 }
3772             } else if (type == EdgeType::SAFE_AREA_PADDING) {
3773                 if (useLengthMetrics) {
3774                     ViewAbstractModel::GetInstance()->SetSafeAreaPaddings(GetLocalizedPadding(commonCalcDimension.top,
3775                         commonCalcDimension.bottom, commonCalcDimension.left, commonCalcDimension.right));
3776                 } else {
3777                     ViewAbstractModel::GetInstance()->SetSafeAreaPaddings(commonCalcDimension.top,
3778                         commonCalcDimension.bottom, commonCalcDimension.left, commonCalcDimension.right);
3779                 }
3780             }
3781             return;
3782         }
3783     }
3784 
3785     CalcDimension length;
3786     if (!ParseJsDimensionVp(jsVal, length)) {
3787         // use default value.
3788         length.Reset();
3789     }
3790     if (type == EdgeType::MARGIN) {
3791         ViewAbstractModel::GetInstance()->SetMargin(length);
3792     } else if (type == EdgeType::PADDING) {
3793         ViewAbstractModel::GetInstance()->SetPadding(length);
3794     }
3795 }
3796 
GetLocalizedPadding(const std::optional<CalcDimension> & top,const std::optional<CalcDimension> & bottom,const std::optional<CalcDimension> & start,const std::optional<CalcDimension> & end)3797 NG::PaddingProperty JSViewAbstract::GetLocalizedPadding(const std::optional<CalcDimension>& top,
3798     const std::optional<CalcDimension>& bottom, const std::optional<CalcDimension>& start,
3799     const std::optional<CalcDimension>& end)
3800 {
3801     NG::PaddingProperty paddings;
3802     if (start.has_value()) {
3803         if (start.value().Unit() == DimensionUnit::CALC) {
3804             paddings.start = NG::CalcLength(start.value().CalcValue());
3805         } else {
3806             paddings.start = NG::CalcLength(start.value());
3807         }
3808     }
3809     if (bottom.has_value()) {
3810         if (bottom.value().Unit() == DimensionUnit::CALC) {
3811             paddings.bottom = NG::CalcLength(bottom.value().CalcValue());
3812         } else {
3813             paddings.bottom = NG::CalcLength(bottom.value());
3814         }
3815     }
3816     if (end.has_value()) {
3817         if (end.value().Unit() == DimensionUnit::CALC) {
3818             paddings.end = NG::CalcLength(end.value().CalcValue());
3819         } else {
3820             paddings.end = NG::CalcLength(end.value());
3821         }
3822     }
3823     if (top.has_value()) {
3824         if (top.value().Unit() == DimensionUnit::CALC) {
3825             paddings.top = NG::CalcLength(top.value().CalcValue());
3826         } else {
3827             paddings.top = NG::CalcLength(top.value());
3828         }
3829     }
3830     return paddings;
3831 }
3832 
ParseMarginOrPaddingCorner(JSRef<JSObject> obj,std::optional<CalcDimension> & top,std::optional<CalcDimension> & bottom,std::optional<CalcDimension> & left,std::optional<CalcDimension> & right)3833 void JSViewAbstract::ParseMarginOrPaddingCorner(JSRef<JSObject> obj, std::optional<CalcDimension>& top,
3834     std::optional<CalcDimension>& bottom, std::optional<CalcDimension>& left, std::optional<CalcDimension>& right)
3835 {
3836     CalcDimension leftDimen;
3837     if (ParseJsDimensionVp(obj->GetProperty(static_cast<int32_t>(ArkUIIndex::LEFT)), leftDimen)) {
3838         left = leftDimen;
3839     }
3840     CalcDimension rightDimen;
3841     if (ParseJsDimensionVp(obj->GetProperty(static_cast<int32_t>(ArkUIIndex::RIGHT)), rightDimen)) {
3842         right = rightDimen;
3843     }
3844     CalcDimension topDimen;
3845     if (ParseJsDimensionVp(obj->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP)), topDimen)) {
3846         top = topDimen;
3847     }
3848     CalcDimension bottomDimen;
3849     if (ParseJsDimensionVp(obj->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM)), bottomDimen)) {
3850         bottom = bottomDimen;
3851     }
3852 }
3853 
ParseLocalizedMarginOrLocalizedPaddingCorner(const JSRef<JSObject> & object,LocalizedCalcDimension & localizedCalcDimension)3854 void JSViewAbstract::ParseLocalizedMarginOrLocalizedPaddingCorner(
3855     const JSRef<JSObject>& object, LocalizedCalcDimension& localizedCalcDimension)
3856 {
3857     auto jsStart = object->GetProperty(static_cast<int32_t>(ArkUIIndex::START));
3858     if (jsStart->IsObject()) {
3859         JSRef<JSObject> startObj = JSRef<JSObject>::Cast(jsStart);
3860         CalcDimension calcDimension;
3861         if (ParseJsLengthMetrics(startObj, calcDimension)) {
3862             localizedCalcDimension.start = calcDimension;
3863         }
3864     }
3865     auto jsEnd = object->GetProperty(static_cast<int32_t>(ArkUIIndex::END));
3866     if (jsEnd->IsObject()) {
3867         JSRef<JSObject> endObj = JSRef<JSObject>::Cast(jsEnd);
3868         CalcDimension calcDimension;
3869         if (ParseJsLengthMetrics(endObj, calcDimension)) {
3870             localizedCalcDimension.end = calcDimension;
3871         }
3872     }
3873     auto jsTop = object->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP));
3874     if (jsTop->IsObject()) {
3875         JSRef<JSObject> topObj = JSRef<JSObject>::Cast(jsTop);
3876         CalcDimension calcDimension;
3877         if (ParseJsLengthMetrics(topObj, calcDimension)) {
3878             localizedCalcDimension.top = calcDimension;
3879         }
3880     }
3881     auto jsBottom = object->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM));
3882     if (jsBottom->IsObject()) {
3883         JSRef<JSObject> bottomObj = JSRef<JSObject>::Cast(jsBottom);
3884         CalcDimension calcDimension;
3885         if (ParseJsLengthMetrics(bottomObj, calcDimension)) {
3886             localizedCalcDimension.bottom = calcDimension;
3887         }
3888     }
3889 }
3890 
ParseCommonMarginOrPaddingCorner(const JSRef<JSObject> & object,CommonCalcDimension & commonCalcDimension)3891 bool JSViewAbstract::ParseCommonMarginOrPaddingCorner(
3892     const JSRef<JSObject>& object, CommonCalcDimension& commonCalcDimension)
3893 {
3894     if (CheckLengthMetrics(object)) {
3895         LocalizedCalcDimension localizedCalcDimension;
3896         ParseLocalizedMarginOrLocalizedPaddingCorner(object, localizedCalcDimension);
3897         auto isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
3898         commonCalcDimension.top = localizedCalcDimension.top;
3899         commonCalcDimension.bottom = localizedCalcDimension.bottom;
3900         commonCalcDimension.left = isRightToLeft ? localizedCalcDimension.end : localizedCalcDimension.start;
3901         commonCalcDimension.right = isRightToLeft ? localizedCalcDimension.start : localizedCalcDimension.end;
3902         return true;
3903     }
3904     ParseMarginOrPaddingCorner(object, commonCalcDimension.top, commonCalcDimension.bottom, commonCalcDimension.left,
3905         commonCalcDimension.right);
3906     return false;
3907 }
3908 
JsOutline(const JSCallbackInfo & info)3909 void JSViewAbstract::JsOutline(const JSCallbackInfo& info)
3910 {
3911     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
3912     auto jsVal = info[0];
3913     if (!CheckJSCallbackInfo("JsOutline", jsVal, checkList)) {
3914         CalcDimension borderWidth;
3915         ViewAbstractModel::GetInstance()->SetOuterBorderWidth(borderWidth);
3916         ViewAbstractModel::GetInstance()->SetOuterBorderColor(Color::BLACK);
3917         ViewAbstractModel::GetInstance()->SetOuterBorderRadius(borderWidth);
3918         ViewAbstractModel::GetInstance()->SetOuterBorderStyle(BorderStyle::SOLID);
3919         return;
3920     }
3921     JSRef<JSObject> object = JSRef<JSObject>::Cast(jsVal);
3922     auto valueOuterWidth = object->GetProperty("width");
3923     if (!valueOuterWidth->IsUndefined()) {
3924         ParseOuterBorderWidth(valueOuterWidth);
3925     } else if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
3926         ViewAbstractModel::GetInstance()->SetOuterBorderWidth({});
3927     }
3928 
3929     // use default value when undefined.
3930     ParseOuterBorderColor(object->GetProperty("color"));
3931 
3932     auto valueOuterRadius = object->GetProperty("radius");
3933     if (!valueOuterRadius->IsUndefined()) {
3934         ParseOuterBorderRadius(valueOuterRadius);
3935     } else if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
3936         ViewAbstractModel::GetInstance()->SetOuterBorderRadius(Dimension {});
3937     }
3938     // use default value when undefined.
3939     ParseOuterBorderStyle(object->GetProperty("style"));
3940     info.ReturnSelf();
3941 }
3942 
JsOutlineWidth(const JSCallbackInfo & info)3943 void JSViewAbstract::JsOutlineWidth(const JSCallbackInfo& info)
3944 {
3945     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
3946         JSCallbackInfoType::OBJECT };
3947     auto jsVal = info[0];
3948     if (!CheckJSCallbackInfo("JsOutlineWidth", jsVal, checkList)) {
3949         ViewAbstractModel::GetInstance()->SetOuterBorderWidth({});
3950         return;
3951     }
3952     ParseOuterBorderWidth(jsVal);
3953 }
3954 
JsOutlineColor(const JSCallbackInfo & info)3955 void JSViewAbstract::JsOutlineColor(const JSCallbackInfo& info)
3956 {
3957     ParseOuterBorderColor(info[0]);
3958 }
3959 
JsOutlineRadius(const JSCallbackInfo & info)3960 void JSViewAbstract::JsOutlineRadius(const JSCallbackInfo& info)
3961 {
3962     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
3963         JSCallbackInfoType::OBJECT };
3964     auto jsVal = info[0];
3965     if (!CheckJSCallbackInfo("JsOutlineRadius", jsVal, checkList)) {
3966         ViewAbstractModel::GetInstance()->SetOuterBorderRadius(Dimension {});
3967         return;
3968     }
3969     ParseOuterBorderRadius(jsVal);
3970 }
3971 
JsOutlineStyle(const JSCallbackInfo & info)3972 void JSViewAbstract::JsOutlineStyle(const JSCallbackInfo& info)
3973 {
3974     ParseOuterBorderStyle(info[0]);
3975 }
3976 
JsBorder(const JSCallbackInfo & info)3977 void JSViewAbstract::JsBorder(const JSCallbackInfo& info)
3978 {
3979     if (!info[0]->IsObject()) {
3980         CalcDimension borderWidth;
3981         ViewAbstractModel::GetInstance()->SetBorderWidth(borderWidth);
3982         ViewAbstractModel::GetInstance()->SetBorderColor(Color::BLACK);
3983         ViewAbstractModel::GetInstance()->SetBorderRadius(borderWidth);
3984         ViewAbstractModel::GetInstance()->SetBorderStyle(BorderStyle::SOLID);
3985         ViewAbstractModel::GetInstance()->SetDashGap(Dimension(-1));
3986         ViewAbstractModel::GetInstance()->SetDashWidth(Dimension(-1));
3987         return;
3988     }
3989     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
3990 
3991     auto valueWidth = object->GetProperty(static_cast<int32_t>(ArkUIIndex::WIDTH));
3992     if (!valueWidth->IsUndefined()) {
3993         ParseBorderWidth(valueWidth);
3994     }
3995 
3996     // use default value when undefined.
3997     ParseBorderColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR)));
3998 
3999     auto valueRadius = object->GetProperty(static_cast<int32_t>(ArkUIIndex::RADIUS));
4000     if (!valueRadius->IsUndefined()) {
4001         ParseBorderRadius(valueRadius);
4002     }
4003     // use default value when undefined.
4004     ParseBorderStyle(object->GetProperty(static_cast<int32_t>(ArkUIIndex::STYLE)));
4005 
4006     auto dashGap = object->GetProperty("dashGap");
4007     if (!dashGap->IsUndefined()) {
4008         ParseDashGap(dashGap);
4009     }
4010     auto dashWidth = object->GetProperty("dashWidth");
4011     if (!dashWidth->IsUndefined()) {
4012         ParseDashWidth(dashWidth);
4013     }
4014 
4015     info.ReturnSelf();
4016 }
4017 
IsBorderWidthObjUndefined(const JSRef<JSVal> & args)4018 bool IsBorderWidthObjUndefined(const JSRef<JSVal>& args)
4019 {
4020     if (!args->IsObject()) {
4021         return false;
4022     }
4023     JSRef<JSObject> obj = JSRef<JSObject>::Cast(args);
4024     if (obj->IsUndefined()) {
4025         return true;
4026     }
4027     // filter dynamic $r raw input
4028     if (obj->HasProperty("id")) {
4029         return false;
4030     }
4031     if ((!obj->HasProperty(TOP_PROPERTY) || obj->GetProperty(TOP_PROPERTY)->IsUndefined()) &&
4032         (!obj->HasProperty(RIGHT_PROPERTY) || obj->GetProperty(RIGHT_PROPERTY)->IsUndefined()) &&
4033         (!obj->HasProperty(BOTTOM_PROPERTY) || obj->GetProperty(BOTTOM_PROPERTY)->IsUndefined()) &&
4034         (!obj->HasProperty(LEFT_PROPERTY) || obj->GetProperty(LEFT_PROPERTY)->IsUndefined()) &&
4035         (!obj->HasProperty(START_PROPERTY) || obj->GetProperty(START_PROPERTY)->IsUndefined()) &&
4036         (!obj->HasProperty(END_PROPERTY) || obj->GetProperty(END_PROPERTY)->IsUndefined())) {
4037         return true;
4038     }
4039 
4040     return false;
4041 }
4042 
JsBorderWidth(const JSCallbackInfo & info)4043 void JSViewAbstract::JsBorderWidth(const JSCallbackInfo& info)
4044 {
4045     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
4046         JSCallbackInfoType::OBJECT };
4047     auto jsVal = info[0];
4048     if (!CheckJSCallbackInfo("JsBorderWidth", jsVal, checkList)) {
4049         ViewAbstractModel::GetInstance()->SetBorderWidth({});
4050         return;
4051     }
4052     ParseBorderWidth(jsVal);
4053 }
4054 
ParseBorderWidth(const JSRef<JSVal> & args)4055 void JSViewAbstract::ParseBorderWidth(const JSRef<JSVal>& args)
4056 {
4057     CalcDimension borderWidth;
4058     if (ParseJsDimensionVp(args, borderWidth)) {
4059         if (borderWidth.IsNegative()) {
4060             borderWidth.Reset();
4061         }
4062         if (borderWidth.Unit() == DimensionUnit::PERCENT) {
4063             borderWidth.Reset();
4064         }
4065         ViewAbstractModel::GetInstance()->SetBorderWidth(borderWidth);
4066     } else if (args->IsObject()) {
4067         if (IsBorderWidthObjUndefined(args)) {
4068             ViewAbstractModel::GetInstance()->SetBorderWidth({});
4069             return;
4070         }
4071         CommonCalcDimension commonCalcDimension;
4072         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args);
4073         if (ParseCommonEdgeWidths(obj, commonCalcDimension, true)) {
4074             ViewAbstractModel::GetInstance()->SetBorderWidth(commonCalcDimension.left, commonCalcDimension.right,
4075                 commonCalcDimension.top, commonCalcDimension.bottom, true);
4076             return;
4077         }
4078         ViewAbstractModel::GetInstance()->SetBorderWidth(
4079             commonCalcDimension.left, commonCalcDimension.right, commonCalcDimension.top, commonCalcDimension.bottom);
4080     } else {
4081         return;
4082     }
4083 }
4084 
ParseDashGap(const JSRef<JSVal> & args)4085 void JSViewAbstract::ParseDashGap(const JSRef<JSVal>& args)
4086 {
4087     CalcDimension dashGap;
4088     if (ParseLengthMetricsToDimension(args, dashGap)) {
4089         if (dashGap.Unit() == DimensionUnit::PERCENT) {
4090             dashGap.Reset();
4091         }
4092         ViewAbstractModel::GetInstance()->SetDashGap(dashGap);
4093     } else if (args->IsObject()) {
4094         CommonCalcDimension commonCalcDimension;
4095         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args);
4096         ParseCommonEdgeWidthsForDashParams(obj, commonCalcDimension);
4097         ViewAbstractModel::GetInstance()->SetDashGap(
4098             commonCalcDimension.left, commonCalcDimension.right, commonCalcDimension.top, commonCalcDimension.bottom);
4099     } else {
4100         dashGap.Reset();
4101         ViewAbstractModel::GetInstance()->SetDashGap(dashGap);
4102     }
4103 }
4104 
ParseDashWidth(const JSRef<JSVal> & args)4105 void JSViewAbstract::ParseDashWidth(const JSRef<JSVal>& args)
4106 {
4107     CalcDimension dashWidth;
4108     if (ParseLengthMetricsToDimension(args, dashWidth)) {
4109         if (dashWidth.Unit() == DimensionUnit::PERCENT) {
4110             dashWidth.Reset();
4111         }
4112         ViewAbstractModel::GetInstance()->SetDashWidth(dashWidth);
4113     } else if (args->IsObject()) {
4114         CommonCalcDimension commonCalcDimension;
4115         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args);
4116         ParseCommonEdgeWidthsForDashParams(obj, commonCalcDimension);
4117         ViewAbstractModel::GetInstance()->SetDashWidth(
4118             commonCalcDimension.left, commonCalcDimension.right, commonCalcDimension.top, commonCalcDimension.bottom);
4119     } else {
4120         dashWidth.Reset();
4121         ViewAbstractModel::GetInstance()->SetDashWidth(dashWidth);
4122     }
4123 }
4124 
ParseOuterBorderWidth(const JSRef<JSVal> & args)4125 void JSViewAbstract::ParseOuterBorderWidth(const JSRef<JSVal>& args)
4126 {
4127     CalcDimension borderWidth;
4128     if (ParseJsDimensionVp(args, borderWidth)) {
4129         if (borderWidth.IsNegative() || borderWidth.Unit() == DimensionUnit::PERCENT) {
4130             borderWidth.Reset();
4131         }
4132         ViewAbstractModel::GetInstance()->SetOuterBorderWidth(borderWidth);
4133     } else if (args->IsObject()) {
4134         std::optional<CalcDimension> leftDimen;
4135         std::optional<CalcDimension> rightDimen;
4136         std::optional<CalcDimension> topDimen;
4137         std::optional<CalcDimension> bottomDimen;
4138         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
4139         CalcDimension left;
4140         if (ParseJsDimensionVp(object->GetProperty("left"), left) && left.IsNonNegative()) {
4141             if (left.Unit() == DimensionUnit::PERCENT) {
4142                 left.Reset();
4143             }
4144             leftDimen = left;
4145         }
4146         CalcDimension right;
4147         if (ParseJsDimensionVp(object->GetProperty("right"), right) && right.IsNonNegative()) {
4148             if (right.Unit() == DimensionUnit::PERCENT) {
4149                 right.Reset();
4150             }
4151             rightDimen = right;
4152         }
4153         CalcDimension top;
4154         if (ParseJsDimensionVp(object->GetProperty("top"), top) && top.IsNonNegative()) {
4155             if (top.Unit() == DimensionUnit::PERCENT) {
4156                 top.Reset();
4157             }
4158             topDimen = top;
4159         }
4160         CalcDimension bottom;
4161         if (ParseJsDimensionVp(object->GetProperty("bottom"), bottom) && bottom.IsNonNegative()) {
4162             if (bottom.Unit() == DimensionUnit::PERCENT) {
4163                 bottom.Reset();
4164             }
4165             bottomDimen = bottom;
4166         }
4167         ViewAbstractModel::GetInstance()->SetOuterBorderWidth(leftDimen, rightDimen, topDimen, bottomDimen);
4168     } else {
4169         return;
4170     }
4171 }
4172 
JsBorderImage(const JSCallbackInfo & info)4173 void JSViewAbstract::JsBorderImage(const JSCallbackInfo& info)
4174 {
4175     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
4176     auto jsVal = info[0];
4177     if (!CheckJSCallbackInfo("JsBorderImage", jsVal, checkList)) {
4178         RefPtr<BorderImage> borderImage = AceType::MakeRefPtr<BorderImage>();
4179         uint8_t imageBorderBitsets = 0;
4180         ViewAbstractModel::GetInstance()->SetBorderImage(borderImage, imageBorderBitsets);
4181         return;
4182     }
4183     JSRef<JSObject> object = JSRef<JSObject>::Cast(jsVal);
4184     CHECK_NULL_VOID(!object->IsEmpty());
4185 
4186     RefPtr<BorderImage> borderImage = AceType::MakeRefPtr<BorderImage>();
4187     uint8_t imageBorderBitsets = 0;
4188 
4189     auto valueSource = object->GetProperty(static_cast<int32_t>(ArkUIIndex::SOURCE));
4190     CHECK_NULL_VOID((valueSource->IsString() || valueSource->IsObject()));
4191     std::string srcResult;
4192     std::string bundleName;
4193     std::string moduleName;
4194     GetJsMediaBundleInfo(valueSource, bundleName, moduleName);
4195     borderImage->SetBundleName(bundleName);
4196     borderImage->SetModuleName(moduleName);
4197     if (valueSource->IsString() && !valueSource->ToString().empty()) {
4198         borderImage->SetSrc(valueSource->ToString());
4199         imageBorderBitsets |= BorderImage::SOURCE_BIT;
4200     } else if (valueSource->IsObject() && ParseJsMedia(valueSource, srcResult)) {
4201         borderImage->SetSrc(srcResult);
4202         imageBorderBitsets |= BorderImage::SOURCE_BIT;
4203     } else if (valueSource->IsObject()) {
4204         ParseBorderImageLinearGradient(valueSource, imageBorderBitsets);
4205     }
4206     auto valueOutset = object->GetProperty("outset");
4207     if (valueOutset->IsNumber() || valueOutset->IsString() || valueOutset->IsObject()) {
4208         imageBorderBitsets |= BorderImage::OUTSET_BIT;
4209         ParseBorderImageOutset(valueOutset, borderImage);
4210     }
4211     auto valueRepeat = object->GetProperty(static_cast<int32_t>(ArkUIIndex::REPEAT));
4212     if (!valueRepeat->IsNull()) {
4213         imageBorderBitsets |= BorderImage::REPEAT_BIT;
4214         ParseBorderImageRepeat(valueRepeat, borderImage);
4215     }
4216     auto valueSlice = object->GetProperty(static_cast<int32_t>(ArkUIIndex::SLICE));
4217     if (valueSlice->IsNumber() || valueSlice->IsString() || valueSlice->IsObject()) {
4218         imageBorderBitsets |= BorderImage::SLICE_BIT;
4219         ParseBorderImageSlice(valueSlice, borderImage);
4220     }
4221     auto valueWidth = object->GetProperty(static_cast<int32_t>(ArkUIIndex::WIDTH));
4222     if (valueWidth->IsNumber() || valueWidth->IsString() || valueWidth->IsObject()) {
4223         imageBorderBitsets |= BorderImage::WIDTH_BIT;
4224         ParseBorderImageWidth(valueWidth, borderImage);
4225     }
4226     auto needFill = object->GetProperty(static_cast<int32_t>(ArkUIIndex::FILL));
4227     if (needFill->IsBoolean()) {
4228         borderImage->SetNeedFillCenter(needFill->ToBoolean());
4229     }
4230     ViewAbstractModel::GetInstance()->SetBorderImage(borderImage, imageBorderBitsets);
4231     info.ReturnSelf();
4232 }
4233 
ParseBorderImageDimension(const JSRef<JSVal> & args,BorderImage::BorderImageOption & borderImageDimension)4234 bool JSViewAbstract::ParseBorderImageDimension(
4235     const JSRef<JSVal>& args, BorderImage::BorderImageOption& borderImageDimension)
4236 {
4237     if (!args->IsObject()) {
4238         return false;
4239     }
4240     JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
4241     if (CheckLengthMetrics(object)) {
4242         LocalizedCalcDimension localizedCalcDimension;
4243         ParseBorderImageLengthMetrics(object, localizedCalcDimension);
4244         borderImageDimension.topDimension = localizedCalcDimension.top;
4245         borderImageDimension.bottomDimension = localizedCalcDimension.bottom;
4246         borderImageDimension.startDimension = localizedCalcDimension.start;
4247         borderImageDimension.endDimension = localizedCalcDimension.end;
4248         return true;
4249     }
4250     static std::array<int32_t, DIRECTION_COUNT> keys = { static_cast<int32_t>(ArkUIIndex::LEFT),
4251         static_cast<int32_t>(ArkUIIndex::RIGHT), static_cast<int32_t>(ArkUIIndex::TOP),
4252         static_cast<int32_t>(ArkUIIndex::BOTTOM) };
4253     for (uint32_t i = 0; i < keys.size(); i++) {
4254         CalcDimension currentDimension;
4255         auto dimensionValue = object->GetProperty(keys.at(i));
4256         if (ParseJsDimensionVp(dimensionValue, currentDimension)) {
4257             auto direction = static_cast<BorderImageDirection>(i);
4258             switch (direction) {
4259                 case BorderImageDirection::LEFT:
4260                     borderImageDimension.leftDimension = currentDimension;
4261                     break;
4262                 case BorderImageDirection::RIGHT:
4263                     borderImageDimension.rightDimension = currentDimension;
4264                     break;
4265                 case BorderImageDirection::TOP:
4266                     borderImageDimension.topDimension = currentDimension;
4267                     break;
4268                 case BorderImageDirection::BOTTOM:
4269                     borderImageDimension.bottomDimension = currentDimension;
4270                     break;
4271                 default:
4272                     break;
4273             }
4274         }
4275     }
4276     return false;
4277 }
4278 
ParseBorderImageLengthMetrics(const JSRef<JSObject> & object,LocalizedCalcDimension & localizedCalcDimension)4279 void JSViewAbstract::ParseBorderImageLengthMetrics(
4280     const JSRef<JSObject>& object, LocalizedCalcDimension& localizedCalcDimension)
4281 {
4282     for (uint32_t i = 0; i < LENGTH_METRICS_KEYS.size(); i++) {
4283         auto jsVal = object->GetProperty(LENGTH_METRICS_KEYS.at(i));
4284         if (!jsVal->IsObject()) {
4285             continue;
4286         }
4287         JSRef<JSObject> lengthMetricsObj = JSRef<JSObject>::Cast(jsVal);
4288         CalcDimension calcDimension;
4289         if (ParseJsLengthMetrics(lengthMetricsObj, calcDimension)) {
4290             auto direction = static_cast<BorderImageDirection>(i);
4291             switch (direction) {
4292                 case BorderImageDirection::LEFT:
4293                     localizedCalcDimension.start = calcDimension;
4294                     break;
4295                 case BorderImageDirection::RIGHT:
4296                     localizedCalcDimension.end = calcDimension;
4297                     break;
4298                 case BorderImageDirection::TOP:
4299                     localizedCalcDimension.top = calcDimension;
4300                     break;
4301                 case BorderImageDirection::BOTTOM:
4302                     localizedCalcDimension.bottom = calcDimension;
4303                     break;
4304                 default:
4305                     break;
4306             }
4307         }
4308     }
4309 }
4310 
CheckJSCallbackInfo(const std::string & callerName,const JSRef<JSVal> & tmpInfo,std::vector<JSCallbackInfoType> & infoTypes)4311 bool JSViewAbstract::CheckJSCallbackInfo(
4312     const std::string& callerName, const JSRef<JSVal>& tmpInfo, std::vector<JSCallbackInfoType>& infoTypes)
4313 {
4314     bool typeVerified = false;
4315     std::string unrecognizedType;
4316     for (const auto& infoType : infoTypes) {
4317         switch (infoType) {
4318             case JSCallbackInfoType::STRING:
4319                 if (tmpInfo->IsString()) {
4320                     typeVerified = true;
4321                 } else {
4322                     unrecognizedType += "string|";
4323                 }
4324                 break;
4325             case JSCallbackInfoType::NUMBER:
4326                 if (tmpInfo->IsNumber()) {
4327                     typeVerified = true;
4328                 } else {
4329                     unrecognizedType += "number|";
4330                 }
4331                 break;
4332             case JSCallbackInfoType::OBJECT:
4333                 if (tmpInfo->IsObject()) {
4334                     typeVerified = true;
4335                 } else {
4336                     unrecognizedType += "object|";
4337                 }
4338                 break;
4339             case JSCallbackInfoType::FUNCTION:
4340                 if (tmpInfo->IsFunction()) {
4341                     typeVerified = true;
4342                 } else {
4343                     unrecognizedType += "Function|";
4344                 }
4345                 break;
4346             default:
4347                 break;
4348         }
4349     }
4350     if (!typeVerified) {
4351         LOGD("%{public}s: info[0] is not a [%{public}s]", callerName.c_str(),
4352             unrecognizedType.substr(0, unrecognizedType.size() - 1).c_str());
4353     }
4354     return typeVerified || infoTypes.size() == 0;
4355 }
4356 
UpdateGradientWithDirection(NG::Gradient & lineGradient,NG::GradientDirection direction)4357 void JSViewAbstract::UpdateGradientWithDirection(NG::Gradient& lineGradient, NG::GradientDirection direction)
4358 {
4359     switch (direction) {
4360         case NG::GradientDirection::LEFT:
4361             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
4362             break;
4363         case NG::GradientDirection::RIGHT:
4364             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
4365             break;
4366         case NG::GradientDirection::TOP:
4367             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
4368             break;
4369         case NG::GradientDirection::BOTTOM:
4370             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
4371             break;
4372         case NG::GradientDirection::LEFT_TOP:
4373             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
4374             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
4375             break;
4376         case NG::GradientDirection::LEFT_BOTTOM:
4377             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
4378             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
4379             break;
4380         case NG::GradientDirection::RIGHT_TOP:
4381             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
4382             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
4383             break;
4384         case NG::GradientDirection::RIGHT_BOTTOM:
4385             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
4386             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
4387             break;
4388         case NG::GradientDirection::NONE:
4389         case NG::GradientDirection::START_TO_END:
4390         case NG::GradientDirection::END_TO_START:
4391         default:
4392             break;
4393     }
4394 }
4395 
ParseBorderImageLinearGradient(const JSRef<JSVal> & args,uint8_t & bitset)4396 void JSViewAbstract::ParseBorderImageLinearGradient(const JSRef<JSVal>& args, uint8_t& bitset)
4397 {
4398     if (!args->IsObject()) {
4399         return;
4400     }
4401     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(args);
4402     NG::Gradient lineGradient;
4403     lineGradient.CreateGradientWithType(NG::GradientType::LINEAR);
4404     // angle
4405     std::optional<float> degree;
4406     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
4407         GetJsAngle(static_cast<int32_t>(ArkUIIndex::ANGLE), jsObj, degree);
4408     } else {
4409         GetJsAngleWithDefault(static_cast<int32_t>(ArkUIIndex::ANGLE), jsObj, degree, 180.0f);
4410     }
4411     if (degree) {
4412         lineGradient.GetLinearGradient()->angle = CalcDimension(degree.value(), DimensionUnit::PX);
4413         degree.reset();
4414     }
4415     // direction
4416     auto direction = static_cast<NG::GradientDirection>(
4417         jsObj->GetPropertyValue<int32_t>(static_cast<int32_t>(ArkUIIndex::DIRECTION),
4418         static_cast<int32_t>(NG::GradientDirection::NONE)));
4419     UpdateGradientWithDirection(lineGradient, direction);
4420     auto repeating = jsObj->GetPropertyValue<bool>(static_cast<int32_t>(ArkUIIndex::REPEATING), false);
4421     lineGradient.SetRepeat(repeating);
4422     NewGetJsGradientColorStops(lineGradient, jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::COLORS)));
4423     ViewAbstractModel::GetInstance()->SetBorderImageGradient(lineGradient);
4424     bitset |= BorderImage::GRADIENT_BIT;
4425 }
4426 
ParseBorderImageRepeat(const JSRef<JSVal> & args,RefPtr<BorderImage> & borderImage)4427 void JSViewAbstract::ParseBorderImageRepeat(const JSRef<JSVal>& args, RefPtr<BorderImage>& borderImage)
4428 {
4429     auto repeatString = args->ToString();
4430     if (repeatString == "Repeat") {
4431         borderImage->SetRepeatMode(BorderImageRepeat::REPEAT);
4432     } else if (repeatString == "Round") {
4433         borderImage->SetRepeatMode(BorderImageRepeat::ROUND);
4434     } else if (repeatString == "Space") {
4435         borderImage->SetRepeatMode(BorderImageRepeat::SPACE);
4436     } else {
4437         borderImage->SetRepeatMode(BorderImageRepeat::STRETCH);
4438     }
4439 }
4440 
ParseBorderImageOutset(const JSRef<JSVal> & args,RefPtr<BorderImage> & borderImage)4441 void JSViewAbstract::ParseBorderImageOutset(const JSRef<JSVal>& args, RefPtr<BorderImage>& borderImage)
4442 {
4443     CalcDimension outsetDimension;
4444     if (ParseJsDimensionVp(args, outsetDimension)) {
4445         borderImage->SetEdgeOutset(BorderImageDirection::LEFT, outsetDimension);
4446         borderImage->SetEdgeOutset(BorderImageDirection::RIGHT, outsetDimension);
4447         borderImage->SetEdgeOutset(BorderImageDirection::TOP, outsetDimension);
4448         borderImage->SetEdgeOutset(BorderImageDirection::BOTTOM, outsetDimension);
4449         return;
4450     }
4451     BorderImage::BorderImageOption option;
4452     ParseBorderImageDimension(args, option);
4453     if (option.startDimension.has_value()) {
4454         borderImage->SetEdgeOutset(BorderImageDirection::START, option.startDimension.value());
4455     }
4456     if (option.endDimension.has_value()) {
4457         borderImage->SetEdgeOutset(BorderImageDirection::END, option.endDimension.value());
4458     }
4459     if (option.leftDimension.has_value()) {
4460         borderImage->SetEdgeOutset(BorderImageDirection::LEFT, option.leftDimension.value());
4461     }
4462     if (option.rightDimension.has_value()) {
4463         borderImage->SetEdgeOutset(BorderImageDirection::RIGHT, option.rightDimension.value());
4464     }
4465     if (option.topDimension.has_value()) {
4466         borderImage->SetEdgeOutset(BorderImageDirection::TOP, option.topDimension.value());
4467     }
4468     if (option.bottomDimension.has_value()) {
4469         borderImage->SetEdgeOutset(BorderImageDirection::BOTTOM, option.bottomDimension.value());
4470     }
4471 }
4472 
ParseBorderImageSlice(const JSRef<JSVal> & args,RefPtr<BorderImage> & borderImage)4473 void JSViewAbstract::ParseBorderImageSlice(const JSRef<JSVal>& args, RefPtr<BorderImage>& borderImage)
4474 {
4475     CalcDimension sliceDimension;
4476     if (ParseJsDimensionVp(args, sliceDimension)) {
4477         borderImage->SetEdgeSlice(BorderImageDirection::LEFT, sliceDimension);
4478         borderImage->SetEdgeSlice(BorderImageDirection::RIGHT, sliceDimension);
4479         borderImage->SetEdgeSlice(BorderImageDirection::TOP, sliceDimension);
4480         borderImage->SetEdgeSlice(BorderImageDirection::BOTTOM, sliceDimension);
4481         return;
4482     }
4483     if (!args->IsObject()) {
4484         return;
4485     }
4486     JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
4487     if (CheckLengthMetrics(object)) {
4488         LocalizedCalcDimension localizedCalcDimension;
4489         ParseBorderImageLengthMetrics(object, localizedCalcDimension);
4490         if (localizedCalcDimension.top.has_value()) {
4491             borderImage->SetEdgeSlice(BorderImageDirection::TOP, localizedCalcDimension.top.value());
4492         }
4493         if (localizedCalcDimension.bottom.has_value()) {
4494             borderImage->SetEdgeSlice(BorderImageDirection::BOTTOM, localizedCalcDimension.bottom.value());
4495         }
4496         if (localizedCalcDimension.start.has_value()) {
4497             borderImage->SetEdgeSlice(BorderImageDirection::START, localizedCalcDimension.start.value());
4498         }
4499         if (localizedCalcDimension.end.has_value()) {
4500             borderImage->SetEdgeSlice(BorderImageDirection::END, localizedCalcDimension.end.value());
4501         }
4502         return;
4503     }
4504     static std::array<int32_t, DIRECTION_COUNT> keys = { static_cast<int32_t>(ArkUIIndex::LEFT),
4505         static_cast<int32_t>(ArkUIIndex::RIGHT), static_cast<int32_t>(ArkUIIndex::TOP),
4506         static_cast<int32_t>(ArkUIIndex::BOTTOM) };
4507     for (uint32_t i = 0; i < keys.size(); i++) {
4508         auto dimensionValue = object->GetProperty(keys.at(i));
4509         if (ParseJsDimensionVp(dimensionValue, sliceDimension)) {
4510             borderImage->SetEdgeSlice(static_cast<BorderImageDirection>(i), sliceDimension);
4511         }
4512     }
4513 }
4514 
ParseBorderImageWidth(const JSRef<JSVal> & args,RefPtr<BorderImage> & borderImage)4515 void JSViewAbstract::ParseBorderImageWidth(const JSRef<JSVal>& args, RefPtr<BorderImage>& borderImage)
4516 {
4517     CalcDimension widthDimension;
4518     if (ParseJsDimensionVp(args, widthDimension)) {
4519         borderImage->SetEdgeWidth(BorderImageDirection::LEFT, widthDimension);
4520         borderImage->SetEdgeWidth(BorderImageDirection::RIGHT, widthDimension);
4521         borderImage->SetEdgeWidth(BorderImageDirection::TOP, widthDimension);
4522         borderImage->SetEdgeWidth(BorderImageDirection::BOTTOM, widthDimension);
4523         return;
4524     }
4525 
4526     BorderImage::BorderImageOption option;
4527     ParseBorderImageDimension(args, option);
4528     if (option.startDimension.has_value()) {
4529         borderImage->SetEdgeWidth(BorderImageDirection::START, option.startDimension.value());
4530     }
4531     if (option.endDimension.has_value()) {
4532         borderImage->SetEdgeWidth(BorderImageDirection::END, option.endDimension.value());
4533     }
4534     if (option.leftDimension.has_value()) {
4535         borderImage->SetEdgeWidth(BorderImageDirection::LEFT, option.leftDimension.value());
4536     }
4537     if (option.rightDimension.has_value()) {
4538         borderImage->SetEdgeWidth(BorderImageDirection::RIGHT, option.rightDimension.value());
4539     }
4540     if (option.topDimension.has_value()) {
4541         borderImage->SetEdgeWidth(BorderImageDirection::TOP, option.topDimension.value());
4542     }
4543     if (option.bottomDimension.has_value()) {
4544         borderImage->SetEdgeWidth(BorderImageDirection::BOTTOM, option.bottomDimension.value());
4545     }
4546 }
4547 
JsBorderColor(const JSCallbackInfo & info)4548 void JSViewAbstract::JsBorderColor(const JSCallbackInfo& info)
4549 {
4550     ParseBorderColor(info[0]);
4551 }
4552 
GetLocalizedBorderColor(const std::optional<Color> & colorStart,const std::optional<Color> & colorEnd,const std::optional<Color> & colorTop,const std::optional<Color> & colorBottom)4553 NG::BorderColorProperty JSViewAbstract::GetLocalizedBorderColor(const std::optional<Color>& colorStart,
4554     const std::optional<Color>& colorEnd, const std::optional<Color>& colorTop,
4555     const std::optional<Color>& colorBottom)
4556 {
4557     NG::BorderColorProperty borderColors;
4558     borderColors.startColor = colorStart;
4559     borderColors.endColor = colorEnd;
4560     borderColors.topColor = colorTop;
4561     borderColors.bottomColor = colorBottom;
4562     borderColors.multiValued = true;
4563     return borderColors;
4564 }
4565 
ParseBorderColor(const JSRef<JSVal> & args)4566 void JSViewAbstract::ParseBorderColor(const JSRef<JSVal>& args)
4567 {
4568     Color borderColor;
4569     if (ParseJsColor(args, borderColor)) {
4570         ViewAbstractModel::GetInstance()->SetBorderColor(borderColor);
4571     } else if (args->IsObject()) {
4572         CommonColor commonColor;
4573         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
4574         if (ParseCommonEdgeColors(object, commonColor)) {
4575             ViewAbstractModel::GetInstance()->SetBorderColor(
4576                 GetLocalizedBorderColor(commonColor.left, commonColor.right, commonColor.top, commonColor.bottom));
4577             return;
4578         }
4579         ViewAbstractModel::GetInstance()->SetBorderColor(
4580             commonColor.left, commonColor.right, commonColor.top, commonColor.bottom);
4581     } else {
4582         ViewAbstractModel::GetInstance()->SetBorderColor(Color::BLACK);
4583     }
4584 }
4585 
ParseOuterBorderColor(const JSRef<JSVal> & args)4586 void JSViewAbstract::ParseOuterBorderColor(const JSRef<JSVal>& args)
4587 {
4588     Color borderColor;
4589     if (ParseJsColor(args, borderColor)) {
4590         ViewAbstractModel::GetInstance()->SetOuterBorderColor(borderColor);
4591     } else if (args->IsObject()) {
4592         CommonColor commonColor;
4593         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
4594         if (ParseCommonEdgeColors(object, commonColor)) {
4595             ViewAbstractModel::GetInstance()->SetOuterBorderColor(
4596                 GetLocalizedBorderColor(commonColor.left, commonColor.right, commonColor.top, commonColor.bottom));
4597             return;
4598         }
4599         ViewAbstractModel::GetInstance()->SetOuterBorderColor(
4600             commonColor.left, commonColor.right, commonColor.top, commonColor.bottom);
4601     } else {
4602         ViewAbstractModel::GetInstance()->SetOuterBorderColor(Color::BLACK);
4603     }
4604 }
4605 
JsBorderRadius(const JSCallbackInfo & info)4606 void JSViewAbstract::JsBorderRadius(const JSCallbackInfo& info)
4607 {
4608     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
4609         JSCallbackInfoType::OBJECT };
4610     auto jsVal = info[0];
4611     if (!CheckJSCallbackInfo("JsBorderRadius", jsVal, checkList)) {
4612         ViewAbstractModel::GetInstance()->SetBorderRadius(Dimension {});
4613         return;
4614     }
4615     ParseBorderRadius(jsVal);
4616 }
4617 
GetLocalizedBorderRadius(const std::optional<Dimension> & radiusTopStart,const std::optional<Dimension> & radiusTopEnd,const std::optional<Dimension> & radiusBottomStart,const std::optional<Dimension> & radiusBottomEnd)4618 NG::BorderRadiusProperty JSViewAbstract::GetLocalizedBorderRadius(const std::optional<Dimension>& radiusTopStart,
4619     const std::optional<Dimension>& radiusTopEnd, const std::optional<Dimension>& radiusBottomStart,
4620     const std::optional<Dimension>& radiusBottomEnd)
4621 {
4622     NG::BorderRadiusProperty borderRadius;
4623     borderRadius.radiusTopStart = radiusTopStart;
4624     borderRadius.radiusTopEnd = radiusTopEnd;
4625     borderRadius.radiusBottomStart = radiusBottomStart;
4626     borderRadius.radiusBottomEnd = radiusBottomEnd;
4627     borderRadius.multiValued = true;
4628     return borderRadius;
4629 }
4630 
ParseBorderRadius(const JSRef<JSVal> & args)4631 void JSViewAbstract::ParseBorderRadius(const JSRef<JSVal>& args)
4632 {
4633     CalcDimension borderRadius;
4634     if (ParseJsDimensionVp(args, borderRadius)) {
4635         ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius);
4636     } else if (args->IsObject()) {
4637         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
4638         CalcDimension topLeft;
4639         CalcDimension topRight;
4640         CalcDimension bottomLeft;
4641         CalcDimension bottomRight;
4642         if (ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight)) {
4643             ViewAbstractModel::GetInstance()->SetBorderRadius(
4644                 GetLocalizedBorderRadius(topLeft, topRight, bottomLeft, bottomRight));
4645                 return;
4646         }
4647         ViewAbstractModel::GetInstance()->SetBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
4648     }
4649 }
4650 
ParseOuterBorderRadius(const JSRef<JSVal> & args)4651 void JSViewAbstract::ParseOuterBorderRadius(const JSRef<JSVal>& args)
4652 {
4653     if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
4654         return;
4655     }
4656     CalcDimension borderRadius;
4657     if (ParseJsDimensionVp(args, borderRadius)) {
4658         if (borderRadius.Unit() == DimensionUnit::PERCENT) {
4659             borderRadius.Reset();
4660         }
4661         ViewAbstractModel::GetInstance()->SetOuterBorderRadius(borderRadius);
4662     } else if (args->IsObject()) {
4663         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
4664         CalcDimension topLeft;
4665         CalcDimension topRight;
4666         CalcDimension bottomLeft;
4667         CalcDimension bottomRight;
4668         if (ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight)) {
4669             ViewAbstractModel::GetInstance()->SetOuterBorderRadius(
4670                 GetLocalizedBorderRadius(topLeft, topRight, bottomLeft, bottomRight));
4671         }
4672         ViewAbstractModel::GetInstance()->SetOuterBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
4673     }
4674 }
4675 
GetBorderRadius(const char * key,JSRef<JSObject> & object,CalcDimension & radius)4676 void JSViewAbstract::GetBorderRadius(const char* key, JSRef<JSObject>& object, CalcDimension& radius)
4677 {
4678     ParseJsDimensionVp(object->GetProperty(key), radius);
4679 }
4680 
GetBorderRadiusByLengthMetrics(const char * key,JSRef<JSObject> & object,CalcDimension & radius)4681 void JSViewAbstract::GetBorderRadiusByLengthMetrics(const char* key, JSRef<JSObject>& object, CalcDimension& radius)
4682 {
4683     if (object->HasProperty(key) && object->GetProperty(key)->IsObject()) {
4684         JSRef<JSObject> startObj = JSRef<JSObject>::Cast(object->GetProperty(key));
4685         ParseJsLengthMetrics(startObj, radius);
4686     }
4687 }
4688 
ParseAllBorderRadiuses(JSRef<JSObject> & object,CalcDimension & topLeft,CalcDimension & topRight,CalcDimension & bottomLeft,CalcDimension & bottomRight)4689 bool JSViewAbstract::ParseAllBorderRadiuses(JSRef<JSObject>& object, CalcDimension& topLeft, CalcDimension& topRight,
4690     CalcDimension& bottomLeft, CalcDimension& bottomRight)
4691 {
4692     if (object->HasProperty(TOP_START_PROPERTY) || object->HasProperty(TOP_END_PROPERTY) ||
4693         object->HasProperty(BOTTOM_START_PROPERTY) || object->HasProperty(BOTTOM_END_PROPERTY)) {
4694         CalcDimension topStart;
4695         CalcDimension topEnd;
4696         CalcDimension bottomStart;
4697         CalcDimension bottomEnd;
4698         GetBorderRadiusByLengthMetrics(TOP_START_PROPERTY, object, topStart);
4699         GetBorderRadiusByLengthMetrics(TOP_END_PROPERTY, object, topEnd);
4700         GetBorderRadiusByLengthMetrics(BOTTOM_START_PROPERTY, object, bottomStart);
4701         GetBorderRadiusByLengthMetrics(BOTTOM_END_PROPERTY, object, bottomEnd);
4702         topLeft = topStart;
4703         topRight = topEnd;
4704         bottomLeft = bottomStart;
4705         bottomRight = bottomEnd;
4706         return true;
4707     }
4708     GetBorderRadius("topLeft", object, topLeft);
4709     GetBorderRadius("topRight", object, topRight);
4710     GetBorderRadius("bottomLeft", object, bottomLeft);
4711     GetBorderRadius("bottomRight", object, bottomRight);
4712     return false;
4713 }
4714 
JsBorderStyle(const JSCallbackInfo & info)4715 void JSViewAbstract::JsBorderStyle(const JSCallbackInfo& info)
4716 {
4717     ParseBorderStyle(info[0]);
4718 }
4719 namespace {
ConvertBorderStyle(int32_t value)4720 BorderStyle ConvertBorderStyle(int32_t value)
4721 {
4722     auto style = static_cast<BorderStyle>(value);
4723     if (style < BorderStyle::SOLID || style > BorderStyle::NONE) {
4724         style = BorderStyle::SOLID;
4725     }
4726     return style;
4727 }
4728 
ConvertOptionBorderStyle(int32_t value,std::optional<BorderStyle> & style)4729 bool ConvertOptionBorderStyle(int32_t value, std::optional<BorderStyle>& style)
4730 {
4731     style = static_cast<BorderStyle>(value);
4732     if (style < BorderStyle::SOLID || style > BorderStyle::NONE) {
4733         return false;
4734     }
4735     return true;
4736 }
4737 } // namespace
4738 
ParseBorderStyle(const JSRef<JSVal> & args)4739 void JSViewAbstract::ParseBorderStyle(const JSRef<JSVal>& args)
4740 {
4741     if (args->IsObject()) {
4742         std::optional<BorderStyle> styleLeft;
4743         std::optional<BorderStyle> styleRight;
4744         std::optional<BorderStyle> styleTop;
4745         std::optional<BorderStyle> styleBottom;
4746         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
4747         auto leftValue = object->GetProperty(static_cast<int32_t>(ArkUIIndex::LEFT));
4748         if (leftValue->IsNumber()) {
4749             styleLeft = ConvertBorderStyle(leftValue->ToNumber<int32_t>());
4750         }
4751         auto rightValue = object->GetProperty(static_cast<int32_t>(ArkUIIndex::RIGHT));
4752         if (rightValue->IsNumber()) {
4753             styleRight = ConvertBorderStyle(rightValue->ToNumber<int32_t>());
4754         }
4755         auto topValue = object->GetProperty(static_cast<int32_t>(ArkUIIndex::TOP));
4756         if (topValue->IsNumber()) {
4757             styleTop = ConvertBorderStyle(topValue->ToNumber<int32_t>());
4758         }
4759         auto bottomValue = object->GetProperty(static_cast<int32_t>(ArkUIIndex::BOTTOM));
4760         if (bottomValue->IsNumber()) {
4761             styleBottom = ConvertBorderStyle(bottomValue->ToNumber<int32_t>());
4762         }
4763         ViewAbstractModel::GetInstance()->SetBorderStyle(styleLeft, styleRight, styleTop, styleBottom);
4764         return;
4765     }
4766     if (args->IsNumber()) {
4767         auto borderStyle = ConvertBorderStyle(args->ToNumber<int32_t>());
4768         ViewAbstractModel::GetInstance()->SetBorderStyle(borderStyle);
4769         return;
4770     }
4771     ViewAbstractModel::GetInstance()->SetBorderStyle(BorderStyle::SOLID);
4772 }
4773 
ParseOuterBorderStyle(const JSRef<JSVal> & args)4774 void JSViewAbstract::ParseOuterBorderStyle(const JSRef<JSVal>& args)
4775 {
4776     if (!args->IsObject() && !args->IsNumber()) {
4777         ViewAbstractModel::GetInstance()->SetOuterBorderStyle(BorderStyle::SOLID);
4778         return;
4779     }
4780     if (args->IsObject()) {
4781         std::optional<BorderStyle> styleLeft;
4782         std::optional<BorderStyle> styleRight;
4783         std::optional<BorderStyle> styleTop;
4784         std::optional<BorderStyle> styleBottom;
4785         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
4786         auto leftValue = object->GetProperty("left");
4787         if (!leftValue->IsUndefined() && leftValue->IsNumber()) {
4788             styleLeft = ConvertBorderStyle(leftValue->ToNumber<int32_t>());
4789         }
4790         auto rightValue = object->GetProperty("right");
4791         if (!rightValue->IsUndefined() && rightValue->IsNumber()) {
4792             styleRight = ConvertBorderStyle(rightValue->ToNumber<int32_t>());
4793         }
4794         auto topValue = object->GetProperty("top");
4795         if (!topValue->IsUndefined() && topValue->IsNumber()) {
4796             styleTop = ConvertBorderStyle(topValue->ToNumber<int32_t>());
4797         }
4798         auto bottomValue = object->GetProperty("bottom");
4799         if (!bottomValue->IsUndefined() && bottomValue->IsNumber()) {
4800             styleBottom = ConvertBorderStyle(bottomValue->ToNumber<int32_t>());
4801         }
4802         ViewAbstractModel::GetInstance()->SetOuterBorderStyle(styleLeft, styleRight, styleTop, styleBottom);
4803         return;
4804     }
4805     auto borderStyle = ConvertBorderStyle(args->ToNumber<int32_t>());
4806     ViewAbstractModel::GetInstance()->SetOuterBorderStyle(borderStyle);
4807 }
4808 
JsBlur(const JSCallbackInfo & info)4809 void JSViewAbstract::JsBlur(const JSCallbackInfo& info)
4810 {
4811     if (info.Length() == 0) {
4812         return;
4813     }
4814     double blur = 0.0;
4815     if (!ParseJsDouble(info[0], blur)) {
4816         return;
4817     }
4818 
4819     BlurOption blurOption;
4820     if (info.Length() > 1 && info[1]->IsObject()) {
4821         JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(info[1]);
4822         ParseBlurOption(jsBlurOption, blurOption);
4823     }
4824     CalcDimension dimensionRadius(blur, DimensionUnit::PX);
4825     ViewAbstractModel::GetInstance()->SetFrontBlur(dimensionRadius, blurOption);
4826     info.SetReturnValue(info.This());
4827 }
4828 
JsMotionBlur(const JSCallbackInfo & info)4829 void JSViewAbstract::JsMotionBlur(const JSCallbackInfo& info)
4830 {
4831     if (!info[0]->IsObject()) {
4832         return;
4833     }
4834     MotionBlurOption option;
4835     double x = 0.0;
4836     double y = 0.0;
4837     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
4838     JSRef<JSVal> jsAnchor = jsObj->GetProperty("anchor");
4839     if (!jsAnchor->IsNull() && !jsAnchor->IsUndefined() && jsAnchor->IsObject()) {
4840         JSRef<JSObject> jsAnchorObj = JSRef<JSObject>::Cast(jsAnchor);
4841         ParseJsDouble(jsAnchorObj->GetProperty("x"), x);
4842         ParseJsDouble(jsAnchorObj->GetProperty("y"), y);
4843     }
4844     double radius = 0.0;
4845     if (!ParseJsDouble(jsObj->GetProperty("radius"), radius) || LessNotEqual(radius, 0.0)) {
4846         radius = 0.0;
4847     }
4848     if (LessNotEqual(x, 0.0)) {
4849         x = 0.0;
4850     }
4851     if (LessNotEqual(y, 0.0)) {
4852         y = 0.0;
4853     }
4854     option.radius = radius;
4855     option.anchor.x = std::clamp(x, 0.0, 1.0);
4856     option.anchor.y = std::clamp(y, 0.0, 1.0);
4857     ViewAbstractModel::GetInstance()->SetMotionBlur(option);
4858 }
4859 
JsColorBlend(const JSCallbackInfo & info)4860 void JSViewAbstract::JsColorBlend(const JSCallbackInfo& info)
4861 {
4862     Color colorBlend;
4863     if (info[0]->IsUndefined()) {
4864         colorBlend = Color::TRANSPARENT;
4865         SetColorBlend(colorBlend);
4866         return;
4867     }
4868     if (!ParseJsColor(info[0], colorBlend)) {
4869         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
4870             colorBlend = Color::TRANSPARENT;
4871             SetColorBlend(colorBlend);
4872         }
4873         return;
4874     }
4875     SetColorBlend(colorBlend);
4876     info.SetReturnValue(info.This());
4877 }
4878 
JsUseEffect(const JSCallbackInfo & info)4879 void JSViewAbstract::JsUseEffect(const JSCallbackInfo& info)
4880 {
4881     if (info[0]->IsBoolean()) {
4882         auto effectType = EffectType::DEFAULT;
4883         if (info.Length() == 2 && info[1]->IsNumber()) {
4884             effectType = static_cast<EffectType>(info[1]->ToNumber<int32_t>());
4885             if (effectType < EffectType::DEFAULT || effectType > EffectType::WINDOW_EFFECT) {
4886                 effectType = EffectType::DEFAULT;
4887             }
4888         }
4889         ViewAbstractModel::GetInstance()->SetUseEffect(info[0]->ToBoolean(), effectType);
4890     }
4891 }
4892 
JsUseShadowBatching(const JSCallbackInfo & info)4893 void JSViewAbstract::JsUseShadowBatching(const JSCallbackInfo& info)
4894 {
4895     if (info[0]->IsBoolean()) {
4896         ViewAbstractModel::GetInstance()->SetUseShadowBatching(info[0]->ToBoolean());
4897     } else if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
4898         ViewAbstractModel::GetInstance()->SetUseShadowBatching(false);
4899     }
4900 }
4901 
JsBackdropBlur(const JSCallbackInfo & info)4902 void JSViewAbstract::JsBackdropBlur(const JSCallbackInfo& info)
4903 {
4904     if (info.Length() == 0) {
4905         return;
4906     }
4907     double blur = 0.0;
4908     BlurOption blurOption;
4909     if (!ParseJsDouble(info[0], blur)) {
4910         if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
4911             return;
4912         }
4913     }
4914     CalcDimension dimensionRadius(blur, DimensionUnit::PX);
4915     if (info.Length() > 1 && info[1]->IsObject()) {
4916         JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(info[1]);
4917         ParseBlurOption(jsBlurOption, blurOption);
4918     }
4919     ViewAbstractModel::GetInstance()->SetBackdropBlur(dimensionRadius, blurOption);
4920     info.SetReturnValue(info.This());
4921 }
4922 
GetFractionStops(std::vector<std::pair<float,float>> & fractionStops,const JSRef<JSVal> & array)4923 void JSViewAbstract::GetFractionStops(
4924     std::vector<std::pair<float, float>>& fractionStops, const JSRef<JSVal>& array)
4925 {
4926     if (!array->IsArray() || JSRef<JSArray>::Cast(array)->Length() <= 1) {
4927         return;
4928     }
4929     JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(array);
4930     float tmpPos = -1.0f;
4931     size_t length = jsArray->Length();
4932     for (size_t i = 0; i < length; i++) {
4933         std::pair<float, float> fractionStop;
4934         JSRef<JSVal> item = jsArray->GetValueAt(i);
4935         if (!item->IsArray()) {
4936             continue;
4937         }
4938         JSRef<JSArray> subArray = JSRef<JSArray>::Cast(item);
4939         if (subArray->Length() < 2) {
4940             continue;
4941         }
4942 
4943         double value = 0.0;
4944         if (ParseJsDouble(subArray->GetValueAt(0), value)) {
4945             value = std::clamp(value, 0.0, 1.0);
4946             fractionStop.first = static_cast<float>(value);
4947         }
4948         value = 0.0;
4949         if (ParseJsDouble(subArray->GetValueAt(1), value)) {
4950             value = std::clamp(value, 0.0, 1.0);
4951             fractionStop.second = static_cast<float>(value);
4952         }
4953 
4954         if (fractionStop.second <= tmpPos) {
4955             fractionStops.clear();
4956             return;
4957         }
4958         tmpPos = fractionStop.second;
4959         fractionStops.push_back(fractionStop);
4960     }
4961 }
JsLinearGradientBlur(const JSCallbackInfo & info)4962 void JSViewAbstract::JsLinearGradientBlur(const JSCallbackInfo& info)
4963 {
4964     if (info.Length() < 2) { // 2 represents the least para num;
4965         return;
4966     }
4967     double blurRadius = 0.0;
4968     ParseJsDouble(info[0], blurRadius);
4969 
4970     std::vector<std::pair<float, float>> fractionStops;
4971     auto direction = GradientDirection::BOTTOM;
4972     if (info[1]->IsObject()) {
4973         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[1]);
4974         GetFractionStops(fractionStops, jsObj->GetProperty("fractionStops"));
4975         auto directionValue =
4976             jsObj->GetPropertyValue<int8_t>("direction", static_cast<int8_t>(GradientDirection::BOTTOM));
4977         if (directionValue < static_cast<int8_t>(GradientDirection::LEFT) ||
4978             directionValue >= static_cast<int8_t>(GradientDirection::NONE)) {
4979             directionValue = static_cast<int8_t>(GradientDirection::BOTTOM);
4980         }
4981         direction = static_cast<GradientDirection>(directionValue);
4982     }
4983     if (static_cast<int32_t>(fractionStops.size()) <= 1) {
4984         fractionStops.clear();
4985         fractionStops.push_back(std::pair<float, float>(0.0f, 0.0f));
4986         fractionStops.push_back(std::pair<float, float>(0.0f, 1.0f));
4987     }
4988     // Parse direction
4989     CalcDimension dimensionRadius(static_cast<float>(blurRadius), DimensionUnit::PX);
4990     NG::LinearGradientBlurPara blurPara(dimensionRadius, fractionStops, static_cast<NG::GradientDirection>(direction));
4991     SetLinearGradientBlur(blurPara);
4992 }
4993 
JsBackgroundBrightness(const JSCallbackInfo & info)4994 void JSViewAbstract::JsBackgroundBrightness(const JSCallbackInfo& info)
4995 {
4996     double rate = 0.0;
4997     double lightUpDegree = 0.0;
4998     if (info[0]->IsObject()) {
4999         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
5000         ParseJsDouble(jsObj->GetProperty("rate"), rate);
5001         ParseJsDouble(jsObj->GetProperty("lightUpDegree"), lightUpDegree);
5002     }
5003     SetDynamicLightUp(rate, lightUpDegree);
5004 }
5005 
JsBackgroundBrightnessInternal(const JSCallbackInfo & info)5006 void JSViewAbstract::JsBackgroundBrightnessInternal(const JSCallbackInfo& info)
5007 {
5008     if (info.Length() == 0) {
5009         return;
5010     }
5011     BrightnessOption option;
5012     if (info[0]->IsObject()) {
5013         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[0]);
5014         ParseBrightnessOption(jsOption, option);
5015     }
5016     SetBgDynamicBrightness(option);
5017 }
5018 
JsForegroundBrightness(const JSCallbackInfo & info)5019 void JSViewAbstract::JsForegroundBrightness(const JSCallbackInfo& info)
5020 {
5021     if (info.Length() == 0) {
5022         return;
5023     }
5024     BrightnessOption option;
5025     if (info[0]->IsObject()) {
5026         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[0]);
5027         ParseBrightnessOption(jsOption, option);
5028     }
5029     SetFgDynamicBrightness(option);
5030 }
5031 
JsWindowBlur(const JSCallbackInfo & info)5032 void JSViewAbstract::JsWindowBlur(const JSCallbackInfo& info)
5033 {
5034     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
5035     auto jsVal = info[0];
5036     if (!CheckJSCallbackInfo("JsWindowBlur", jsVal, checkList)) {
5037         return;
5038     }
5039 
5040     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsVal);
5041     double progress = 0.0;
5042     ParseJsDouble(jsObj->GetProperty("percent"), progress);
5043     auto style = jsObj->GetPropertyValue<int32_t>("style",
5044         static_cast<int32_t>(WindowBlurStyle::STYLE_BACKGROUND_SMALL_LIGHT));
5045 
5046     progress = std::clamp(progress, 0.0, 1.0);
5047     style = std::clamp(style, static_cast<int32_t>(WindowBlurStyle::STYLE_BACKGROUND_SMALL_LIGHT),
5048         static_cast<int32_t>(WindowBlurStyle::STYLE_BACKGROUND_XLARGE_DARK));
5049 
5050     SetWindowBlur(static_cast<float>(progress), static_cast<WindowBlurStyle>(style));
5051     info.SetReturnValue(info.This());
5052 }
5053 
ParseDollarResource(const JSRef<JSVal> & jsValue,std::string & targetModule,ResourceType & resType,std::string & resName,bool isParseType)5054 bool JSViewAbstract::ParseDollarResource(const JSRef<JSVal>& jsValue, std::string& targetModule, ResourceType& resType,
5055     std::string& resName, bool isParseType)
5056 {
5057     if (!jsValue->IsString()) {
5058         return false;
5059     }
5060     std::string resPath = jsValue->ToString();
5061     std::smatch results;
5062     std::regex tokenRegex(RESOURCE_TOKEN_PATTERN);
5063     if (!std::regex_match(resPath, results, tokenRegex)) {
5064         return false;
5065     }
5066     targetModule = results[1];
5067     if (isParseType && !ConvertResourceType(results[2], resType)) {
5068         return false;
5069     }
5070     resName = resPath;
5071     return true;
5072 }
5073 
ConvertResourceType(const std::string & typeName,ResourceType & resType)5074 bool JSViewAbstract::ConvertResourceType(const std::string& typeName, ResourceType& resType)
5075 {
5076     static const std::unordered_map<std::string, ResourceType> resTypeMap {
5077         { "color", ResourceType::COLOR },
5078         { "media", ResourceType::MEDIA },
5079         { "float", ResourceType::FLOAT },
5080         { "string", ResourceType::STRING },
5081         { "plural", ResourceType::PLURAL },
5082         { "pattern", ResourceType::PATTERN },
5083         { "boolean", ResourceType::BOOLEAN },
5084         { "integer", ResourceType::INTEGER },
5085         { "strarray", ResourceType::STRARRAY },
5086         { "intarray", ResourceType::INTARRAY },
5087     };
5088     auto it = resTypeMap.find(typeName);
5089     if (it == resTypeMap.end()) {
5090         return false;
5091     }
5092     resType = it->second;
5093     return true;
5094 }
5095 
CompleteResourceObject(JSRef<JSObject> & jsObj)5096 void JSViewAbstract::CompleteResourceObject(JSRef<JSObject>& jsObj)
5097 {
5098     std::string bundleName;
5099     std::string moduleName;
5100     int32_t resId = -1;
5101     CompleteResourceObjectInner(jsObj, bundleName, moduleName, resId);
5102 }
5103 
CompleteResourceObjectWithBundleName(JSRef<JSObject> & jsObj,std::string & bundleName,std::string & moduleName,int32_t & resId)5104 void JSViewAbstract::CompleteResourceObjectWithBundleName(
5105     JSRef<JSObject>& jsObj, std::string& bundleName, std::string& moduleName, int32_t& resId)
5106 {
5107     CompleteResourceObjectInner(jsObj, bundleName, moduleName, resId);
5108 }
5109 
CompleteResourceObjectInner(JSRef<JSObject> & jsObj,std::string & bundleName,std::string & moduleName,int32_t & resIdValue)5110 void JSViewAbstract::CompleteResourceObjectInner(
5111     JSRef<JSObject>& jsObj, std::string& bundleName, std::string& moduleName, int32_t& resIdValue)
5112 {
5113     // dynamic $r raw input format is
5114     // {"id":"app.xxx.xxx", "params":[], "bundleName":"xxx", "moduleName":"xxx"}
5115     JSRef<JSVal> resId = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::ID));
5116     ResourceType resType;
5117 
5118     std::string targetModule;
5119     std::string resName;
5120     if (resId->IsString()) {
5121         JSRef<JSVal> type = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::TYPE));
5122         int32_t typeNum = -1;
5123         if (type->IsNumber()) {
5124             typeNum = type->ToNumber<int32_t>();
5125         }
5126         if (!ParseDollarResource(resId, targetModule, resType, resName, typeNum == UNKNOWN_RESOURCE_TYPE)) {
5127             return;
5128         }
5129         CompleteResourceObjectFromId(type, jsObj, resType, resName);
5130     } else if (resId->IsNumber()) {
5131         resIdValue = resId->ToNumber<int32_t>();
5132         if (resIdValue == -1) {
5133             CompleteResourceObjectFromParams(resIdValue, jsObj, targetModule, resType, resName);
5134         }
5135     }
5136 
5137     JSViewAbstract::GetJsMediaBundleInfo(jsObj, bundleName, moduleName);
5138     if ((bundleName.empty() && !moduleName.empty()) || bundleName == DEFAULT_HAR_BUNDLE_NAME) {
5139         bundleName = GetBundleNameFromContainer();
5140         jsObj->SetProperty<std::string>(static_cast<int32_t>(ArkUIIndex::BUNDLE_NAME), bundleName);
5141     }
5142     if (moduleName == DEFAULT_HAR_MODULE_NAME) {
5143         moduleName = GetModuleNameFromContainer();
5144         jsObj->SetProperty<std::string>(static_cast<int32_t>(ArkUIIndex::MODULE_NAME), moduleName);
5145     }
5146 }
5147 
ParseJsDimensionNG(const JSRef<JSVal> & jsValue,CalcDimension & result,DimensionUnit defaultUnit,bool isSupportPercent)5148 bool JSViewAbstract::ParseJsDimensionNG(
5149     const JSRef<JSVal>& jsValue, CalcDimension& result, DimensionUnit defaultUnit, bool isSupportPercent)
5150 {
5151     if (jsValue->IsNumber()) {
5152         result = CalcDimension(jsValue->ToNumber<double>(), defaultUnit);
5153         return true;
5154     }
5155     if (jsValue->IsString()) {
5156         auto value = jsValue->ToString();
5157         if (!isSupportPercent && value.back() == '%') {
5158             return false;
5159         }
5160         return StringUtils::StringToCalcDimensionNG(value, result, false, defaultUnit);
5161     }
5162     if (jsValue->IsObject()) {
5163         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5164         CompleteResourceObject(jsObj);
5165         JSRef<JSVal> resId = jsObj->GetProperty("id");
5166         if (!resId->IsNumber()) {
5167             return false;
5168         }
5169         auto resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
5170         if (resType == UNKNOWN_RESOURCE_TYPE) {
5171             return false;
5172         }
5173 
5174         auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
5175         auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
5176         if (!resourceWrapper) {
5177             return false;
5178         }
5179 
5180         auto resIdNum = resId->ToNumber<int32_t>();
5181         if (resIdNum == -1) {
5182             if (!IsGetResourceByName(jsObj)) {
5183                 return false;
5184             }
5185             JSRef<JSVal> args = jsObj->GetProperty("params");
5186             if (!args->IsArray()) {
5187                 return false;
5188             }
5189             JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5190             auto param = params->GetValueAt(0);
5191             if (resType == static_cast<int32_t>(ResourceType::STRING)) {
5192                 auto value = resourceWrapper->GetStringByName(param->ToString());
5193                 return StringUtils::StringToCalcDimensionNG(value, result, false, defaultUnit);
5194             }
5195             if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
5196                 auto value = std::to_string(resourceWrapper->GetIntByName(param->ToString()));
5197                 StringUtils::StringToDimensionWithUnitNG(value, result, defaultUnit);
5198                 return true;
5199             }
5200             result = resourceWrapper->GetDimensionByName(param->ToString());
5201             return true;
5202         }
5203 
5204         if (resType == static_cast<int32_t>(ResourceType::STRING)) {
5205             auto value = resourceWrapper->GetString(resId->ToNumber<uint32_t>());
5206             return StringUtils::StringToCalcDimensionNG(value, result, false, defaultUnit);
5207         }
5208         if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
5209             auto value = std::to_string(resourceWrapper->GetInt(resId->ToNumber<uint32_t>()));
5210             StringUtils::StringToDimensionWithUnitNG(value, result, defaultUnit);
5211             return true;
5212         }
5213 
5214         if (resType == static_cast<int32_t>(ResourceType::FLOAT)) {
5215             result = resourceWrapper->GetDimension(resId->ToNumber<uint32_t>()); // float return true pixel value
5216             return true;
5217         }
5218     }
5219 
5220     return false;
5221 }
5222 
ParseJsLengthNG(const JSRef<JSVal> & jsValue,NG::CalcLength & result,DimensionUnit defaultUnit,bool isSupportPercent)5223 bool JSViewAbstract::ParseJsLengthNG(
5224     const JSRef<JSVal>& jsValue, NG::CalcLength& result, DimensionUnit defaultUnit, bool isSupportPercent)
5225 {
5226     if (jsValue->IsNumber()) {
5227         if (std::isnan(jsValue->ToNumber<double>())) {
5228             return false;
5229         }
5230         result = NG::CalcLength(jsValue->ToNumber<double>(), defaultUnit);
5231         return true;
5232     } else if (jsValue->IsObject()) {
5233         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5234         JSRef<JSVal> value = jsObj->GetProperty("value");
5235         if (value->IsNull() || (value->IsNumber() && std::isnan(value->ToNumber<double>())) || value->IsUndefined()) {
5236             return false;
5237         }
5238         DimensionUnit unit = defaultUnit;
5239         JSRef<JSVal> jsUnit = jsObj->GetProperty("unit");
5240         if (jsUnit->IsNumber()) {
5241             if (!isSupportPercent && jsUnit->ToNumber<int32_t>() == static_cast<int32_t>(DimensionUnit::PERCENT)) {
5242                 return false;
5243             }
5244             unit = static_cast<DimensionUnit>(jsUnit->ToNumber<int32_t>());
5245         }
5246         result = NG::CalcLength(value->ToNumber<double>(), unit);
5247         return true;
5248     }
5249 
5250     return false;
5251 }
5252 
ParseJsLengthVpNG(const JSRef<JSVal> & jsValue,NG::CalcLength & result,bool isSupportPercent)5253 bool JSViewAbstract::ParseJsLengthVpNG(const JSRef<JSVal>& jsValue, NG::CalcLength& result, bool isSupportPercent)
5254 {
5255     // 'vp' -> the value varies with pixel density of device.
5256     return ParseJsLengthNG(jsValue, result, DimensionUnit::VP, isSupportPercent);
5257 }
5258 
ParseJsDimension(const JSRef<JSVal> & jsValue,CalcDimension & result,DimensionUnit defaultUnit)5259 bool JSViewAbstract::ParseJsDimension(const JSRef<JSVal>& jsValue, CalcDimension& result, DimensionUnit defaultUnit)
5260 {
5261     if (jsValue->IsNumber()) {
5262         result = CalcDimension(jsValue->ToNumber<double>(), defaultUnit);
5263         return true;
5264     }
5265     if (jsValue->IsString()) {
5266         result = StringUtils::StringToCalcDimension(jsValue->ToString(), false, defaultUnit);
5267         return true;
5268     }
5269     if (!jsValue->IsObject()) {
5270         return false;
5271     }
5272     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5273     CompleteResourceObject(jsObj);
5274     JSRef<JSVal> resId = jsObj->GetProperty("id");
5275     if (!resId->IsNumber()) {
5276         return false;
5277     }
5278 
5279     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
5280     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
5281     if (!resourceWrapper) {
5282         return false;
5283     }
5284 
5285     auto resIdNum = resId->ToNumber<int32_t>();
5286     int32_t resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
5287     if (resType == UNKNOWN_RESOURCE_TYPE) {
5288         return false;
5289     }
5290 
5291     if (resIdNum == -1) {
5292         if (!IsGetResourceByName(jsObj)) {
5293             return false;
5294         }
5295         JSRef<JSVal> args = jsObj->GetProperty("params");
5296         if (!args->IsArray()) {
5297             return false;
5298         }
5299         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5300         auto param = params->GetValueAt(0);
5301         if (resType == static_cast<int32_t>(ResourceType::STRING)) {
5302             auto value = resourceWrapper->GetStringByName(param->ToString());
5303             result = StringUtils::StringToCalcDimension(value, false, defaultUnit);
5304             return true;
5305         }
5306         if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
5307             auto value = std::to_string(resourceWrapper->GetIntByName(param->ToString()));
5308             result = StringUtils::StringToDimensionWithUnit(value, defaultUnit);
5309             return true;
5310         }
5311         result = resourceWrapper->GetDimensionByName(param->ToString());
5312         return true;
5313     }
5314 
5315     if (resType == static_cast<int32_t>(ResourceType::STRING)) {
5316         auto value = resourceWrapper->GetString(resId->ToNumber<uint32_t>());
5317         result = StringUtils::StringToCalcDimension(value, false, defaultUnit);
5318         return true;
5319     }
5320     if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
5321         auto value = std::to_string(resourceWrapper->GetInt(resId->ToNumber<uint32_t>()));
5322         result = StringUtils::StringToDimensionWithUnit(value, defaultUnit);
5323         return true;
5324     }
5325     result = resourceWrapper->GetDimension(resId->ToNumber<uint32_t>());
5326     return true;
5327 }
5328 
ParseJsDimensionVpNG(const JSRef<JSVal> & jsValue,CalcDimension & result,bool isSupportPercent)5329 bool JSViewAbstract::ParseJsDimensionVpNG(const JSRef<JSVal>& jsValue, CalcDimension& result, bool isSupportPercent)
5330 {
5331     // 'vp' -> the value varies with pixel density of device.
5332     return ParseJsDimensionNG(jsValue, result, DimensionUnit::VP, isSupportPercent);
5333 }
5334 
ParseJsDimensionVp(const JSRef<JSVal> & jsValue,CalcDimension & result)5335 bool JSViewAbstract::ParseJsDimensionVp(const JSRef<JSVal>& jsValue, CalcDimension& result)
5336 {
5337     // 'vp' -> the value varies with pixel density of device.
5338     return ParseJsDimension(jsValue, result, DimensionUnit::VP);
5339 }
5340 
ParseJsDimensionFp(const JSRef<JSVal> & jsValue,CalcDimension & result)5341 bool JSViewAbstract::ParseJsDimensionFp(const JSRef<JSVal>& jsValue, CalcDimension& result)
5342 {
5343     // the 'fp' unit is used for text scenes.
5344     return ParseJsDimension(jsValue, result, DimensionUnit::FP);
5345 }
5346 
ParseJsDimensionFpNG(const JSRef<JSVal> & jsValue,CalcDimension & result,bool isSupportPercent)5347 bool JSViewAbstract::ParseJsDimensionFpNG(const JSRef<JSVal>& jsValue, CalcDimension& result, bool isSupportPercent)
5348 {
5349     // the 'fp' unit is used for text scenes.
5350     return ParseJsDimensionNG(jsValue, result, DimensionUnit::FP, isSupportPercent);
5351 }
5352 
ParseJsDimensionPx(const JSRef<JSVal> & jsValue,CalcDimension & result)5353 bool JSViewAbstract::ParseJsDimensionPx(const JSRef<JSVal>& jsValue, CalcDimension& result)
5354 {
5355     return ParseJsDimension(jsValue, result, DimensionUnit::PX);
5356 }
5357 
ParseColorMetricsToColor(const JSRef<JSVal> & jsValue,Color & result)5358 bool JSViewAbstract::ParseColorMetricsToColor(const JSRef<JSVal>& jsValue, Color& result)
5359 {
5360     if (!jsValue->IsObject()) {
5361         return false;
5362     }
5363     auto colorObj = JSRef<JSObject>::Cast(jsValue);
5364     auto toNumericProp = colorObj->GetProperty("toNumeric");
5365     if (toNumericProp->IsFunction()) {
5366         auto colorVal = JSRef<JSFunc>::Cast(toNumericProp)->Call(colorObj, 0, nullptr);
5367         result.SetValue(colorVal->ToNumber<uint32_t>());
5368         return true;
5369     }
5370     return false;
5371 }
5372 
ParseLengthMetricsToDimension(const JSRef<JSVal> & jsValue,CalcDimension & result)5373 bool JSViewAbstract::ParseLengthMetricsToDimension(const JSRef<JSVal>& jsValue, CalcDimension& result)
5374 {
5375     if (jsValue->IsNumber()) {
5376         result = CalcDimension(jsValue->ToNumber<double>(), DimensionUnit::FP);
5377         return true;
5378     }
5379     if (jsValue->IsString()) {
5380         auto value = jsValue->ToString();
5381         return StringUtils::StringToCalcDimensionNG(value, result, false, DimensionUnit::FP);
5382     }
5383     if (jsValue->IsObject()) {
5384         auto jsObj = JSRef<JSObject>::Cast(jsValue);
5385         auto valObj = jsObj->GetProperty("value");
5386         if (valObj->IsUndefined() || valObj->IsNull()) {
5387             return false;
5388         }
5389         double value = valObj->ToNumber<double>();
5390         auto unit = static_cast<DimensionUnit>(jsObj->GetProperty("unit")->ToNumber<int32_t>());
5391         result = CalcDimension(value, unit);
5392         return true;
5393     }
5394     return false;
5395 }
5396 
ParseLengthMetricsToPositiveDimension(const JSRef<JSVal> & jsValue,CalcDimension & result)5397 bool JSViewAbstract::ParseLengthMetricsToPositiveDimension(const JSRef<JSVal>& jsValue, CalcDimension& result)
5398 {
5399     return ParseLengthMetricsToDimension(jsValue, result) ? GreatOrEqual(result.Value(), 0.0f) : false;
5400 }
5401 
ParseResourceToDouble(const JSRef<JSVal> & jsValue,double & result)5402 bool JSViewAbstract::ParseResourceToDouble(const JSRef<JSVal>& jsValue, double& result)
5403 {
5404     if (!jsValue->IsObject()) {
5405         return false;
5406     }
5407     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5408     CompleteResourceObject(jsObj);
5409     if (jsObj->IsEmpty()) {
5410         return false;
5411     }
5412     JSRef<JSVal> id = jsObj->GetProperty("id");
5413     if (!id->IsNumber()) {
5414         return false;
5415     }
5416 
5417     auto resId = id->ToNumber<int32_t>();
5418     int32_t resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
5419     if (resType == UNKNOWN_RESOURCE_TYPE) {
5420         return false;
5421     }
5422 
5423     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
5424     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
5425     if (!resourceWrapper) {
5426         return false;
5427     }
5428 
5429     if (resId == -1) {
5430         if (!IsGetResourceByName(jsObj)) {
5431             return false;
5432         }
5433         JSRef<JSVal> args = jsObj->GetProperty("params");
5434         if (!args->IsArray()) {
5435             return false;
5436         }
5437         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5438         auto param = params->GetValueAt(0);
5439         if (resType == static_cast<int32_t>(ResourceType::STRING)) {
5440             auto numberString = resourceWrapper->GetStringByName(param->ToString());
5441             return StringUtils::StringToDouble(numberString, result);
5442         }
5443         if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
5444             result = resourceWrapper->GetIntByName(param->ToString());
5445             return true;
5446         }
5447         if (resType == static_cast<int32_t>(ResourceType::FLOAT)) {
5448             result = resourceWrapper->GetDoubleByName(param->ToString());
5449             return true;
5450         }
5451         return false;
5452     }
5453     if (resType == static_cast<int32_t>(ResourceType::STRING)) {
5454         auto numberString = resourceWrapper->GetString(resId);
5455         return StringUtils::StringToDouble(numberString, result);
5456     }
5457     if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
5458         result = resourceWrapper->GetInt(resId);
5459         return true;
5460     }
5461     if (resType == static_cast<int32_t>(ResourceType::FLOAT)) {
5462         result = resourceWrapper->GetDouble(resId);
5463         return true;
5464     }
5465     return false;
5466 }
5467 
ParseJsDouble(const JSRef<JSVal> & jsValue,double & result)5468 bool JSViewAbstract::ParseJsDouble(const JSRef<JSVal>& jsValue, double& result)
5469 {
5470     if (jsValue->IsNumber()) {
5471         result = jsValue->ToNumber<double>();
5472         return true;
5473     }
5474     if (jsValue->IsString()) {
5475         return StringUtils::StringToDouble(jsValue->ToString(), result);
5476     }
5477     if (jsValue->IsObject()) {
5478         return ParseResourceToDouble(jsValue, result);
5479     }
5480     return false;
5481 }
5482 
ParseJsInt32(const JSRef<JSVal> & jsValue,int32_t & result)5483 bool JSViewAbstract::ParseJsInt32(const JSRef<JSVal>& jsValue, int32_t& result)
5484 {
5485     if (jsValue->IsNumber()) {
5486         result = jsValue->ToNumber<int32_t>();
5487         return true;
5488     }
5489     if (jsValue->IsString()) {
5490         result = StringUtils::StringToInt(jsValue->ToString());
5491         return true;
5492     }
5493     if (!jsValue->IsObject()) {
5494         return false;
5495     }
5496     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5497     CompleteResourceObject(jsObj);
5498     JSRef<JSVal> resId = jsObj->GetProperty("id");
5499     if (!resId->IsNumber()) {
5500         return false;
5501     }
5502 
5503     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
5504     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
5505     if (!resourceWrapper) {
5506         return false;
5507     }
5508 
5509     auto resIdNum = resId->ToNumber<int32_t>();
5510     if (resIdNum == -1) {
5511         if (!IsGetResourceByName(jsObj)) {
5512             return false;
5513         }
5514         JSRef<JSVal> args = jsObj->GetProperty("params");
5515         if (!args->IsArray()) {
5516             return false;
5517         }
5518         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5519         auto param = params->GetValueAt(0);
5520         result = resourceWrapper->GetIntByName(param->ToString());
5521         return true;
5522     }
5523     result = resourceWrapper->GetInt(resId->ToNumber<uint32_t>());
5524     return true;
5525 }
5526 
ParseJsColorFromResource(const JSRef<JSVal> & jsValue,Color & result)5527 bool JSViewAbstract::ParseJsColorFromResource(const JSRef<JSVal>& jsValue, Color& result)
5528 {
5529     if (!jsValue->IsObject()) {
5530         return false;
5531     }
5532     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5533     CompleteResourceObject(jsObj);
5534 
5535     auto ok = JSViewAbstract::ParseJsObjColorFromResource(jsObj, result);
5536     if (ok) {
5537         JSRef<JSVal> jsOpacityRatio = jsObj->GetProperty("opacityRatio");
5538         if (jsOpacityRatio->IsNumber()) {
5539             double opacityRatio = jsOpacityRatio->ToNumber<double>();
5540             result = result.BlendOpacity(opacityRatio);
5541         }
5542     }
5543     return ok;
5544 }
5545 
ParseJsObjColorFromResource(const JSRef<JSObject> & jsObj,Color & result)5546 bool JSViewAbstract::ParseJsObjColorFromResource(const JSRef<JSObject> &jsObj, Color& result)
5547 {
5548     JSRef<JSVal> resId = jsObj->GetProperty("id");
5549     if (!resId->IsNumber()) {
5550         return false;
5551     }
5552 
5553     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
5554     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
5555     if (!resourceWrapper) {
5556         return false;
5557     }
5558 
5559     auto resIdNum = resId->ToNumber<int32_t>();
5560     if (resIdNum == -1) {
5561         if (!IsGetResourceByName(jsObj)) {
5562             return false;
5563         }
5564         JSRef<JSVal> args = jsObj->GetProperty("params");
5565         if (!args->IsArray()) {
5566             return false;
5567         }
5568         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5569         auto param = params->GetValueAt(0);
5570         result = resourceWrapper->GetColorByName(param->ToString());
5571         return true;
5572     }
5573 
5574     auto type = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
5575     if (type == static_cast<int32_t>(ResourceType::STRING)) {
5576         auto value = resourceWrapper->GetString(resId->ToNumber<uint32_t>());
5577         return Color::ParseColorString(value, result);
5578     }
5579     if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
5580         auto value = resourceWrapper->GetInt(resId->ToNumber<uint32_t>());
5581         result = Color(ColorAlphaAdapt(value));
5582         return true;
5583     }
5584     if (type == static_cast<int32_t>(ResourceType::COLOR)) {
5585         result = resourceWrapper->GetColor(resId->ToNumber<uint32_t>());
5586         result.SetResourceId(resId->ToNumber<uint32_t>());
5587         return true;
5588     }
5589     return false;
5590 }
5591 
ParseJsColor(const JSRef<JSVal> & jsValue,Color & result)5592 bool JSViewAbstract::ParseJsColor(const JSRef<JSVal>& jsValue, Color& result)
5593 {
5594     if (jsValue->IsNumber()) {
5595         result = Color(ColorAlphaAdapt(jsValue->ToNumber<uint32_t>()));
5596         return true;
5597     }
5598     if (jsValue->IsString()) {
5599         return Color::ParseColorString(jsValue->ToString(), result);
5600     }
5601     if (jsValue->IsObject()) {
5602         return ParseJsColorFromResource(jsValue, result);
5603     }
5604     return false;
5605 }
5606 
ParseJsColor(const JSRef<JSVal> & jsValue,Color & result,const Color & defaultColor)5607 bool JSViewAbstract::ParseJsColor(const JSRef<JSVal>& jsValue, Color& result, const Color& defaultColor)
5608 {
5609     if (jsValue->IsNumber()) {
5610         result = Color(ColorAlphaAdapt(jsValue->ToNumber<uint32_t>()));
5611         return true;
5612     }
5613     if (jsValue->IsString()) {
5614         return Color::ParseColorString(jsValue->ToString(), result, defaultColor);
5615     }
5616     if (!jsValue->IsObject()) {
5617         return false;
5618     }
5619     return ParseJsColorFromResource(jsValue, result);
5620 }
5621 
ParseJsColorStrategy(const JSRef<JSVal> & jsValue,ForegroundColorStrategy & strategy)5622 bool JSViewAbstract::ParseJsColorStrategy(const JSRef<JSVal>& jsValue, ForegroundColorStrategy& strategy)
5623 {
5624     if (jsValue->IsString()) {
5625         std::string colorStr = jsValue->ToString();
5626         if (colorStr.compare("invert") == 0) {
5627             strategy = ForegroundColorStrategy::INVERT;
5628             return true;
5629         }
5630     }
5631     return false;
5632 }
5633 
ParseJsShadowColorStrategy(const JSRef<JSVal> & jsValue,ShadowColorStrategy & strategy)5634 bool JSViewAbstract::ParseJsShadowColorStrategy(const JSRef<JSVal>& jsValue, ShadowColorStrategy& strategy)
5635 {
5636     if (jsValue->IsString()) {
5637         std::string colorStr = jsValue->ToString();
5638         if (colorStr.compare("average") == 0) {
5639             strategy = ShadowColorStrategy::AVERAGE;
5640             return true;
5641         } else if (colorStr.compare("primary") == 0) {
5642             strategy = ShadowColorStrategy::PRIMARY;
5643             return true;
5644         }
5645     }
5646     return false;
5647 }
5648 
ParseJsSymbolId(const JSRef<JSVal> & jsValue,std::uint32_t & symbolId,RefPtr<ResourceObject> & symbolResourceObject)5649 bool JSViewAbstract::ParseJsSymbolId(
5650     const JSRef<JSVal>& jsValue, std::uint32_t& symbolId, RefPtr<ResourceObject>& symbolResourceObject)
5651 {
5652     if (jsValue->IsNull() || jsValue->IsUndefined()) {
5653         symbolId = 0;
5654         return false;
5655     }
5656     if (!jsValue->IsObject()) {
5657         return false;
5658     }
5659     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5660     CompleteResourceObject(jsObj);
5661     JSRef<JSVal> resId = jsObj->GetProperty("id");
5662     if (resId->IsNull() || !resId->IsNumber()) {
5663         return false;
5664     }
5665     auto resourceObject = GetResourceObject(jsObj);
5666     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
5667     symbolResourceObject = resourceObject;
5668     if (!resourceWrapper) {
5669         return false;
5670     }
5671     if (!resourceObject) {
5672         return false;
5673     }
5674 
5675     auto resIdNum = resId->ToNumber<int32_t>();
5676     if (resIdNum == -1) {
5677         if (!IsGetResourceByName(jsObj)) {
5678             return false;
5679         }
5680         JSRef<JSVal> args = jsObj->GetProperty("params");
5681         if (!args->IsArray()) {
5682             return false;
5683         }
5684         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5685         auto param = params->GetValueAt(0);
5686         auto symbol = resourceWrapper->GetSymbolByName(param->ToString().c_str());
5687         if (!symbol) {
5688             return false;
5689         }
5690         symbolId = symbol;
5691         return true;
5692     }
5693 
5694     auto symbol = resourceWrapper->GetSymbolById(resIdNum);
5695     if (!symbol) {
5696         return false;
5697     }
5698     symbolId = symbol;
5699     return true;
5700 }
5701 
ParseJsSymbolColor(const JSRef<JSVal> & jsValue,std::vector<Color> & result)5702 bool JSViewAbstract::ParseJsSymbolColor(const JSRef<JSVal>& jsValue, std::vector<Color>& result)
5703 {
5704     if (!jsValue->IsArray()) {
5705         return false;
5706     }
5707     if (jsValue->IsArray()) {
5708         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
5709         for (size_t i = 0; i < array->Length(); i++) {
5710             JSRef<JSVal> value = array->GetValueAt(i);
5711             if (!value->IsNumber() && !value->IsString() && !value->IsObject()) {
5712                 return false;
5713             }
5714             if (value->IsNumber()) {
5715                 result.emplace_back(Color(ColorAlphaAdapt(value->ToNumber<uint32_t>())));
5716                 continue;
5717             } else if (value->IsString()) {
5718                 Color color;
5719                 Color::ParseColorString(value->ToString(), color);
5720                 result.emplace_back(color);
5721                 continue;
5722             } else {
5723                 Color color;
5724                 ParseJsColorFromResource(value, color);
5725                 result.emplace_back(color);
5726             }
5727         }
5728         return true;
5729     }
5730     return false;
5731 }
5732 
ParseJsFontFamilies(const JSRef<JSVal> & jsValue,std::vector<std::string> & result)5733 bool JSViewAbstract::ParseJsFontFamilies(const JSRef<JSVal>& jsValue, std::vector<std::string>& result)
5734 {
5735     result.clear();
5736     if (!jsValue->IsString() && !jsValue->IsObject()) {
5737         return false;
5738     }
5739     if (jsValue->IsString()) {
5740         result = ConvertStrToFontFamilies(jsValue->ToString());
5741         return true;
5742     }
5743     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5744     CompleteResourceObject(jsObj);
5745     JSRef<JSVal> resId = jsObj->GetProperty("id");
5746     if (!resId->IsNumber()) {
5747         return false;
5748     }
5749 
5750     auto resourceObject = GetResourceObject(jsObj);
5751     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
5752     if (!resourceWrapper) {
5753         return false;
5754     }
5755 
5756     auto resIdNum = resId->ToNumber<int32_t>();
5757     if (resIdNum == -1) {
5758         if (!IsGetResourceByName(jsObj)) {
5759             return false;
5760         }
5761         JSRef<JSVal> args = jsObj->GetProperty("params");
5762         if (!args->IsArray()) {
5763             return false;
5764         }
5765         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5766         auto param = params->GetValueAt(0);
5767         result.emplace_back(resourceWrapper->GetStringByName(param->ToString()));
5768         return true;
5769     }
5770     result.emplace_back(resourceWrapper->GetString(resId->ToNumber<uint32_t>()));
5771     return true;
5772 }
5773 
ParseJsString(const JSRef<JSVal> & jsValue,std::string & result)5774 bool JSViewAbstract::ParseJsString(const JSRef<JSVal>& jsValue, std::string& result)
5775 {
5776     if (jsValue->IsString()) {
5777         result = jsValue->ToString();
5778         return true;
5779     }
5780 
5781     if (!jsValue->IsObject()) {
5782         return false;
5783     }
5784 
5785     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5786     CompleteResourceObject(jsObj);
5787 
5788     JSRef<JSVal> resId = jsObj->GetProperty("id");
5789     if (!resId->IsNumber()) {
5790         return false;
5791     }
5792     auto type = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
5793     if (type == UNKNOWN_RESOURCE_TYPE) {
5794         return false;
5795     }
5796 
5797     JSRef<JSVal> args = jsObj->GetProperty("params");
5798     if (!args->IsArray()) {
5799         return false;
5800     }
5801 
5802     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
5803     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
5804     if (!resourceWrapper) {
5805         return false;
5806     }
5807 
5808     JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5809     auto resIdNum = resId->ToNumber<int32_t>();
5810     if (resIdNum == -1) {
5811         if (!IsGetResourceByName(jsObj)) {
5812             return false;
5813         }
5814         auto param = params->GetValueAt(0);
5815         if (type == static_cast<int32_t>(ResourceType::STRING)) {
5816             auto originStr = resourceWrapper->GetStringByName(param->ToString());
5817             ReplaceHolder(originStr, params, 1);
5818             result = originStr;
5819         } else if (type == static_cast<int32_t>(ResourceType::PLURAL)) {
5820             auto countJsVal = params->GetValueAt(1);
5821             int count = 0;
5822             if (!countJsVal->IsNumber()) {
5823                 return false;
5824             }
5825             count = countJsVal->ToNumber<int>();
5826             auto pluralStr = resourceWrapper->GetPluralStringByName(param->ToString(), count);
5827             ReplaceHolder(pluralStr, params, 2);
5828             result = pluralStr;
5829         } else {
5830             return false;
5831         }
5832         return true;
5833     }
5834     if (type == static_cast<int32_t>(ResourceType::STRING)) {
5835         auto originStr = resourceWrapper->GetString(resId->ToNumber<uint32_t>());
5836         ReplaceHolder(originStr, params, 0);
5837         result = originStr;
5838     } else if (type == static_cast<int32_t>(ResourceType::PLURAL)) {
5839         auto countJsVal = params->GetValueAt(0);
5840         int count = 0;
5841         if (!countJsVal->IsNumber()) {
5842             return false;
5843         }
5844         count = countJsVal->ToNumber<int>();
5845         auto pluralStr = resourceWrapper->GetPluralString(resId->ToNumber<uint32_t>(), count);
5846         ReplaceHolder(pluralStr, params, 1);
5847         result = pluralStr;
5848     } else if (type == static_cast<int32_t>(ResourceType::FLOAT)) {
5849         result = std::to_string(resourceWrapper->GetDouble(resId->ToNumber<uint32_t>()));
5850     } else if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
5851         result = std::to_string(resourceWrapper->GetInt(resId->ToNumber<uint32_t>()));
5852     } else {
5853         return false;
5854     }
5855     return true;
5856 }
5857 
ParseJsMedia(const JSRef<JSVal> & jsValue,std::string & result)5858 bool JSViewAbstract::ParseJsMedia(const JSRef<JSVal>& jsValue, std::string& result)
5859 {
5860     if (!jsValue->IsObject() && !jsValue->IsString()) {
5861         return false;
5862     }
5863     if (jsValue->IsString()) {
5864         result = jsValue->ToString();
5865         return true;
5866     }
5867     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5868     CompleteResourceObject(jsObj);
5869     return ParseJSMediaInternal(jsObj, result);
5870 }
5871 
ParseJsMediaWithBundleName(const JSRef<JSVal> & jsValue,std::string & result,std::string & bundleName,std::string & moduleName,int32_t & resId)5872 bool JSViewAbstract::ParseJsMediaWithBundleName(
5873     const JSRef<JSVal>& jsValue, std::string& result, std::string& bundleName, std::string& moduleName, int32_t& resId)
5874 {
5875     if (!jsValue->IsObject() && !jsValue->IsString()) {
5876         return JSViewAbstract::GetJsMediaBundleInfo(jsValue, bundleName, moduleName);
5877     }
5878     if (jsValue->IsString()) {
5879         result = jsValue->ToString();
5880         return JSViewAbstract::GetJsMediaBundleInfo(jsValue, bundleName, moduleName);
5881     }
5882     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5883     CompleteResourceObjectWithBundleName(jsObj, bundleName, moduleName, resId);
5884     return ParseJSMediaInternal(jsObj, result);
5885 }
5886 
ParseJSMediaInternal(const JSRef<JSObject> & jsObj,std::string & result)5887 bool JSViewAbstract::ParseJSMediaInternal(const JSRef<JSObject>& jsObj, std::string& result)
5888 {
5889     int32_t type = jsObj->GetPropertyValue<int32_t>(static_cast<int32_t>(ArkUIIndex::TYPE), UNKNOWN_RESOURCE_TYPE);
5890     JSRef<JSVal> resId = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::ID));
5891     if (!resId->IsNull() && type != UNKNOWN_RESOURCE_TYPE && resId->IsNumber()) {
5892         auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
5893         auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
5894         CHECK_NULL_RETURN(resourceWrapper, false);
5895         if (type == static_cast<int32_t>(ResourceType::RAWFILE)) {
5896             JSRef<JSVal> args = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::PARAMS));
5897             if (!args->IsArray()) {
5898                 return false;
5899             }
5900             JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5901             auto fileName = params->GetValueAt(0);
5902             if (!fileName->IsString()) {
5903                 return false;
5904             }
5905             result = resourceWrapper->GetRawfile(fileName->ToString());
5906             return true;
5907         }
5908         auto resIdNum = resId->ToNumber<int32_t>();
5909         if (resIdNum == -1) {
5910             if (!IsGetResourceByName(jsObj)) {
5911                 return false;
5912             }
5913             JSRef<JSVal> args = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::PARAMS));
5914             if (!args->IsArray()) {
5915                 return false;
5916             }
5917             JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
5918             auto param = params->GetValueAt(0);
5919             if (type == static_cast<int32_t>(ResourceType::MEDIA)) {
5920                 result = resourceWrapper->GetMediaPathByName(param->ToString());
5921                 return true;
5922             }
5923             if (type == static_cast<int32_t>(ResourceType::STRING)) {
5924                 result = resourceWrapper->GetStringByName(param->ToString());
5925                 return true;
5926             }
5927             return false;
5928         } else if (type == static_cast<int32_t>(ResourceType::MEDIA)) {
5929             result = resourceWrapper->GetMediaPath(resId->ToNumber<uint32_t>());
5930             return true;
5931         } else if (type == static_cast<int32_t>(ResourceType::STRING)) {
5932             result = resourceWrapper->GetString(resId->ToNumber<uint32_t>());
5933             return true;
5934         }
5935     }
5936     return false;
5937 }
5938 
SetTabBarSymbolOptionApply(const JSCallbackInfo & info,TabBarSymbol & symbolApply,const JSRef<JSVal> & modifierNormalObj,const JSRef<JSVal> & modifierSelectedObj)5939 void JSViewAbstract::SetTabBarSymbolOptionApply(const JSCallbackInfo& info, TabBarSymbol& symbolApply,
5940     const JSRef<JSVal>& modifierNormalObj, const JSRef<JSVal>& modifierSelectedObj)
5941 {
5942     auto vm = info.GetVm();
5943     auto globalObj = JSNApi::GetGlobalObject(vm);
5944     auto globalFunc = globalObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "applySymbolGlyphModifierToNode"));
5945     JsiValue jsiValue(globalFunc);
5946     JsiRef<JsiValue> globalFuncRef = JsiRef<JsiValue>::Make(jsiValue);
5947     if (!globalFuncRef->IsFunction()) {
5948         return;
5949     }
5950     if (modifierNormalObj->IsUndefined()) {
5951         symbolApply.onApply = nullptr;
5952     } else {
5953         RefPtr<JsFunction> jsFunc =
5954             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(globalFuncRef));
5955         auto onApply = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
5956                             modifierNormal = std::move(modifierNormalObj),
5957                             modifierSelected = std::move(modifierSelectedObj)](
5958                             WeakPtr<NG::FrameNode> frameNode, std::string type) {
5959             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5960             auto node = frameNode.Upgrade();
5961             CHECK_NULL_VOID(node);
5962             JSRef<JSVal> params[SECOND_INDEX];
5963             if (type == "normal") {
5964                 params[0] = modifierNormal;
5965             } else if (!modifierSelected->IsUndefined()) {
5966                 params[0] = modifierSelected;
5967             }
5968             params[1] = JSRef<JSVal>::Make(panda::NativePointerRef::New(execCtx.vm_, AceType::RawPtr(node)));
5969             PipelineContext::SetCallBackNode(node);
5970             func->ExecuteJS(SECOND_INDEX, params);
5971         };
5972         symbolApply.onApply = onApply;
5973     }
5974 }
5975 
ParseJsBool(const JSRef<JSVal> & jsValue,bool & result)5976 bool JSViewAbstract::ParseJsBool(const JSRef<JSVal>& jsValue, bool& result)
5977 {
5978     if (!jsValue->IsBoolean() && !jsValue->IsObject()) {
5979         return false;
5980     }
5981 
5982     if (jsValue->IsBoolean()) {
5983         result = jsValue->ToBoolean();
5984         return true;
5985     }
5986 
5987     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
5988     CompleteResourceObject(jsObj);
5989     int32_t resType = jsObj->GetPropertyValue<int32_t>(static_cast<int32_t>(ArkUIIndex::TYPE), UNKNOWN_RESOURCE_TYPE);
5990     if (resType == UNKNOWN_RESOURCE_TYPE) {
5991         return false;
5992     }
5993 
5994     JSRef<JSVal> resId = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::ID));
5995     if (!resId->IsNumber()) {
5996         return false;
5997     }
5998 
5999     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
6000     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
6001     if (!resourceWrapper) {
6002         return false;
6003     }
6004 
6005     auto resIdNum = resId->ToNumber<int32_t>();
6006     if (resIdNum == -1) {
6007         if (!IsGetResourceByName(jsObj)) {
6008             return false;
6009         }
6010         JSRef<JSVal> args = jsObj->GetProperty("params");
6011         if (!args->IsArray()) {
6012             return false;
6013         }
6014         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
6015         auto param = params->GetValueAt(0);
6016         if (resType == static_cast<int32_t>(ResourceType::BOOLEAN)) {
6017             result = resourceWrapper->GetBooleanByName(param->ToString());
6018             return true;
6019         }
6020         return false;
6021     }
6022 
6023     if (resType == static_cast<int32_t>(ResourceType::BOOLEAN)) {
6024         result = resourceWrapper->GetBoolean(resId->ToNumber<uint32_t>());
6025         return true;
6026     }
6027     return false;
6028 }
6029 
ParseJsInteger(const JSRef<JSVal> & jsValue,uint32_t & result)6030 bool JSViewAbstract::ParseJsInteger(const JSRef<JSVal>& jsValue, uint32_t& result)
6031 {
6032     return ParseJsInteger<uint32_t>(jsValue, result);
6033 }
6034 
ParseJsInteger(const JSRef<JSVal> & jsValue,int32_t & result)6035 bool JSViewAbstract::ParseJsInteger(const JSRef<JSVal>& jsValue, int32_t& result)
6036 {
6037     return ParseJsInteger<int32_t>(jsValue, result);
6038 }
6039 
ParseJsIntegerArray(const JSRef<JSVal> & jsValue,std::vector<uint32_t> & result)6040 bool JSViewAbstract::ParseJsIntegerArray(const JSRef<JSVal>& jsValue, std::vector<uint32_t>& result)
6041 {
6042     if (!jsValue->IsArray() && !jsValue->IsObject()) {
6043         return false;
6044     }
6045 
6046     if (jsValue->IsArray()) {
6047         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
6048         for (size_t i = 0; i < array->Length(); i++) {
6049             JSRef<JSVal> value = array->GetValueAt(i);
6050             if (value->IsNumber()) {
6051                 result.emplace_back(value->ToNumber<uint32_t>());
6052             } else if (value->IsObject()) {
6053                 uint32_t singleResInt;
6054                 if (ParseJsInteger(value, singleResInt)) {
6055                     result.emplace_back(singleResInt);
6056                 } else {
6057                     return false;
6058                 }
6059             } else {
6060                 return false;
6061             }
6062         }
6063         return true;
6064     }
6065 
6066     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
6067     CompleteResourceObject(jsObj);
6068     int32_t resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
6069     if (resType == UNKNOWN_RESOURCE_TYPE) {
6070         return false;
6071     }
6072 
6073     JSRef<JSVal> resId = jsObj->GetProperty("id");
6074     if (!resId->IsNumber()) {
6075         return false;
6076     }
6077 
6078     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
6079     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
6080     if (!resourceWrapper) {
6081         return false;
6082     }
6083 
6084     auto resIdNum = resId->ToNumber<int32_t>();
6085     if (resIdNum == -1) {
6086         if (!IsGetResourceByName(jsObj)) {
6087             return false;
6088         }
6089         JSRef<JSVal> args = jsObj->GetProperty("params");
6090         if (!args->IsArray()) {
6091             return false;
6092         }
6093         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
6094         auto param = params->GetValueAt(0);
6095         if (resType == static_cast<int32_t>(ResourceType::INTARRAY)) {
6096             result = resourceWrapper->GetIntArrayByName(param->ToString());
6097             return true;
6098         }
6099         return false;
6100     }
6101 
6102     if (resType == static_cast<int32_t>(ResourceType::INTARRAY)) {
6103         result = resourceWrapper->GetIntArray(resId->ToNumber<uint32_t>());
6104         return true;
6105     }
6106     return false;
6107 }
6108 
ParseJsStrArray(const JSRef<JSVal> & jsValue,std::vector<std::string> & result)6109 bool JSViewAbstract::ParseJsStrArray(const JSRef<JSVal>& jsValue, std::vector<std::string>& result)
6110 {
6111     if (!jsValue->IsArray() && !jsValue->IsObject()) {
6112         return false;
6113     }
6114 
6115     if (jsValue->IsArray()) {
6116         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
6117         for (size_t i = 0; i < array->Length(); i++) {
6118             JSRef<JSVal> value = array->GetValueAt(i);
6119             if (value->IsString()) {
6120                 result.emplace_back(value->ToString());
6121             } else if (value->IsObject()) {
6122                 std::string singleResStr;
6123                 if (ParseJsString(value, singleResStr)) {
6124                     result.emplace_back(singleResStr);
6125                 } else {
6126                     return false;
6127                 }
6128             } else {
6129                 return false;
6130             }
6131         }
6132         return true;
6133     }
6134 
6135     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
6136     CompleteResourceObject(jsObj);
6137     int32_t resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
6138     if (resType == UNKNOWN_RESOURCE_TYPE) {
6139         return false;
6140     }
6141 
6142     JSRef<JSVal> resId = jsObj->GetProperty("id");
6143     if (!resId->IsNumber()) {
6144         return false;
6145     }
6146 
6147     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
6148     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
6149     if (!resourceWrapper) {
6150         return false;
6151     }
6152 
6153     auto resIdNum = resId->ToNumber<int32_t>();
6154     if (resIdNum == -1) {
6155         if (!IsGetResourceByName(jsObj)) {
6156             return false;
6157         }
6158         JSRef<JSVal> args = jsObj->GetProperty("params");
6159         if (!args->IsArray()) {
6160             return false;
6161         }
6162         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
6163         auto param = params->GetValueAt(0);
6164         if (resType == static_cast<int32_t>(ResourceType::STRARRAY)) {
6165             result = resourceWrapper->GetStringArrayByName(param->ToString());
6166             return true;
6167         }
6168         return false;
6169     }
6170 
6171     if (resType == static_cast<int32_t>(ResourceType::STRARRAY)) {
6172         result = resourceWrapper->GetStringArray(resId->ToNumber<uint32_t>());
6173         return true;
6174     }
6175     return false;
6176 }
6177 
IsGetResourceByName(const JSRef<JSObject> & jsObj)6178 bool JSViewAbstract::IsGetResourceByName(const JSRef<JSObject>& jsObj)
6179 {
6180     JSRef<JSVal> resId = jsObj->GetProperty("id");
6181     if (!resId->IsNumber() || resId->ToNumber<int32_t>() != -1) {
6182         return false;
6183     }
6184     JSRef<JSVal> args = jsObj->GetProperty("params");
6185     if (!args->IsArray()) {
6186         return false;
6187     }
6188     JSRef<JSVal> bundleName = jsObj->GetProperty("bundleName");
6189     JSRef<JSVal> moduleName = jsObj->GetProperty("moduleName");
6190     if (!bundleName->IsString() || !moduleName->IsString()) {
6191         return false;
6192     }
6193     JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
6194     if (params->IsEmpty()) {
6195         return false;
6196     }
6197     return true;
6198 }
6199 
ParseSize(const JSCallbackInfo & info)6200 std::pair<CalcDimension, CalcDimension> JSViewAbstract::ParseSize(const JSCallbackInfo& info)
6201 {
6202     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
6203     auto jsVal = info[0];
6204     if (!CheckJSCallbackInfo("ParseSize", jsVal, checkList)) {
6205         return std::pair<CalcDimension, CalcDimension>();
6206     }
6207     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsVal);
6208     CalcDimension width;
6209     CalcDimension height;
6210     if (!ParseJsDimensionVp(jsObj->GetProperty("width"), width) ||
6211         !ParseJsDimensionVp(jsObj->GetProperty("height"), height)) {
6212         return std::pair<CalcDimension, CalcDimension>();
6213     }
6214     return std::pair<CalcDimension, CalcDimension>(width, height);
6215 }
6216 
JsUseAlign(const JSCallbackInfo & info)6217 void JSViewAbstract::JsUseAlign(const JSCallbackInfo& info)
6218 {
6219     if (info.Length() < 2) {
6220         return;
6221     }
6222 
6223     if (!info[0]->IsObject() && !info[1]->IsObject()) {
6224         return;
6225     }
6226 
6227     AlignDeclaration* declaration = JSRef<JSObject>::Cast(info[0])->Unwrap<AlignDeclaration>();
6228     if (declaration == nullptr) {
6229         return;
6230     }
6231 
6232     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
6233     JSRef<JSVal> side = obj->GetProperty("side");
6234     JSRef<JSVal> offset = obj->GetProperty("offset");
6235 
6236     if (!side->IsNumber()) {
6237         return;
6238     }
6239 
6240     auto sideValue = side->ToNumber<int32_t>();
6241 
6242     if (declaration->GetDeclarationType() == AlignDeclaration::DeclarationType::HORIZONTAL) {
6243         if (sideValue < static_cast<int32_t>(AlignDeclaration::Edge::START) ||
6244             sideValue > static_cast<int32_t>(AlignDeclaration::Edge::END)) {
6245             return;
6246         }
6247     } else if (declaration->GetDeclarationType() == AlignDeclaration::DeclarationType::VERTICAL) {
6248         if (sideValue < static_cast<int32_t>(AlignDeclaration::Edge::TOP) ||
6249             sideValue > static_cast<int32_t>(AlignDeclaration::Edge::BASELINE)) {
6250             return;
6251         }
6252     }
6253 
6254     std::optional<CalcDimension> optOffset;
6255     CalcDimension offsetDimension;
6256     if (ParseJsDimensionVp(offset, offsetDimension)) {
6257         optOffset = offsetDimension;
6258     }
6259     ViewAbstractModel::GetInstance()->SetUseAlign(
6260         declaration, static_cast<AlignDeclaration::Edge>(sideValue), optOffset);
6261 }
6262 
JsGridSpan(const JSCallbackInfo & info)6263 void JSViewAbstract::JsGridSpan(const JSCallbackInfo& info)
6264 {
6265     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
6266     auto jsVal = info[0];
6267     if (!CheckJSCallbackInfo("JsGridSpan", jsVal, checkList)) {
6268         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
6269             ViewAbstractModel::GetInstance()->SetGrid(NG::DEFAULT_GRID_SPAN, std::nullopt);
6270         }
6271         return;
6272     }
6273     auto span = jsVal->ToNumber<int32_t>();
6274     ViewAbstractModel::GetInstance()->SetGrid(span, std::nullopt);
6275 }
6276 
JsGridOffset(const JSCallbackInfo & info)6277 void JSViewAbstract::JsGridOffset(const JSCallbackInfo& info)
6278 {
6279     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
6280     auto jsVal = info[0];
6281     if (!CheckJSCallbackInfo("JsGridOffset", jsVal, checkList)) {
6282         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
6283             ViewAbstractModel::GetInstance()->SetGrid(std::nullopt, NG::DEFAULT_GRID_OFFSET);
6284         }
6285         return;
6286     }
6287     auto offset = jsVal->ToNumber<int32_t>();
6288     ViewAbstractModel::GetInstance()->SetGrid(std::nullopt, offset);
6289 }
6290 
ParseSpanAndOffset(const JSRef<JSVal> & val,uint32_t & span,int32_t & offset)6291 static bool ParseSpanAndOffset(const JSRef<JSVal>& val, uint32_t& span, int32_t& offset)
6292 {
6293     // {lg: 4}
6294     if (val->IsNumber()) {
6295         span = val->ToNumber<uint32_t>();
6296         return true;
6297     }
6298 
6299     if (!val->IsObject()) {
6300         return false;
6301     }
6302 
6303     // {lg: {span: 1, offset: 2}}
6304     JSRef<JSObject> obj = JSRef<JSObject>::Cast(val);
6305     span = obj->GetProperty("span")->ToNumber<uint32_t>();
6306     offset = obj->GetProperty("offset")->ToNumber<int32_t>();
6307     return true;
6308 }
6309 
JsUseSizeType(const JSCallbackInfo & info)6310 void JSViewAbstract::JsUseSizeType(const JSCallbackInfo& info)
6311 {
6312     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
6313     auto jsVal = info[0];
6314     if (!CheckJSCallbackInfo("JsUseSizeType", jsVal, checkList)) {
6315         return;
6316     }
6317     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(jsVal);
6318     for (auto values : SCREEN_SIZE_VALUES) {
6319         JSRef<JSVal> val = sizeObj->GetProperty(values.second.c_str());
6320         if (val->IsNull() || val->IsEmpty()) {
6321             continue;
6322         }
6323         uint32_t span = 0;
6324         int32_t offset = 0;
6325         if (ParseSpanAndOffset(val, span, offset)) {
6326             ViewAbstractModel::GetInstance()->SetGrid(span, offset, values.first);
6327         }
6328     }
6329 }
6330 
JsZIndex(const JSCallbackInfo & info)6331 void JSViewAbstract::JsZIndex(const JSCallbackInfo& info)
6332 {
6333     int zIndex = 0;
6334     if (info[0]->IsNumber()) {
6335         zIndex = info[0]->ToNumber<int>();
6336     }
6337 
6338     ViewAbstractModel::GetInstance()->SetZIndex(zIndex);
6339 }
6340 
Pop()6341 void JSViewAbstract::Pop()
6342 {
6343     ViewStackModel::GetInstance()->Pop();
6344 }
6345 
JsSetDraggable(bool draggable)6346 void JSViewAbstract::JsSetDraggable(bool draggable)
6347 {
6348     ViewAbstractModel::GetInstance()->SetDraggable(draggable);
6349 }
6350 
ParseDragPreviewOptions(const JSCallbackInfo & info)6351 NG::DragPreviewOption JSViewAbstract::ParseDragPreviewOptions (const JSCallbackInfo& info)
6352 {
6353     NG::DragPreviewOption previewOption;
6354     if (!info[0]->IsObject()) {
6355         return previewOption;
6356     }
6357     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
6358     auto mode = obj->GetProperty("mode");
6359     bool isAuto = true;
6360     if (mode->IsNumber()) {
6361         ParseDragPreviewMode(previewOption, mode->ToNumber<int>(), isAuto);
6362     } else if (mode->IsArray()) {
6363         JSRef<JSArray> array = JSRef<JSArray>::Cast(mode);
6364         for (size_t i = 0; i < array->Length(); i++) {
6365             JSRef<JSVal> value = array->GetValueAt(i);
6366             if (value->IsNumber()) {
6367                 ParseDragPreviewMode(previewOption, value->ToNumber<int>(), isAuto);
6368             }
6369             if (isAuto) {
6370                 break;
6371             }
6372         }
6373     }
6374 
6375     JSViewAbstract::SetDragNumberBadge(info, previewOption);
6376 
6377     if (info.Length() > 1 && info[1]->IsObject()) {
6378         JSRef<JSObject> interObj = JSRef<JSObject>::Cast(info[1]);
6379         auto multiSelection = interObj->GetProperty("isMultiSelectionEnabled");
6380         if (multiSelection->IsBoolean()) {
6381             previewOption.isMultiSelectionEnabled = multiSelection->ToBoolean();
6382         }
6383         auto defaultAnimation = interObj->GetProperty("defaultAnimationBeforeLifting");
6384         if (defaultAnimation->IsBoolean()) {
6385             previewOption.defaultAnimationBeforeLifting = defaultAnimation->ToBoolean();
6386         }
6387         auto dragPreview = interObj->GetProperty("isDragPreviewEnabled");
6388         if (dragPreview->IsBoolean()) {
6389             previewOption.isDragPreviewEnabled = dragPreview->ToBoolean();
6390         }
6391     }
6392 
6393     JSViewAbstract::SetDragPreviewOptionApply(info, previewOption);
6394 
6395     return previewOption;
6396 }
6397 
JsSetDragPreviewOptions(const JSCallbackInfo & info)6398 void JSViewAbstract::JsSetDragPreviewOptions(const JSCallbackInfo& info)
6399 {
6400     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
6401     auto jsVal = info[0];
6402     if (!CheckJSCallbackInfo("JsSetDragPreviewOptions", jsVal, checkList)) {
6403         return;
6404     }
6405     NG::DragPreviewOption previewOption = ParseDragPreviewOptions(info);
6406     ViewAbstractModel::GetInstance()->SetDragPreviewOptions(previewOption);
6407 }
6408 
JsOnDragStart(const JSCallbackInfo & info)6409 void JSViewAbstract::JsOnDragStart(const JSCallbackInfo& info)
6410 {
6411     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
6412     auto jsVal = info[0];
6413     if (!CheckJSCallbackInfo("JsOnDragStart", jsVal, checkList)) {
6414         return;
6415     }
6416 
6417     RefPtr<JsDragFunction> jsOnDragStartFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(jsVal));
6418 
6419     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
6420     auto onDragStart = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragStartFunc), node = frameNode](
6421                            const RefPtr<DragEvent>& info, const std::string& extraParams) -> NG::DragDropBaseInfo {
6422         NG::DragDropBaseInfo dragDropInfo;
6423         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, dragDropInfo);
6424         PipelineContext::SetCallBackNode(node);
6425         auto ret = func->Execute(info, extraParams);
6426         if (!ret->IsObject()) {
6427             return dragDropInfo;
6428         }
6429 
6430         dragDropInfo.node = ParseDragNode(ret);
6431         auto builderObj = JSRef<JSObject>::Cast(ret);
6432 #if defined(PIXEL_MAP_SUPPORTED)
6433         auto pixmap = builderObj->GetProperty("pixelMap");
6434         dragDropInfo.pixelMap = CreatePixelMapFromNapiValue(pixmap);
6435 #endif
6436         auto extraInfo = builderObj->GetProperty("extraInfo");
6437         ParseJsString(extraInfo, dragDropInfo.extraInfo);
6438         return dragDropInfo;
6439     };
6440     ViewAbstractModel::GetInstance()->SetOnDragStart(std::move(onDragStart));
6441 }
6442 
ParseAndUpdateDragItemInfo(const JSRef<JSVal> & info,NG::DragDropBaseInfo & dragInfo)6443 bool JSViewAbstract::ParseAndUpdateDragItemInfo(const JSRef<JSVal>& info, NG::DragDropBaseInfo& dragInfo)
6444 {
6445     auto node = ParseDragNode(info);
6446     if (!node) {
6447         return false;
6448     }
6449     dragInfo.node = node;
6450     return true;
6451 }
6452 
ParseDragNode(const JSRef<JSVal> & info)6453 RefPtr<AceType> JSViewAbstract::ParseDragNode(const JSRef<JSVal>& info)
6454 {
6455     auto builderFunc = ParseDragStartBuilderFunc(info);
6456     if (!builderFunc) {
6457         return nullptr;
6458     }
6459     // use another VSP instance while executing the builder function
6460     ViewStackModel::GetInstance()->NewScope();
6461     {
6462         ACE_SCORING_EVENT("onDragStart.builder");
6463         builderFunc->Execute();
6464     }
6465 
6466     return ViewStackModel::GetInstance()->Finish();
6467 }
6468 
JsOnDragEnter(const JSCallbackInfo & info)6469 void JSViewAbstract::JsOnDragEnter(const JSCallbackInfo& info)
6470 {
6471     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
6472     auto jsVal = info[0];
6473     if (!CheckJSCallbackInfo("JsOnDragEnter", jsVal, checkList)) {
6474         return;
6475     }
6476     RefPtr<JsDragFunction> jsOnDragEnterFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(jsVal));
6477     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
6478     auto onDragEnter = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEnterFunc), node = frameNode](
6479                            const RefPtr<OHOS::Ace::DragEvent>& info, const std::string& extraParams) {
6480         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6481         ACE_SCORING_EVENT("onDragEnter");
6482         PipelineContext::SetCallBackNode(node);
6483         func->Execute(info, extraParams);
6484     };
6485 
6486     ViewAbstractModel::GetInstance()->SetOnDragEnter(std::move(onDragEnter));
6487 }
6488 
JsOnDragEnd(const JSCallbackInfo & info)6489 void JSViewAbstract::JsOnDragEnd(const JSCallbackInfo& info)
6490 {
6491     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
6492     auto jsVal = info[0];
6493     if (!CheckJSCallbackInfo("JsOnDragEnd", jsVal, checkList)) {
6494         return;
6495     }
6496     RefPtr<JsDragFunction> jsOnDragEndFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(jsVal));
6497     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
6498     auto onDragEnd = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEndFunc), node = frameNode](
6499                          const RefPtr<OHOS::Ace::DragEvent>& info) {
6500         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6501         ACE_SCORING_EVENT("onDragEnd");
6502         auto extraParams = JsonUtil::Create(true);
6503         PipelineContext::SetCallBackNode(node);
6504         func->Execute(info, extraParams->ToString());
6505     };
6506 
6507     ViewAbstractModel::GetInstance()->SetOnDragEnd(std::move(onDragEnd));
6508 }
6509 
JsOnDragMove(const JSCallbackInfo & info)6510 void JSViewAbstract::JsOnDragMove(const JSCallbackInfo& info)
6511 {
6512     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
6513     auto jsVal = info[0];
6514     if (!CheckJSCallbackInfo("JsOnDragMove", jsVal, checkList)) {
6515         return;
6516     }
6517     RefPtr<JsDragFunction> jsOnDragMoveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(jsVal));
6518     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
6519     auto onDragMove = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragMoveFunc), node = frameNode](
6520                           const RefPtr<OHOS::Ace::DragEvent>& info, const std::string& extraParams) {
6521         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6522         ACE_SCORING_EVENT("onDragMove");
6523         PipelineContext::SetCallBackNode(node);
6524         func->Execute(info, extraParams);
6525     };
6526 
6527     ViewAbstractModel::GetInstance()->SetOnDragMove(std::move(onDragMove));
6528 }
6529 
JsOnDragLeave(const JSCallbackInfo & info)6530 void JSViewAbstract::JsOnDragLeave(const JSCallbackInfo& info)
6531 {
6532     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
6533     auto jsVal = info[0];
6534     if (!CheckJSCallbackInfo("JsOnDragLeave", jsVal, checkList)) {
6535         return;
6536     }
6537     RefPtr<JsDragFunction> jsOnDragLeaveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(jsVal));
6538     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
6539     auto onDragLeave = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragLeaveFunc), node = frameNode](
6540                            const RefPtr<OHOS::Ace::DragEvent>& info, const std::string& extraParams) {
6541         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6542         ACE_SCORING_EVENT("onDragLeave");
6543         PipelineContext::SetCallBackNode(node);
6544         func->Execute(info, extraParams);
6545     };
6546 
6547     ViewAbstractModel::GetInstance()->SetOnDragLeave(std::move(onDragLeave));
6548 }
6549 
JsOnDrop(const JSCallbackInfo & info)6550 void JSViewAbstract::JsOnDrop(const JSCallbackInfo& info)
6551 {
6552     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
6553     auto jsVal = info[0];
6554     if (!CheckJSCallbackInfo("JsOnDrop", jsVal, checkList)) {
6555         return;
6556     }
6557     RefPtr<JsDragFunction> jsOnDropFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(jsVal));
6558     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
6559     auto onDrop = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDropFunc), node = frameNode](
6560                       const RefPtr<OHOS::Ace::DragEvent>& info, const std::string& extraParams) {
6561         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6562         ACE_SCORING_EVENT("onDrop");
6563         PipelineContext::SetCallBackNode(node);
6564         func->Execute(info, extraParams);
6565     };
6566 
6567     ViewAbstractModel::GetInstance()->SetOnDrop(std::move(onDrop));
6568 }
6569 
JsOnAreaChange(const JSCallbackInfo & info)6570 void JSViewAbstract::JsOnAreaChange(const JSCallbackInfo& info)
6571 {
6572     auto jsVal = info[0];
6573     if (jsVal->IsUndefined() && IsDisableEventVersion()) {
6574         ViewAbstractModel::GetInstance()->DisableOnAreaChange();
6575         return;
6576     }
6577     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
6578     if (!CheckJSCallbackInfo("JsOnAreaChange", jsVal, checkList)) {
6579         return;
6580     }
6581     auto jsOnAreaChangeFunction = AceType::MakeRefPtr<JsOnAreaChangeFunction>(JSRef<JSFunc>::Cast(jsVal));
6582 
6583     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
6584     auto onAreaChanged = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAreaChangeFunction),
6585                              node = frameNode](
6586                              const Rect& oldRect, const Offset& oldOrigin, const Rect& rect, const Offset& origin) {
6587         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6588         ACE_SCORING_EVENT("onAreaChange");
6589         PipelineContext::SetCallBackNode(node);
6590         func->Execute(oldRect, oldOrigin, rect, origin);
6591     };
6592     ViewAbstractModel::GetInstance()->SetOnAreaChanged(std::move(onAreaChanged));
6593 }
6594 
JsOnSizeChange(const JSCallbackInfo & info)6595 void JSViewAbstract::JsOnSizeChange(const JSCallbackInfo& info)
6596 {
6597     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
6598     auto jsVal = info[0];
6599     if (!CheckJSCallbackInfo("JsOnSizeChange", jsVal, checkList)) {
6600         return;
6601     }
6602     auto jsOnSizeChangeFunction = AceType::MakeRefPtr<JsOnSizeChangeFunction>(JSRef<JSFunc>::Cast(jsVal));
6603 
6604     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
6605     auto onSizeChanged = [execCtx = info.GetExecutionContext(), func = std::move(jsOnSizeChangeFunction),
6606                             node = frameNode](const NG::RectF& oldRect, const NG::RectF& rect) {
6607         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6608         ACE_SCORING_EVENT("onSizeChange");
6609         PipelineContext::SetCallBackNode(node);
6610         func->Execute(oldRect, rect);
6611     };
6612     ViewAbstractModel::GetInstance()->SetOnSizeChanged(std::move(onSizeChanged));
6613 }
6614 
6615 #ifndef WEARABLE_PRODUCT
JsBindPopup(const JSCallbackInfo & info)6616 void JSViewAbstract::JsBindPopup(const JSCallbackInfo& info)
6617 {
6618     if (info.Length() < 2) {
6619         return;
6620     }
6621     if ((!info[0]->IsBoolean() && !info[0]->IsObject()) || !info[1]->IsObject()) {
6622         return;
6623     }
6624     auto popupParam = AceType::MakeRefPtr<PopupParam>();
6625     // Set IsShow to popupParam
6626     if (info[0]->IsBoolean()) {
6627         popupParam->SetIsShow(info[0]->ToBoolean());
6628     } else {
6629         JSRef<JSObject> showObj = JSRef<JSObject>::Cast(info[0]);
6630         auto callback = ParseDoubleBindCallback(info, showObj);
6631         popupParam->SetOnStateChange(std::move(callback));
6632         popupParam->SetIsShow(showObj->GetProperty("value")->ToBoolean());
6633     }
6634     // Set popup to popupParam
6635     auto popupObj = JSRef<JSObject>::Cast(info[1]);
6636     SetPopupDismiss(info, popupObj, popupParam);
6637     if (popupObj->GetProperty("message")->IsString()) {
6638         ParsePopupParam(info, popupObj, popupParam); // Parse PopupOptions param
6639         ViewAbstractModel::GetInstance()->BindPopup(popupParam, nullptr);
6640     } else if (!popupObj->GetProperty("builder").IsEmpty()) {
6641         ParseCustomPopupParam(info, popupObj, popupParam); // Parse CustomPopupOptions param
6642         auto builderValue = popupObj->GetProperty("builder");
6643         auto builder = builderValue;
6644         if (!builderValue->IsObject()) {
6645             return;
6646         }
6647         if (!builderValue->IsFunction()) {
6648             JSRef<JSObject> builderObj;
6649             builderObj = JSRef<JSObject>::Cast(builderValue);
6650             builder = builderObj->GetProperty("builder");
6651             if (!builder->IsFunction()) {
6652                 return;
6653             }
6654         }
6655         if (popupParam->IsShow() && !IsPopupCreated()) {
6656             auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
6657             CHECK_NULL_VOID(builderFunc);
6658             ViewStackModel::GetInstance()->NewScope();
6659             builderFunc->Execute();
6660             auto customNode = ViewStackModel::GetInstance()->Finish();
6661             ViewAbstractModel::GetInstance()->BindPopup(popupParam, customNode);
6662         } else {
6663             ViewAbstractModel::GetInstance()->BindPopup(popupParam, nullptr);
6664         }
6665     } else {
6666         return;
6667     }
6668 }
6669 
SetPopupDismiss(const JSCallbackInfo & info,const JSRef<JSObject> & popupObj,const RefPtr<PopupParam> & popupParam)6670 void JSViewAbstract::SetPopupDismiss(
6671     const JSCallbackInfo& info, const JSRef<JSObject>& popupObj, const RefPtr<PopupParam>& popupParam)
6672 {
6673     auto onWillDismissFunc = popupObj->GetProperty("onWillDismiss");
6674     if (onWillDismissFunc->IsBoolean()) {
6675         bool onWillDismissBool = onWillDismissFunc->ToBoolean();
6676         popupParam->SetInteractiveDismiss(onWillDismissBool);
6677         popupParam->SetOnWillDismiss(nullptr);
6678         if (onWillDismissBool) {
6679             TAG_LOGI(AceLogTag::ACE_FORM, "popup register onWillDismiss");
6680         }
6681     } else if (onWillDismissFunc->IsFunction()) {
6682         auto onWillDismissCallback = ParsePopupCallback(info, popupObj);
6683         popupParam->SetOnWillDismiss(std::move(onWillDismissCallback));
6684         popupParam->SetInteractiveDismiss(true);
6685         if (onWillDismissCallback != nullptr) {
6686             TAG_LOGI(AceLogTag::ACE_FORM, "popup register onWillDismiss");
6687         }
6688     }
6689 }
6690 
ParsePopupCallback(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)6691 PopupOnWillDismiss JSViewAbstract::ParsePopupCallback(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
6692 {
6693     auto onWillDismissFunc = paramObj->GetProperty("onWillDismiss");
6694     if (!onWillDismissFunc->IsFunction()) {
6695         return PopupOnWillDismiss();
6696     }
6697     RefPtr<JsFunction> jsFunc =
6698         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillDismissFunc));
6699     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
6700     auto onWillDismiss = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
6701                           node = frameNode](int32_t reason) {
6702         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6703         ACE_SCORING_EVENT("Bindpopup.dismiss");
6704         PipelineContext::SetCallBackNode(node);
6705 
6706         JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
6707         objectTemplate->SetInternalFieldCount(ON_WILL_DISMISS_FIELD_COUNT);
6708         JSRef<JSObject> dismissObj = objectTemplate->NewInstance();
6709         dismissObj->SetPropertyObject("dismiss", JSRef<JSFunc>::New<FunctionCallback>(JSViewAbstract::JsDismissPopup));
6710         dismissObj->SetProperty<int32_t>("reason", reason);
6711         JSRef<JSVal> newJSVal = JSRef<JSObject>::Cast(dismissObj);
6712 
6713         func->ExecuteJS(1, &newJSVal);
6714     };
6715     return onWillDismiss;
6716 }
6717 
JsDismissPopup(panda::JsiRuntimeCallInfo * runtimeCallInfo)6718 panda::Local<panda::JSValueRef> JSViewAbstract::JsDismissPopup(panda::JsiRuntimeCallInfo* runtimeCallInfo)
6719 {
6720     ViewAbstractModel::GetInstance()->DismissPopup();
6721     return JSValueRef::Undefined(runtimeCallInfo->GetVM());
6722 }
6723 #endif
6724 
ParseDialogCallback(const JSRef<JSObject> & paramObj,std::function<void (const int32_t & info)> & onWillDismiss)6725 void JSViewAbstract::ParseDialogCallback(const JSRef<JSObject>& paramObj,
6726     std::function<void(const int32_t& info)>& onWillDismiss)
6727 {
6728     auto onWillDismissFunc = paramObj->GetProperty("onWillDismiss");
6729     if (onWillDismissFunc->IsFunction()) {
6730         auto jsFunc =
6731             AceType::MakeRefPtr<JsWeakFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillDismissFunc));
6732         onWillDismiss = [func = std::move(jsFunc)](const int32_t& info) {
6733             JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
6734             objectTemplate->SetInternalFieldCount(ON_WILL_DISMISS_FIELD_COUNT);
6735             JSRef<JSObject> dismissObj = objectTemplate->NewInstance();
6736             dismissObj->SetPropertyObject(
6737                 "dismiss", JSRef<JSFunc>::New<FunctionCallback>(JSViewAbstract::JsDismissDialog));
6738             dismissObj->SetProperty<int32_t>("reason", info);
6739             JSRef<JSVal> newJSVal = JSRef<JSObject>::Cast(dismissObj);
6740             func->ExecuteJS(1, &newJSVal);
6741         };
6742     }
6743 }
6744 
JsDismissDialog(panda::JsiRuntimeCallInfo * runtimeCallInfo)6745 panda::Local<panda::JSValueRef> JSViewAbstract::JsDismissDialog(panda::JsiRuntimeCallInfo* runtimeCallInfo)
6746 {
6747     ViewAbstractModel::GetInstance()->DismissDialog();
6748     return JSValueRef::Undefined(runtimeCallInfo->GetVM());
6749 }
6750 
JsLinearGradient(const JSCallbackInfo & info)6751 void JSViewAbstract::JsLinearGradient(const JSCallbackInfo& info)
6752 {
6753     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
6754     auto jsVal = info[0];
6755     if (!CheckJSCallbackInfo("LinearGradient", jsVal, checkList)) {
6756         NG::Gradient newGradient;
6757         newGradient.CreateGradientWithType(NG::GradientType::LINEAR);
6758         ViewAbstractModel::GetInstance()->SetLinearGradient(newGradient);
6759         return;
6760     }
6761     NG::Gradient newGradient;
6762     NewJsLinearGradient(info, newGradient);
6763     ViewAbstractModel::GetInstance()->SetLinearGradient(newGradient);
6764 }
6765 
NewJsLinearGradient(const JSCallbackInfo & info,NG::Gradient & newGradient)6766 void JSViewAbstract::NewJsLinearGradient(const JSCallbackInfo& info, NG::Gradient& newGradient)
6767 {
6768     if (!info[0]->IsObject()) {
6769         return;
6770     }
6771     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
6772     newGradient.CreateGradientWithType(NG::GradientType::LINEAR);
6773     // angle
6774     std::optional<float> degree;
6775     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
6776         GetJsAngle(static_cast<int32_t>(ArkUIIndex::ANGLE), jsObj, degree);
6777     } else {
6778         GetJsAngleWithDefault(static_cast<int32_t>(ArkUIIndex::ANGLE), jsObj, degree, 180.0f);
6779     }
6780     if (degree) {
6781         newGradient.GetLinearGradient()->angle = CalcDimension(degree.value(), DimensionUnit::PX);
6782         degree.reset();
6783     }
6784     // direction
6785     auto direction = static_cast<GradientDirection>(
6786         jsObj->GetPropertyValue<int32_t>("direction", static_cast<int32_t>(GradientDirection::NONE)));
6787     switch (direction) {
6788         case GradientDirection::LEFT:
6789             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
6790             break;
6791         case GradientDirection::RIGHT:
6792             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
6793             break;
6794         case GradientDirection::TOP:
6795             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
6796             break;
6797         case GradientDirection::BOTTOM:
6798             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
6799             break;
6800         case GradientDirection::LEFT_TOP:
6801             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
6802             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
6803             break;
6804         case GradientDirection::LEFT_BOTTOM:
6805             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
6806             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
6807             break;
6808         case GradientDirection::RIGHT_TOP:
6809             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
6810             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
6811             break;
6812         case GradientDirection::RIGHT_BOTTOM:
6813             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
6814             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
6815             break;
6816         case GradientDirection::NONE:
6817         case GradientDirection::START_TO_END:
6818         case GradientDirection::END_TO_START:
6819         default:
6820             break;
6821     }
6822     auto repeating = jsObj->GetPropertyValue<bool>("repeating", false);
6823     newGradient.SetRepeat(repeating);
6824     NewGetJsGradientColorStops(newGradient, jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::COLORS)));
6825 }
6826 
JsRadialGradient(const JSCallbackInfo & info)6827 void JSViewAbstract::JsRadialGradient(const JSCallbackInfo& info)
6828 {
6829     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
6830     auto jsVal = info[0];
6831     if (!CheckJSCallbackInfo("JsRadialGradient", jsVal, checkList)) {
6832         NG::Gradient newGradient;
6833         newGradient.CreateGradientWithType(NG::GradientType::RADIAL);
6834         ViewAbstractModel::GetInstance()->SetRadialGradient(newGradient);
6835         return;
6836     }
6837     NG::Gradient newGradient;
6838     NewJsRadialGradient(info, newGradient);
6839     ViewAbstractModel::GetInstance()->SetRadialGradient(newGradient);
6840 }
6841 
NewJsRadialGradient(const JSCallbackInfo & info,NG::Gradient & newGradient)6842 void JSViewAbstract::NewJsRadialGradient(const JSCallbackInfo& info, NG::Gradient& newGradient)
6843 {
6844     JSRef<JSVal> arg = info[0];
6845     if (!arg->IsObject()) {
6846         return;
6847     }
6848     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(arg);
6849     newGradient.CreateGradientWithType(NG::GradientType::RADIAL);
6850     // center
6851     JSRef<JSVal> center = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::CENTER));
6852     if (center->IsArray() && JSRef<JSArray>::Cast(center)->Length() == 2) {
6853         CalcDimension value;
6854         JSRef<JSArray> centerArray = JSRef<JSArray>::Cast(center);
6855         if (ParseJsDimensionVp(centerArray->GetValueAt(0), value)) {
6856             newGradient.GetRadialGradient()->radialCenterX = CalcDimension(value);
6857             if (value.Unit() == DimensionUnit::PERCENT) {
6858                 // [0,1] -> [0, 100]
6859                 newGradient.GetRadialGradient()->radialCenterX =
6860                     CalcDimension(value.Value() * 100.0, DimensionUnit::PERCENT);
6861             }
6862         }
6863         if (ParseJsDimensionVp(centerArray->GetValueAt(1), value)) {
6864             newGradient.GetRadialGradient()->radialCenterY = CalcDimension(value);
6865             if (value.Unit() == DimensionUnit::PERCENT) {
6866                 // [0,1] -> [0, 100]
6867                 newGradient.GetRadialGradient()->radialCenterY =
6868                     CalcDimension(value.Value() * 100.0, DimensionUnit::PERCENT);
6869             }
6870         }
6871     }
6872     // radius
6873     CalcDimension radius;
6874     if (ParseJsDimensionVp(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::RADIUS)), radius)) {
6875         newGradient.GetRadialGradient()->radialVerticalSize = CalcDimension(radius);
6876         newGradient.GetRadialGradient()->radialHorizontalSize = CalcDimension(radius);
6877     }
6878     // repeating
6879     auto repeating = jsObj->GetPropertyValue<bool>("repeating", false);
6880     newGradient.SetRepeat(repeating);
6881     // color stops
6882     NewGetJsGradientColorStops(newGradient, jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::COLORS)));
6883 }
6884 
JsSweepGradient(const JSCallbackInfo & info)6885 void JSViewAbstract::JsSweepGradient(const JSCallbackInfo& info)
6886 {
6887     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
6888     auto jsVal = info[0];
6889     if (!CheckJSCallbackInfo("JsSweepGradient", jsVal, checkList)) {
6890         NG::Gradient newGradient;
6891         newGradient.CreateGradientWithType(NG::GradientType::SWEEP);
6892         ViewAbstractModel::GetInstance()->SetSweepGradient(newGradient);
6893         return;
6894     }
6895 
6896     NG::Gradient newGradient;
6897     NewJsSweepGradient(info, newGradient);
6898     ViewAbstractModel::GetInstance()->SetSweepGradient(newGradient);
6899 }
6900 
NewJsSweepGradient(const JSCallbackInfo & info,NG::Gradient & newGradient)6901 void JSViewAbstract::NewJsSweepGradient(const JSCallbackInfo& info, NG::Gradient& newGradient)
6902 {
6903     JSRef<JSVal> arg = info[0];
6904     if (!arg->IsObject()) {
6905         return;
6906     }
6907     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(arg);
6908     newGradient.CreateGradientWithType(NG::GradientType::SWEEP);
6909     // center
6910     JSRef<JSVal> center = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::CENTER));
6911     if (center->IsArray() && JSRef<JSArray>::Cast(center)->Length() == 2) {
6912         CalcDimension value;
6913         JSRef<JSArray> centerArray = JSRef<JSArray>::Cast(center);
6914         if (ParseJsDimensionVp(centerArray->GetValueAt(0), value)) {
6915             newGradient.GetSweepGradient()->centerX = CalcDimension(value);
6916             if (value.Unit() == DimensionUnit::PERCENT) {
6917                 // [0,1] -> [0, 100]
6918                 newGradient.GetSweepGradient()->centerX = CalcDimension(value.Value() * 100.0, DimensionUnit::PERCENT);
6919             }
6920         }
6921         if (ParseJsDimensionVp(centerArray->GetValueAt(1), value)) {
6922             newGradient.GetSweepGradient()->centerY = CalcDimension(value);
6923             if (value.Unit() == DimensionUnit::PERCENT) {
6924                 // [0,1] -> [0, 100]
6925                 newGradient.GetSweepGradient()->centerY = CalcDimension(value.Value() * 100.0, DimensionUnit::PERCENT);
6926             }
6927         }
6928     }
6929     // start, end and rotation
6930     ParseSweepGradientPartly(jsObj, newGradient);
6931     // repeating
6932     auto repeating = jsObj->GetPropertyValue<bool>("repeating", false);
6933     newGradient.SetRepeat(repeating);
6934     // color stops
6935     NewGetJsGradientColorStops(newGradient, jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::COLORS)));
6936 }
6937 
ParseSweepGradientPartly(const JSRef<JSObject> & obj,NG::Gradient & newGradient)6938 void JSViewAbstract::ParseSweepGradientPartly(const JSRef<JSObject>& obj, NG::Gradient& newGradient)
6939 {
6940     std::optional<float> degreeStart;
6941     std::optional<float> degreeEnd;
6942     std::optional<float> degreeRotation;
6943     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
6944         GetJsAngle(static_cast<int32_t>(ArkUIIndex::START), obj, degreeStart);
6945         GetJsAngle(static_cast<int32_t>(ArkUIIndex::END), obj, degreeEnd);
6946         GetJsAngle(static_cast<int32_t>(ArkUIIndex::ROTATION), obj, degreeRotation);
6947     } else {
6948         GetJsAngleWithDefault(static_cast<int32_t>(ArkUIIndex::START), obj, degreeStart, 0.0f);
6949         GetJsAngleWithDefault(static_cast<int32_t>(ArkUIIndex::END), obj, degreeEnd, 0.0f);
6950         GetJsAngleWithDefault(static_cast<int32_t>(ArkUIIndex::ROTATION), obj, degreeRotation, 0.0f);
6951     }
6952     if (degreeStart) {
6953         CheckAngle(degreeStart);
6954         newGradient.GetSweepGradient()->startAngle = CalcDimension(degreeStart.value(), DimensionUnit::PX);
6955     }
6956     if (degreeEnd) {
6957         CheckAngle(degreeEnd);
6958         newGradient.GetSweepGradient()->endAngle = CalcDimension(degreeEnd.value(), DimensionUnit::PX);
6959     }
6960     if (degreeRotation) {
6961         CheckAngle(degreeRotation);
6962         newGradient.GetSweepGradient()->rotation = CalcDimension(degreeRotation.value(), DimensionUnit::PX);
6963     }
6964 }
6965 
JsMotionPath(const JSCallbackInfo & info)6966 void JSViewAbstract::JsMotionPath(const JSCallbackInfo& info)
6967 {
6968     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
6969     auto jsVal = info[0];
6970     if (!CheckJSCallbackInfo("JsMotionPath", jsVal, checkList)) {
6971         ViewAbstractModel::GetInstance()->SetMotionPath(MotionPathOption());
6972         return;
6973     }
6974     MotionPathOption motionPathOption;
6975     if (ParseMotionPath(jsVal, motionPathOption)) {
6976         ViewAbstractModel::GetInstance()->SetMotionPath(motionPathOption);
6977     } else {
6978         TAG_LOGI(AceLogTag::ACE_ANIMATION, "Parse animation motionPath failed. %{public}s", jsVal->ToString().c_str());
6979         ViewAbstractModel::GetInstance()->SetMotionPath(MotionPathOption());
6980     }
6981 }
6982 
JsShadow(const JSCallbackInfo & info)6983 void JSViewAbstract::JsShadow(const JSCallbackInfo& info)
6984 {
6985     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT, JSCallbackInfoType::NUMBER };
6986     auto jsVal = info[0];
6987     if (!CheckJSCallbackInfo("JsShadow", jsVal, checkList)) {
6988         Shadow shadow;
6989         std::vector<Shadow> shadows { shadow };
6990         ViewAbstractModel::GetInstance()->SetBackShadow(shadows);
6991         return;
6992     }
6993     Shadow shadow;
6994     if (!ParseShadowProps(jsVal, shadow)) {
6995         info.ReturnSelf();
6996         return;
6997     }
6998     std::vector<Shadow> shadows { shadow };
6999     ViewAbstractModel::GetInstance()->SetBackShadow(shadows);
7000 }
7001 
JsBlendMode(const JSCallbackInfo & info)7002 void JSViewAbstract::JsBlendMode(const JSCallbackInfo& info)
7003 {
7004     if (info.Length() == 0) {
7005         return;
7006     }
7007     BlendMode blendMode = BlendMode::NONE;
7008     BlendApplyType blendApplyType = BlendApplyType::FAST;
7009     // for backward compatible, we temporary add a magic number to trigger offscreen, will remove soon
7010     constexpr int BACKWARD_COMPAT_MAGIC_NUMBER_OFFSCREEN = 1000;
7011     constexpr int BACKWARD_COMPAT_SOURCE_IN_NUMBER_OFFSCREEN = 2000;
7012     constexpr int BACKWARD_COMPAT_DESTINATION_IN_NUMBER_OFFSCREEN = 3000;
7013     constexpr int BACKWARD_COMPAT_MAGIC_NUMBER_SRC_IN = 5000;
7014     if (info[0]->IsNumber()) {
7015         auto blendModeNum = info[0]->ToNumber<int32_t>();
7016         if (blendModeNum >= 0 && blendModeNum < static_cast<int>(BlendMode::MAX)) {
7017             blendMode = static_cast<BlendMode>(blendModeNum);
7018         } else if (blendModeNum == BACKWARD_COMPAT_MAGIC_NUMBER_OFFSCREEN) {
7019             // backward compatibility code, will remove soon
7020             blendMode = BlendMode::SRC_OVER;
7021             blendApplyType = BlendApplyType::OFFSCREEN;
7022         } else if (blendModeNum == BACKWARD_COMPAT_SOURCE_IN_NUMBER_OFFSCREEN) {
7023             // backward compatibility code, will remove soon
7024             blendMode = BlendMode::SRC_IN;
7025             blendApplyType = BlendApplyType::OFFSCREEN;
7026         } else if (blendModeNum == BACKWARD_COMPAT_DESTINATION_IN_NUMBER_OFFSCREEN) {
7027             // backward compatibility code, will remove soon
7028             blendMode = BlendMode::DST_IN;
7029             blendApplyType = BlendApplyType::OFFSCREEN;
7030         } else if (blendModeNum == BACKWARD_COMPAT_MAGIC_NUMBER_SRC_IN) {
7031             blendMode = BlendMode::BACK_COMPAT_SOURCE_IN;
7032         }
7033     }
7034     if (info.Length() >= PARAMETER_LENGTH_SECOND && info[1]->IsNumber()) {
7035         auto blendApplyTypeNum = info[1]->ToNumber<int32_t>();
7036         if (blendApplyTypeNum >= 0 && blendApplyTypeNum < static_cast<int>(BlendApplyType::MAX)) {
7037             blendApplyType = static_cast<BlendApplyType>(blendApplyTypeNum);
7038         }
7039     }
7040     ViewAbstractModel::GetInstance()->SetBlendMode(blendMode);
7041     ViewAbstractModel::GetInstance()->SetBlendApplyType(blendApplyType);
7042 }
7043 
JsAdvancedBlendMode(const JSCallbackInfo & info)7044 void JSViewAbstract::JsAdvancedBlendMode(const JSCallbackInfo& info)
7045 {
7046     if (info.Length() == 0) {
7047         return;
7048     }
7049     BlendMode blendMode = BlendMode::NONE;
7050     BlendApplyType blendApplyType = BlendApplyType::FAST;
7051     // for backward compatible, we temporary add a magic number to trigger offscreen, will remove soon
7052     constexpr int BACKWARD_COMPAT_MAGIC_NUMBER_OFFSCREEN = 1000;
7053     constexpr int BACKWARD_COMPAT_SOURCE_IN_NUMBER_OFFSCREEN = 2000;
7054     constexpr int BACKWARD_COMPAT_DESTINATION_IN_NUMBER_OFFSCREEN = 3000;
7055     constexpr int BACKWARD_COMPAT_MAGIC_NUMBER_SRC_IN = 5000;
7056     if (info[0]->IsNumber()) {
7057         auto blendModeNum = info[0]->ToNumber<int32_t>();
7058         if (blendModeNum >= 0 && blendModeNum < static_cast<int>(BlendMode::MAX)) {
7059             blendMode = static_cast<BlendMode>(blendModeNum);
7060         } else if (blendModeNum == BACKWARD_COMPAT_MAGIC_NUMBER_OFFSCREEN) {
7061             // backward compatibility code, will remove soon
7062             blendMode = BlendMode::SRC_OVER;
7063             blendApplyType = BlendApplyType::OFFSCREEN;
7064         } else if (blendModeNum == BACKWARD_COMPAT_SOURCE_IN_NUMBER_OFFSCREEN) {
7065             // backward compatibility code, will remove soon
7066             blendMode = BlendMode::SRC_IN;
7067             blendApplyType = BlendApplyType::OFFSCREEN;
7068         } else if (blendModeNum == BACKWARD_COMPAT_DESTINATION_IN_NUMBER_OFFSCREEN) {
7069             // backward compatibility code, will remove soon
7070             blendMode = BlendMode::DST_IN;
7071             blendApplyType = BlendApplyType::OFFSCREEN;
7072         } else if (blendModeNum == BACKWARD_COMPAT_MAGIC_NUMBER_SRC_IN) {
7073             blendMode = BlendMode::BACK_COMPAT_SOURCE_IN;
7074         }
7075     } else if (info[0]->IsObject()) {
7076         auto blender = CreateRSBrightnessBlenderFromNapiValue(info[0]);
7077         ViewAbstractModel::GetInstance()->SetBrightnessBlender(blender);
7078     }
7079     if (info.Length() >= PARAMETER_LENGTH_SECOND && info[1]->IsNumber()) {
7080         auto blendApplyTypeNum = info[1]->ToNumber<int32_t>();
7081         if (blendApplyTypeNum >= 0 && blendApplyTypeNum < static_cast<int>(BlendApplyType::MAX)) {
7082             blendApplyType = static_cast<BlendApplyType>(blendApplyTypeNum);
7083         }
7084     }
7085     if (!info[0]->IsObject()) {
7086         ViewAbstractModel::GetInstance()->SetBlendMode(blendMode);
7087     }
7088     ViewAbstractModel::GetInstance()->SetBlendApplyType(blendApplyType);
7089 }
7090 
JsGrayScale(const JSCallbackInfo & info)7091 void JSViewAbstract::JsGrayScale(const JSCallbackInfo& info)
7092 {
7093     CalcDimension value;
7094     if (!ParseJsDimensionVp(info[0], value)) {
7095         value.SetValue(0.0);
7096         ViewAbstractModel::GetInstance()->SetGrayScale(value);
7097         return;
7098     }
7099 
7100     if (LessNotEqual(value.Value(), 0.0)) {
7101         value.SetValue(0.0);
7102     }
7103 
7104     if (GreatNotEqual(value.Value(), 1.0)) {
7105         value.SetValue(1.0);
7106     }
7107 
7108     ViewAbstractModel::GetInstance()->SetGrayScale(value);
7109 }
7110 
JsBrightness(const JSCallbackInfo & info)7111 void JSViewAbstract::JsBrightness(const JSCallbackInfo& info)
7112 {
7113     CalcDimension value;
7114     if (!ParseJsDimensionVp(info[0], value)) {
7115         value.SetValue(1.0);
7116         ViewAbstractModel::GetInstance()->SetBrightness(value);
7117         return;
7118     }
7119 
7120     ViewAbstractModel::GetInstance()->SetBrightness(value);
7121 }
7122 
JsContrast(const JSCallbackInfo & info)7123 void JSViewAbstract::JsContrast(const JSCallbackInfo& info)
7124 {
7125     CalcDimension value;
7126     if (!ParseJsDimensionVp(info[0], value)) {
7127         value.SetValue(1.0);
7128         ViewAbstractModel::GetInstance()->SetContrast(value);
7129         return;
7130     }
7131 
7132     if (LessNotEqual(value.Value(), 0.0)) {
7133         value.SetValue(0.0);
7134     }
7135 
7136     ViewAbstractModel::GetInstance()->SetContrast(value);
7137 }
7138 
JsSaturate(const JSCallbackInfo & info)7139 void JSViewAbstract::JsSaturate(const JSCallbackInfo& info)
7140 {
7141     CalcDimension value;
7142     if (!ParseJsDimensionVp(info[0], value)) {
7143         value.SetValue(1.0);
7144         ViewAbstractModel::GetInstance()->SetSaturate(value);
7145         return;
7146     }
7147 
7148     if (LessNotEqual(value.Value(), 0.0)) {
7149         value.SetValue(0.0);
7150     }
7151 
7152     ViewAbstractModel::GetInstance()->SetSaturate(value);
7153 }
7154 
JsSepia(const JSCallbackInfo & info)7155 void JSViewAbstract::JsSepia(const JSCallbackInfo& info)
7156 {
7157     CalcDimension value;
7158     if (!ParseJsDimensionVp(info[0], value)) {
7159         value.SetValue(0.0);
7160         ViewAbstractModel::GetInstance()->SetSepia(value);
7161         return;
7162     }
7163 
7164     if (LessNotEqual(value.Value(), 0.0)) {
7165         value.SetValue(0.0);
7166     }
7167 
7168     ViewAbstractModel::GetInstance()->SetSepia(value);
7169 }
7170 
ParseInvertProps(const JSRef<JSVal> & jsValue,InvertVariant & invert)7171 bool JSViewAbstract::ParseInvertProps(const JSRef<JSVal>& jsValue, InvertVariant& invert)
7172 {
7173     double invertValue = 0.0;
7174     if (ParseJsDouble(jsValue, invertValue)) {
7175         invert = static_cast<float>(std::clamp(invertValue, 0.0, 1.0));
7176         return true;
7177     }
7178     auto argsPtrItem = JsonUtil::ParseJsonString(jsValue->ToString());
7179     if (!argsPtrItem || argsPtrItem->IsNull()) {
7180         return false;
7181     }
7182     InvertOption option;
7183     double low = 0.0;
7184     if (ParseJsonDouble(argsPtrItem->GetValue("low"), low)) {
7185         option.low_ = std::clamp(low, 0.0, 1.0);
7186     }
7187     double high = 0.0;
7188     if (ParseJsonDouble(argsPtrItem->GetValue("high"), high)) {
7189         option.high_ = std::clamp(high, 0.0, 1.0);
7190     }
7191     double threshold = 0.0;
7192     if (ParseJsonDouble(argsPtrItem->GetValue("threshold"), threshold)) {
7193         option.threshold_ = std::clamp(threshold, 0.0, 1.0);
7194     }
7195     double thresholdRange = 0.0;
7196     if (ParseJsonDouble(argsPtrItem->GetValue("thresholdRange"), thresholdRange)) {
7197         option.thresholdRange_ = std::clamp(thresholdRange, 0.0, 1.0);
7198     }
7199     invert = option;
7200     return true;
7201 }
7202 
JsInvert(const JSCallbackInfo & info)7203 void JSViewAbstract::JsInvert(const JSCallbackInfo& info)
7204 {
7205     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT, JSCallbackInfoType::NUMBER };
7206     InvertVariant invert = 0.0f;
7207     auto jsVal = info[0];
7208     if (!CheckJSCallbackInfo("JsInvert", jsVal, checkList)) {
7209         ViewAbstractModel::GetInstance()->SetInvert(invert);
7210         return;
7211     }
7212     if (ParseInvertProps(jsVal, invert)) {
7213         ViewAbstractModel::GetInstance()->SetInvert(invert);
7214     }
7215     ViewAbstractModel::GetInstance()->SetInvert(invert);
7216 }
7217 
JsSystemBarEffect(const JSCallbackInfo & info)7218 void JSViewAbstract::JsSystemBarEffect(const JSCallbackInfo& info)
7219 {
7220     ViewAbstractModel::GetInstance()->SetSystemBarEffect(true);
7221 }
7222 
JsHueRotate(const JSCallbackInfo & info)7223 void JSViewAbstract::JsHueRotate(const JSCallbackInfo& info)
7224 {
7225     std::optional<float> degree;
7226     JSRef<JSVal> arg = info[0];
7227     if (arg->IsString()) {
7228         degree = static_cast<float>(StringUtils::StringToDegree(arg->ToString()));
7229     } else if (arg->IsNumber()) {
7230         degree = static_cast<float>(arg->ToNumber<int32_t>());
7231     } else {
7232         ViewAbstractModel::GetInstance()->SetHueRotate(0.0);
7233         return;
7234     }
7235     float deg = 0.0f;
7236     if (degree) {
7237         deg = degree.value();
7238         degree.reset();
7239     }
7240     deg = std::fmod(deg, ROUND_UNIT);
7241     if (deg < 0.0f) {
7242         deg += ROUND_UNIT;
7243     }
7244     ViewAbstractModel::GetInstance()->SetHueRotate(deg);
7245 }
7246 
JsClip(const JSCallbackInfo & info)7247 void JSViewAbstract::JsClip(const JSCallbackInfo& info)
7248 {
7249     JSRef<JSVal> arg = info[0];
7250     if (arg->IsUndefined()) {
7251         ViewAbstractModel::GetInstance()->SetClipEdge(false);
7252         return;
7253     }
7254     if (arg->IsObject()) {
7255         JSShapeAbstract* clipShape = JSRef<JSObject>::Cast(arg)->Unwrap<JSShapeAbstract>();
7256         if (clipShape == nullptr) {
7257             return;
7258         }
7259         ViewAbstractModel::GetInstance()->SetClipShape(clipShape->GetBasicShape());
7260     } else if (arg->IsBoolean()) {
7261         ViewAbstractModel::GetInstance()->SetClipEdge(arg->ToBoolean());
7262     }
7263 }
7264 
JsClipShape(const JSCallbackInfo & info)7265 void JSViewAbstract::JsClipShape(const JSCallbackInfo& info)
7266 {
7267     if (info[0]->IsObject()) {
7268         JSShapeAbstract* clipShape = JSRef<JSObject>::Cast(info[0])->Unwrap<JSShapeAbstract>();
7269         if (clipShape == nullptr) {
7270             return;
7271         }
7272         ViewAbstractModel::GetInstance()->SetClipShape(clipShape->GetBasicShape());
7273     }
7274 }
7275 
JsMask(const JSCallbackInfo & info)7276 void JSViewAbstract::JsMask(const JSCallbackInfo& info)
7277 {
7278     JSRef<JSVal> arg = info[0];
7279     if (!arg->IsObject()) {
7280         ViewAbstractModel::GetInstance()->SetProgressMask(nullptr);
7281         return;
7282     }
7283     auto paramObject = JSRef<JSObject>::Cast(arg);
7284     JSRef<JSVal> typeParam = paramObject->GetProperty("type");
7285     if (!typeParam->IsNull() && !typeParam->IsUndefined() && typeParam->IsString() &&
7286         typeParam->ToString() == "ProgressMask") {
7287         auto progressMask = AceType::MakeRefPtr<NG::ProgressMaskProperty>();
7288         JSRef<JSVal> jValue = paramObject->GetProperty("value");
7289         auto value = jValue->IsNumber() ? jValue->ToNumber<float>() : 0.0f;
7290         if (value < 0.0f) {
7291             value = 0.0f;
7292         }
7293         progressMask->SetValue(value);
7294         JSRef<JSVal> jTotal = paramObject->GetProperty("total");
7295         auto total = jTotal->IsNumber() ? jTotal->ToNumber<float>() : DEFAULT_PROGRESS_TOTAL;
7296         if (total < 0.0f) {
7297             total = DEFAULT_PROGRESS_TOTAL;
7298         }
7299         progressMask->SetMaxValue(total);
7300         JSRef<JSVal> jColor = paramObject->GetProperty("color");
7301         Color colorVal;
7302         if (ParseJsColor(jColor, colorVal)) {
7303             progressMask->SetColor(colorVal);
7304         } else {
7305             RefPtr<ProgressTheme> theme = GetTheme<ProgressTheme>();
7306             progressMask->SetColor(theme->GetMaskColor());
7307         }
7308         JSRef<JSVal> jEnableBreathe = paramObject->GetProperty("breathe");
7309         if (jEnableBreathe->IsBoolean()) {
7310             progressMask->SetEnableBreathe(jEnableBreathe->ToBoolean());
7311         }
7312         ViewAbstractModel::GetInstance()->SetProgressMask(progressMask);
7313     } else {
7314         JSShapeAbstract* maskShape = JSRef<JSObject>::Cast(arg)->Unwrap<JSShapeAbstract>();
7315         if (maskShape == nullptr) {
7316             return;
7317         };
7318         ViewAbstractModel::GetInstance()->SetMask(maskShape->GetBasicShape());
7319     }
7320 }
7321 
JsMaskShape(const JSCallbackInfo & info)7322 void JSViewAbstract::JsMaskShape(const JSCallbackInfo& info)
7323 {
7324     if (!info[0]->IsObject()) {
7325         return;
7326     }
7327 
7328     JSShapeAbstract* maskShape = JSRef<JSObject>::Cast(info[0])->Unwrap<JSShapeAbstract>();
7329     if (maskShape == nullptr) {
7330         return;
7331     };
7332     ViewAbstractModel::GetInstance()->SetMask(maskShape->GetBasicShape());
7333 }
7334 
JsFocusable(const JSCallbackInfo & info)7335 void JSViewAbstract::JsFocusable(const JSCallbackInfo& info)
7336 {
7337     if (!info[0]->IsBoolean()) {
7338         return;
7339     }
7340     ViewAbstractModel::GetInstance()->SetFocusable(info[0]->ToBoolean());
7341 }
7342 
JsTabStop(const JSCallbackInfo & info)7343 void JSViewAbstract::JsTabStop(const JSCallbackInfo& info)
7344 {
7345     if (!info[0]->IsBoolean()) {
7346         ViewAbstractModel::GetInstance()->SetTabStop(false);
7347         return;
7348     }
7349     ViewAbstractModel::GetInstance()->SetTabStop(info[0]->ToBoolean());
7350 }
7351 
JsFocusBox(const JSCallbackInfo & info)7352 void JSViewAbstract::JsFocusBox(const JSCallbackInfo& info)
7353 {
7354     if (!info[0]->IsObject() || info.Length() != 1) {
7355         return;
7356     }
7357     auto obj = JSRef<JSObject>::Cast(info[0]);
7358     NG::FocusBoxStyle style;
7359 
7360     CalcDimension margin;
7361     if (ParseLengthMetricsToDimension(obj->GetProperty("margin"), margin)) {
7362         style.margin = margin;
7363     }
7364     CalcDimension strokeWidth;
7365     if (ParseLengthMetricsToPositiveDimension(obj->GetProperty("strokeWidth"), strokeWidth)) {
7366         style.strokeWidth = strokeWidth;
7367     }
7368     Color strokeColor;
7369     if (ParseColorMetricsToColor(obj->GetProperty("strokeColor"), strokeColor)) {
7370         style.strokeColor = strokeColor;
7371     }
7372 
7373     ViewAbstractModel::GetInstance()->SetFocusBoxStyle(style);
7374 }
7375 
JsOnFocusMove(const JSCallbackInfo & args)7376 void JSViewAbstract::JsOnFocusMove(const JSCallbackInfo& args)
7377 {
7378     JSRef<JSVal> arg = args[0];
7379     if (arg->IsFunction()) {
7380         RefPtr<JsFocusFunction> jsOnFocusMove = AceType::MakeRefPtr<JsFocusFunction>(JSRef<JSFunc>::Cast(arg));
7381         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
7382         auto onFocusMove = [execCtx = args.GetExecutionContext(), func = std::move(jsOnFocusMove), node = frameNode](
7383                                int info) {
7384             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7385             ACE_SCORING_EVENT("onFocusMove");
7386             PipelineContext::SetCallBackNode(node);
7387             func->Execute(info);
7388         };
7389         ViewAbstractModel::GetInstance()->SetOnFocusMove(std::move(onFocusMove));
7390     }
7391 }
7392 
JsOnKeyEvent(const JSCallbackInfo & args)7393 void JSViewAbstract::JsOnKeyEvent(const JSCallbackInfo& args)
7394 {
7395     JSRef<JSVal> arg = args[0];
7396     if (arg->IsUndefined() && IsDisableEventVersion()) {
7397         ViewAbstractModel::GetInstance()->DisableOnKeyEvent();
7398         return;
7399     }
7400     if (!arg->IsFunction()) {
7401         return;
7402     }
7403     RefPtr<JsKeyFunction> JsOnKeyEvent = AceType::MakeRefPtr<JsKeyFunction>(JSRef<JSFunc>::Cast(arg));
7404     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
7405     auto onKeyEvent = [execCtx = args.GetExecutionContext(), func = std::move(JsOnKeyEvent), node = frameNode](
7406                           KeyEventInfo& info) -> bool {
7407         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, false);
7408         ACE_SCORING_EVENT("onKey");
7409         PipelineContext::SetCallBackNode(node);
7410         auto ret = func->ExecuteWithValue(info);
7411         return ret->IsBoolean() ? ret->ToBoolean() : false;
7412     };
7413     ViewAbstractModel::GetInstance()->SetOnKeyEvent(std::move(onKeyEvent));
7414 }
7415 
JsOnFocus(const JSCallbackInfo & args)7416 void JSViewAbstract::JsOnFocus(const JSCallbackInfo& args)
7417 {
7418     JSRef<JSVal> arg = args[0];
7419     if (arg->IsUndefined() && IsDisableEventVersion()) {
7420         ViewAbstractModel::GetInstance()->DisableOnFocus();
7421         return;
7422     }
7423     if (!arg->IsFunction()) {
7424         return;
7425     }
7426     RefPtr<JsFocusFunction> jsOnFocus = AceType::MakeRefPtr<JsFocusFunction>(JSRef<JSFunc>::Cast(arg));
7427     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
7428     auto onFocus = [execCtx = args.GetExecutionContext(), func = std::move(jsOnFocus), node = frameNode]() {
7429         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7430         ACE_SCORING_EVENT("onFocus");
7431         PipelineContext::SetCallBackNode(node);
7432         func->Execute();
7433     };
7434 
7435     ViewAbstractModel::GetInstance()->SetOnFocus(std::move(onFocus));
7436 }
7437 
JsOnBlur(const JSCallbackInfo & args)7438 void JSViewAbstract::JsOnBlur(const JSCallbackInfo& args)
7439 {
7440     JSRef<JSVal> arg = args[0];
7441     if (arg->IsUndefined() && IsDisableEventVersion()) {
7442         ViewAbstractModel::GetInstance()->DisableOnBlur();
7443         return;
7444     }
7445     if (!arg->IsFunction()) {
7446         return;
7447     }
7448     RefPtr<JsFocusFunction> jsOnBlur = AceType::MakeRefPtr<JsFocusFunction>(JSRef<JSFunc>::Cast(arg));
7449     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
7450     auto onBlur = [execCtx = args.GetExecutionContext(), func = std::move(jsOnBlur), node = frameNode]() {
7451         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7452         ACE_SCORING_EVENT("onBlur");
7453         PipelineContext::SetCallBackNode(node);
7454         func->Execute();
7455     };
7456 
7457     ViewAbstractModel::GetInstance()->SetOnBlur(std::move(onBlur));
7458 }
7459 
JsTabIndex(const JSCallbackInfo & info)7460 void JSViewAbstract::JsTabIndex(const JSCallbackInfo& info)
7461 {
7462     JSRef<JSVal> arg = info[0];
7463     if (!arg->IsNumber()) {
7464         return;
7465     }
7466     ViewAbstractModel::GetInstance()->SetTabIndex(arg->ToNumber<int32_t>());
7467 }
7468 
JsFocusOnTouch(const JSCallbackInfo & info)7469 void JSViewAbstract::JsFocusOnTouch(const JSCallbackInfo& info)
7470 {
7471     JSRef<JSVal> arg = info[0];
7472     if (!arg->IsBoolean()) {
7473         return;
7474     }
7475     auto isFocusOnTouch = arg->ToBoolean();
7476     ViewAbstractModel::GetInstance()->SetFocusOnTouch(isFocusOnTouch);
7477 }
7478 
JsDefaultFocus(const JSCallbackInfo & info)7479 void JSViewAbstract::JsDefaultFocus(const JSCallbackInfo& info)
7480 {
7481     JSRef<JSVal> arg = info[0];
7482     if (!arg->IsBoolean()) {
7483         return;
7484     }
7485     auto isDefaultFocus = arg->ToBoolean();
7486     ViewAbstractModel::GetInstance()->SetDefaultFocus(isDefaultFocus);
7487 }
7488 
JsGroupDefaultFocus(const JSCallbackInfo & info)7489 void JSViewAbstract::JsGroupDefaultFocus(const JSCallbackInfo& info)
7490 {
7491     JSRef<JSVal> arg = info[0];
7492     if (!arg->IsBoolean()) {
7493         return;
7494     }
7495     auto isGroupDefaultFocus = arg->ToBoolean();
7496     ViewAbstractModel::GetInstance()->SetGroupDefaultFocus(isGroupDefaultFocus);
7497 }
7498 
JsKey(const std::string & key)7499 void JSViewAbstract::JsKey(const std::string& key)
7500 {
7501     ViewAbstractModel::GetInstance()->SetInspectorId(key);
7502 }
7503 
JsId(const JSCallbackInfo & info)7504 void JSViewAbstract::JsId(const JSCallbackInfo& info)
7505 {
7506     JSRef<JSVal> arg = info[0];
7507     if (!arg->IsString() || arg->IsNull() || arg->IsUndefined()) {
7508         return;
7509     }
7510     std::string id = arg->ToString();
7511     if (id.empty()) {
7512         return;
7513     }
7514     JsKey(id);
7515 }
7516 
JsRestoreId(int32_t restoreId)7517 void JSViewAbstract::JsRestoreId(int32_t restoreId)
7518 {
7519     ViewAbstractModel::GetInstance()->SetRestoreId(restoreId);
7520 }
7521 
JsDebugLine(const JSCallbackInfo & info)7522 void JSViewAbstract::JsDebugLine(const JSCallbackInfo& info)
7523 {
7524     std::string debugLine;
7525     auto length = info.Length();
7526     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING };
7527 
7528     if (length == 1) { // deprecated version of debug line
7529         auto jsVal = info[0];
7530         if (!CheckJSCallbackInfo("JsDebugLine", jsVal, checkList)) {
7531             return;
7532         }
7533         debugLine = jsVal->ToString();
7534     } else if (length == 2) { // debug line with extra package name
7535         auto line = info[0];
7536         auto packageName = info[1];
7537         if (!CheckJSCallbackInfo("JsDebugLine", line, checkList) ||
7538             !CheckJSCallbackInfo("JsDebugLine", packageName, checkList)) {
7539             return;
7540         }
7541         auto json = JsonUtil::Create(true);
7542         json->Put(DEBUG_LINE_INFO_LINE, line->ToString().c_str());
7543         json->Put(DEBUG_LINE_INFO_PACKAGE_NAME, packageName->ToString().c_str());
7544         debugLine = json->ToString();
7545     }
7546 
7547     ViewAbstractModel::GetInstance()->SetDebugLine(debugLine);
7548 }
7549 
JsOpacityPassThrough(const JSCallbackInfo & info)7550 void JSViewAbstract::JsOpacityPassThrough(const JSCallbackInfo& info)
7551 {
7552     double opacity = 1.0;
7553     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
7554         if (ParseJsDouble(info[0], opacity)) {
7555             opacity = std::clamp(opacity, 0.0, 1.0);
7556         }
7557     } else {
7558         if (!ParseJsDouble(info[0], opacity)) {
7559             return;
7560         }
7561         if ((LessNotEqual(opacity, 0.0)) || opacity > 1) {
7562             opacity = 1.0;
7563         }
7564     }
7565 
7566     ViewAbstractModel::GetInstance()->SetOpacity(opacity, true);
7567 }
7568 
JsTransitionPassThrough(const JSCallbackInfo & info)7569 void JSViewAbstract::JsTransitionPassThrough(const JSCallbackInfo& info)
7570 {
7571     if (info.Length() == 0) {
7572         ViewAbstractModel::GetInstance()->SetTransition(
7573             NG::TransitionOptions::GetDefaultTransition(TransitionType::ALL));
7574         return;
7575     }
7576     if (!info[0]->IsObject()) {
7577         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
7578             ViewAbstractModel::GetInstance()->CleanTransition();
7579             ViewAbstractModel::GetInstance()->SetChainedTransition(nullptr, nullptr);
7580         }
7581         return;
7582     }
7583     auto obj = JSRef<JSObject>::Cast(info[0]);
7584     if (!obj->GetProperty("successor_")->IsUndefined()) {
7585         auto chainedEffect = ParseChainedTransition(obj, info.GetExecutionContext());
7586         std::function<void(bool)> finishCallback;
7587         if (info.Length() > 1 && info[1]->IsFunction()) {
7588             finishCallback = ParseTransitionCallback(JSRef<JSFunc>::Cast(info[1]), info.GetExecutionContext());
7589         }
7590         ViewAbstractModel::GetInstance()->SetChainedTransition(chainedEffect, std::move(finishCallback));
7591         return;
7592     }
7593     auto options = ParseJsTransition(obj);
7594     ViewAbstractModel::GetInstance()->SetTransition(options, true);
7595 }
7596 
JsAccessibilityGroup(const JSCallbackInfo & info)7597 void JSViewAbstract::JsAccessibilityGroup(const JSCallbackInfo& info)
7598 {
7599     bool isGroup = false;
7600     if (info[0]->IsBoolean()) {
7601         isGroup = info[0]->ToBoolean();
7602     }
7603     ViewAbstractModel::GetInstance()->SetAccessibilityGroup(isGroup);
7604 
7605     if (info.Length() > 1 && info[1]->IsObject()) {
7606         auto obj = JSRef<JSObject>::Cast(info[1]);
7607 
7608         auto preferAccessibilityTextObj = obj->GetProperty("accessibilityPreferred");
7609         auto preferAccessibilityText = preferAccessibilityTextObj->IsBoolean() ? preferAccessibilityTextObj->ToBoolean() : false;
7610         ViewAbstractModel::GetInstance()->SetAccessibilityTextPreferred(preferAccessibilityText);
7611     }
7612 }
7613 
JsAccessibilityText(const JSCallbackInfo & info)7614 void JSViewAbstract::JsAccessibilityText(const JSCallbackInfo& info)
7615 {
7616     const JSRef<JSVal>& jsValue = info[0];
7617     std::string text;
7618     if (!ParseJsString(jsValue, text)) {
7619         return;
7620     }
7621     ViewAbstractModel::GetInstance()->SetAccessibilityText(text);
7622 }
7623 
JsAccessibilityTextHint(const std::string & text)7624 void JSViewAbstract::JsAccessibilityTextHint(const std::string& text)
7625 {
7626     ViewAbstractModel::GetInstance()->SetAccessibilityTextHint(text);
7627 }
7628 
JsAccessibilityDescription(const JSCallbackInfo & info)7629 void JSViewAbstract::JsAccessibilityDescription(const JSCallbackInfo& info)
7630 {
7631     const JSRef<JSVal>& jsValue = info[0];
7632     std::string description;
7633     if (!ParseJsString(jsValue, description)) {
7634         return;
7635     }
7636     std::pair<bool, std::string> autoEventPair(false, "");
7637     std::pair<bool, std::string> descriptionPair(false, "");
7638     ParseAccessibilityDescriptionJson(description, autoEventPair, descriptionPair);
7639     if (descriptionPair.first) {
7640         ViewAbstractModel::GetInstance()->SetAccessibilityDescription(descriptionPair.second);
7641     } else {
7642         ViewAbstractModel::GetInstance()->SetAccessibilityDescription(description);
7643     }
7644     if (autoEventPair.first) {
7645         ViewAbstractModel::GetInstance()->SetAutoEventParam(autoEventPair.second);
7646     }
7647 }
7648 
ParseAccessibilityDescriptionJson(const std::string & description,std::pair<bool,std::string> & autoEventPair,std::pair<bool,std::string> & descriptionPair)7649 void JSViewAbstract::ParseAccessibilityDescriptionJson(const std::string& description,
7650     std::pair<bool, std::string>& autoEventPair, std::pair<bool, std::string>& descriptionPair)
7651 {
7652     if (description.empty()) {
7653         return;
7654     }
7655     if (!StartWith(description, "{") || !EndWith(description, "}")) {
7656         return;
7657     }
7658     auto jsonObj = JsonUtil::ParseJsonString(description);
7659     if (!jsonObj || !jsonObj->IsValid() || !jsonObj->IsObject()) {
7660         return;
7661     }
7662     if (jsonObj->Contains("$autoEventParam")) {
7663         auto param = jsonObj->GetValue("$autoEventParam");
7664         if (param) {
7665             autoEventPair = std::make_pair(true, param->ToString());
7666         }
7667     }
7668     if (jsonObj->Contains("$accessibilityDescription")) {
7669         descriptionPair = std::make_pair(true, jsonObj->GetString("$accessibilityDescription"));
7670     } else if (jsonObj->Contains("$autoEventParam")) {
7671         descriptionPair = std::make_pair(true, "");
7672     }
7673 }
7674 
JsAccessibilityImportance(const std::string & importance)7675 void JSViewAbstract::JsAccessibilityImportance(const std::string& importance)
7676 {
7677     ViewAbstractModel::GetInstance()->SetAccessibilityImportance(importance);
7678 }
7679 
JsAccessibilityLevel(const std::string & level)7680 void JSViewAbstract::JsAccessibilityLevel(const std::string& level)
7681 {
7682     ViewAbstractModel::GetInstance()->SetAccessibilityImportance(level);
7683 }
7684 
JsAccessibilityVirtualNode(const JSCallbackInfo & info)7685 void JSViewAbstract::JsAccessibilityVirtualNode(const JSCallbackInfo& info)
7686 {
7687     // parse builder
7688     if (!info[0]->IsObject()) {
7689         return;
7690     }
7691     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
7692     auto builder = obj->GetProperty("builder");
7693     if (builder->IsFunction()) {
7694         auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
7695         CHECK_NULL_VOID(builderFunc);
7696         auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc)]() {
7697             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7698             ACE_SCORING_EVENT("AccessibilityVirtualNode");
7699             func->Execute();
7700         };
7701         NG::ViewAbstractModelNG::GetInstance()->SetAccessibilityVirtualNode(std::move(buildFunc));
7702     }
7703 }
7704 
JsAccessibilitySelected(const JSCallbackInfo & info)7705 void JSViewAbstract::JsAccessibilitySelected(const JSCallbackInfo& info)
7706 {
7707     bool selected = false;
7708     bool resetValue = false;
7709     JSRef<JSVal> arg = info[0];
7710     if (arg->IsUndefined()) {
7711         resetValue = true;
7712     } else if (arg->IsBoolean()) {
7713         selected = arg->ToBoolean();
7714     } else {
7715         return;
7716     }
7717 
7718     ViewAbstractModel::GetInstance()->SetAccessibilitySelected(selected, resetValue);
7719 }
7720 
JsAccessibilityChecked(const JSCallbackInfo & info)7721 void JSViewAbstract::JsAccessibilityChecked(const JSCallbackInfo& info)
7722 {
7723     bool checked = false;
7724     bool resetValue = false;
7725     JSRef<JSVal> arg = info[0];
7726     if (arg->IsUndefined()) {
7727         resetValue = true;
7728     } else if (arg->IsBoolean()) {
7729         checked = arg->ToBoolean();
7730     } else {
7731         return;
7732     }
7733 
7734     ViewAbstractModel::GetInstance()->SetAccessibilityChecked(checked, resetValue);
7735 }
7736 
JsBackground(const JSCallbackInfo & info)7737 void JSViewAbstract::JsBackground(const JSCallbackInfo& info)
7738 {
7739     // Check the parameters
7740     if (info.Length() <= 0 || !info[0]->IsObject()) {
7741         return;
7742     }
7743     JSRef<JSObject> backgroundObj = JSRef<JSObject>::Cast(info[0]);
7744     auto builder = backgroundObj->GetProperty(static_cast<int32_t>(ArkUIIndex::BUILDER));
7745     if (!builder->IsFunction()) {
7746         return;
7747     }
7748     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
7749     CHECK_NULL_VOID(builderFunc);
7750     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
7751     auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = frameNode]() {
7752         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7753         ACE_SCORING_EVENT("BindBackground");
7754         PipelineContext::SetCallBackNode(node);
7755         func->Execute();
7756     };
7757     Alignment alignment = Alignment::CENTER;
7758     if (info.Length() >= PARAMETER_LENGTH_SECOND && info[1]->IsObject()) {
7759         JSRef<JSObject> object = JSRef<JSObject>::Cast(info[1]);
7760         auto align = object->GetProperty(static_cast<int32_t>(ArkUIIndex::ALIGN));
7761         auto value = align->ToNumber<int32_t>();
7762         alignment = ParseAlignment(value);
7763     }
7764     ViewAbstractModel::GetInstance()->BindBackground(std::move(buildFunc), alignment);
7765 }
7766 
JsBindContextMenu(const JSCallbackInfo & info)7767 void JSViewAbstract::JsBindContextMenu(const JSCallbackInfo& info)
7768 {
7769     NG::MenuParam menuParam;
7770     // Check the parameters
7771     if (info.Length() <= 0) {
7772         return;
7773     }
7774     size_t builderIndex = ParseBindContextMenuShow(info, menuParam);
7775     if (!info[builderIndex]->IsObject()) {
7776         return;
7777     }
7778 
7779     JSRef<JSObject> menuObj = JSRef<JSObject>::Cast(info[builderIndex]);
7780     auto builder = menuObj->GetProperty("builder");
7781     if (!builder->IsFunction()) {
7782         return;
7783     }
7784     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
7785     CHECK_NULL_VOID(builderFunc);
7786 
7787     ResponseType responseType = ResponseType::LONG_PRESS;
7788     if (!info[0]->IsBoolean() && info.Length() >= PARAMETER_LENGTH_SECOND && info[1]->IsNumber()) {
7789         auto response = info[1]->ToNumber<int32_t>();
7790         responseType = static_cast<ResponseType>(response);
7791     }
7792     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
7793     std::function<void()> buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc),
7794                                           node = frameNode]() {
7795         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7796         ACE_SCORING_EVENT("BuildContextMenu");
7797         PipelineContext::SetCallBackNode(node);
7798         func->Execute();
7799     };
7800 
7801     menuParam.previewMode = MenuPreviewMode::NONE;
7802     std::function<void()> previewBuildFunc = nullptr;
7803     if (info.Length() >= PARAMETER_LENGTH_THIRD && info[2]->IsObject()) {
7804         ParseBindContentOptionParam(info, info[2], menuParam, previewBuildFunc);
7805     }
7806 
7807     if (responseType != ResponseType::LONG_PRESS) {
7808         menuParam.previewMode = MenuPreviewMode::NONE;
7809         menuParam.isShowHoverImage = false;
7810         menuParam.menuBindType = MenuBindingType::RIGHT_CLICK;
7811     }
7812     menuParam.type = NG::MenuType::CONTEXT_MENU;
7813     ViewAbstractModel::GetInstance()->BindContextMenu(responseType, buildFunc, menuParam, previewBuildFunc);
7814     ViewAbstractModel::GetInstance()->BindDragWithContextMenuParams(menuParam);
7815 }
7816 
ParseBindContentCoverIsShow(const JSCallbackInfo & info)7817 bool ParseBindContentCoverIsShow(const JSCallbackInfo& info)
7818 {
7819     bool isShow = false;
7820     if (info[0]->IsBoolean()) {
7821         isShow = info[0]->ToBoolean();
7822     } else if (info[0]->IsObject()) {
7823         JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(info[0]);
7824         auto isShowObj = callbackObj->GetProperty("value");
7825         isShow = isShowObj->IsBoolean() ? isShowObj->ToBoolean() : false;
7826     }
7827     TAG_LOGD(AceLogTag::ACE_SHEET, "ContentCover get isShow is: %{public}d", isShow);
7828     return isShow;
7829 }
7830 
JsBindContentCover(const JSCallbackInfo & info)7831 void JSViewAbstract::JsBindContentCover(const JSCallbackInfo& info)
7832 {
7833     // parse isShow
7834     bool isShow = ParseBindContentCoverIsShow(info);
7835     DoubleBindCallback callback = nullptr;
7836     if (info[0]->IsObject()) {
7837         JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(info[0]);
7838         callback = ParseDoubleBindCallback(info, callbackObj);
7839     }
7840 
7841     // parse builder
7842     if (!info[1]->IsObject()) {
7843         return;
7844     }
7845     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
7846     auto builder = obj->GetProperty("builder");
7847     if (!builder->IsFunction()) {
7848         return;
7849     }
7850     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
7851     CHECK_NULL_VOID(builderFunc);
7852     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
7853     auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = frameNode]() {
7854         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7855         ACE_SCORING_EVENT("BindContentCover");
7856         PipelineContext::SetCallBackNode(node);
7857         func->Execute();
7858     };
7859 
7860     // parse ModalTransition
7861     NG::ModalStyle modalStyle;
7862     modalStyle.modalTransition = NG::ModalTransition::DEFAULT;
7863     std::function<void()> onShowCallback;
7864     std::function<void()> onDismissCallback;
7865     std::function<void()> onWillShowCallback;
7866     std::function<void()> onWillDismissCallback;
7867     NG::ContentCoverParam contentCoverParam;
7868     std::function<void(const int32_t&)> onWillDismissFunc;
7869     if (info.Length() == 3) {
7870         if (info[2]->IsObject()) {
7871             ParseOverlayCallback(info[2], onShowCallback, onDismissCallback, onWillShowCallback, /* 2:args index */
7872                 onWillDismissCallback, onWillDismissFunc);
7873             ParseModalStyle(info[2], modalStyle);
7874             contentCoverParam.onWillDismiss = std::move(onWillDismissFunc);
7875             ParseModalTransitonEffect(info[2], contentCoverParam, info.GetExecutionContext()); /* 2:args index */
7876         } else if (info[2]->IsNumber()) {
7877             auto transitionNumber = info[2]->ToNumber<int32_t>();
7878             if (transitionNumber >= 0 && transitionNumber <= 2) {
7879                 modalStyle.modalTransition = static_cast<NG::ModalTransition>(transitionNumber);
7880             }
7881         }
7882     }
7883     ViewAbstractModel::GetInstance()->BindContentCover(isShow, std::move(callback), std::move(buildFunc), modalStyle,
7884         std::move(onShowCallback), std::move(onDismissCallback), std::move(onWillShowCallback),
7885         std::move(onWillDismissCallback), contentCoverParam);
7886 }
7887 
ParseModalTransitonEffect(const JSRef<JSObject> & paramObj,NG::ContentCoverParam & contentCoverParam,const JSExecutionContext & context)7888 void JSViewAbstract::ParseModalTransitonEffect(
7889     const JSRef<JSObject>& paramObj, NG::ContentCoverParam& contentCoverParam, const JSExecutionContext& context)
7890 {
7891     auto transitionEffectValue = paramObj->GetProperty("transition");
7892     if (transitionEffectValue->IsObject()) {
7893         JSRef<JSObject> obj = JSRef<JSObject>::Cast(transitionEffectValue);
7894         contentCoverParam.transitionEffect = ParseChainedTransition(obj, context);
7895     }
7896 }
7897 
ParseModalStyle(const JSRef<JSObject> & paramObj,NG::ModalStyle & modalStyle)7898 void JSViewAbstract::ParseModalStyle(const JSRef<JSObject>& paramObj, NG::ModalStyle& modalStyle)
7899 {
7900     auto modalTransition = paramObj->GetProperty("modalTransition");
7901     auto backgroundColor = paramObj->GetProperty("backgroundColor");
7902     if (modalTransition->IsNumber()) {
7903         auto transitionNumber = modalTransition->ToNumber<int32_t>();
7904         if (transitionNumber >= 0 && transitionNumber <= 2) {
7905             modalStyle.modalTransition = static_cast<NG::ModalTransition>(transitionNumber);
7906         }
7907     }
7908     Color color;
7909     if (ParseJsColor(backgroundColor, color)) {
7910         modalStyle.backgroundColor = color;
7911     }
7912 }
7913 
ParseSheetIsShow(const JSCallbackInfo & info,bool & isShow,std::function<void (const std::string &)> & callback)7914 void JSViewAbstract::ParseSheetIsShow(
7915     const JSCallbackInfo& info, bool& isShow, std::function<void(const std::string&)>& callback)
7916 {
7917     if (info[0]->IsBoolean()) {
7918         isShow = info[0]->ToBoolean();
7919     } else if (info[0]->IsObject()) {
7920         JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(info[0]);
7921         callback = ParseDoubleBindCallback(info, callbackObj);
7922         auto isShowObj = callbackObj->GetProperty("value");
7923         isShow = isShowObj->IsBoolean() ? isShowObj->ToBoolean() : false;
7924     }
7925     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet get isShow is: %{public}d", isShow);
7926 }
7927 
JsBindSheet(const JSCallbackInfo & info)7928 void JSViewAbstract::JsBindSheet(const JSCallbackInfo& info)
7929 {
7930     // parse isShow and builder
7931     bool isShow = false;
7932     DoubleBindCallback callback = nullptr;
7933     ParseSheetIsShow(info, isShow, callback);
7934     if (!info[1]->IsObject())
7935         return;
7936     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
7937     auto builder = obj->GetProperty("builder");
7938     if (!builder->IsFunction())
7939         return;
7940     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
7941     CHECK_NULL_VOID(builderFunc);
7942     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
7943     auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = frameNode]() {
7944         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7945         ACE_SCORING_EVENT("BindSheet");
7946         PipelineContext::SetCallBackNode(node);
7947         func->Execute();
7948     };
7949     // parse SheetStyle and callbacks
7950     NG::SheetStyle sheetStyle;
7951     sheetStyle.sheetMode = NG::SheetMode::LARGE;
7952     sheetStyle.showDragBar = true;
7953     sheetStyle.showCloseIcon = true;
7954     sheetStyle.showInPage = false;
7955     std::function<void()> onAppearCallback;
7956     std::function<void()> onDisappearCallback;
7957     std::function<void()> onWillAppearCallback;
7958     std::function<void()> onWillDisappearCallback  ;
7959     std::function<void()> shouldDismissFunc;
7960     std::function<void(const int32_t)> onWillDismissCallback;
7961     std::function<void(const float)> onHeightDidChangeCallback;
7962     std::function<void(const float)> onDetentsDidChangeCallback;
7963     std::function<void(const float)> onWidthDidChangeCallback;
7964     std::function<void(const float)> onTypeDidChangeCallback;
7965     std::function<void()> titleBuilderFunction;
7966     std::function<void()> sheetSpringBackFunc;
7967     if (info.Length() == PARAMETER_LENGTH_THIRD && info[SECOND_INDEX]->IsObject()) {
7968         ParseSheetCallback(info[SECOND_INDEX], onAppearCallback, onDisappearCallback, shouldDismissFunc,
7969             onWillDismissCallback, onWillAppearCallback, onWillDisappearCallback, onHeightDidChangeCallback,
7970             onDetentsDidChangeCallback, onWidthDidChangeCallback, onTypeDidChangeCallback, sheetSpringBackFunc);
7971         ParseSheetStyle(info[2], sheetStyle);
7972         ParseSheetTitle(info[2], sheetStyle, titleBuilderFunction);
7973     }
7974     ViewAbstractModel::GetInstance()->BindSheet(isShow, std::move(callback), std::move(buildFunc),
7975         std::move(titleBuilderFunction), sheetStyle, std::move(onAppearCallback), std::move(onDisappearCallback),
7976         std::move(shouldDismissFunc), std::move(onWillDismissCallback),  std::move(onWillAppearCallback),
7977         std::move(onWillDisappearCallback), std::move(onHeightDidChangeCallback), std::move(onDetentsDidChangeCallback),
7978         std::move(onWidthDidChangeCallback), std::move(onTypeDidChangeCallback), std::move(sheetSpringBackFunc));
7979 }
7980 
ParseSheetStyle(const JSRef<JSObject> & paramObj,NG::SheetStyle & sheetStyle,bool isPartialUpdate)7981 void JSViewAbstract::ParseSheetStyle(
7982     const JSRef<JSObject>& paramObj, NG::SheetStyle& sheetStyle, bool isPartialUpdate)
7983 {
7984     auto height = paramObj->GetProperty("height");
7985     auto showDragBar = paramObj->GetProperty("dragBar");
7986     auto backgroundColor = paramObj->GetProperty("backgroundColor");
7987     auto maskColor = paramObj->GetProperty("maskColor");
7988     auto sheetDetents = paramObj->GetProperty("detents");
7989     auto backgroundBlurStyle = paramObj->GetProperty("blurStyle");
7990     auto showCloseIcon = paramObj->GetProperty("showClose");
7991     auto type = paramObj->GetProperty("preferType");
7992     auto interactive = paramObj->GetProperty("enableOutsideInteractive");
7993     auto showMode = paramObj->GetProperty("mode");
7994     auto scrollSizeMode = paramObj->GetProperty("scrollSizeMode");
7995     auto keyboardAvoidMode = paramObj->GetProperty("keyboardAvoidMode");
7996     auto uiContextObj = paramObj->GetProperty("uiContext");
7997     if (uiContextObj->IsObject()) {
7998         JSRef<JSObject> obj = JSRef<JSObject>::Cast(uiContextObj);
7999         auto prop = obj->GetProperty("instanceId_");
8000         if (prop->IsNumber()) {
8001             sheetStyle.instanceId = prop->ToNumber<int32_t>();
8002         }
8003     }
8004     NG::SheetLevel sheetLevel = NG::SheetLevel::OVERLAY;
8005     if (ParseSheetLevel(showMode, sheetLevel) || !isPartialUpdate) {
8006         sheetStyle.showInPage = (sheetLevel == NG::SheetLevel::EMBEDDED);
8007     }
8008 
8009     std::vector<NG::SheetHeight> detents;
8010     if (ParseSheetDetents(sheetDetents, detents)) {
8011         sheetStyle.detents = detents;
8012     }
8013     BlurStyleOption styleOption;
8014     if (ParseSheetBackgroundBlurStyle(backgroundBlurStyle, styleOption)) {
8015         sheetStyle.backgroundBlurStyle = styleOption;
8016     }
8017     bool showClose = true;
8018     if (ParseJsBool(showCloseIcon, showClose)) {
8019         sheetStyle.showCloseIcon = showClose;
8020     } else if (!isPartialUpdate) {
8021         sheetStyle.showCloseIcon = true;
8022     }
8023 
8024     bool isInteractive = false;
8025     if (ParseJsBool(interactive, isInteractive)) {
8026         sheetStyle.interactive = isInteractive;
8027     }
8028 
8029     if (showDragBar->IsBoolean()) {
8030         sheetStyle.showDragBar = showDragBar->ToBoolean();
8031     } else if (isPartialUpdate) {
8032         sheetStyle.showDragBar.reset();
8033     } else {
8034         sheetStyle.showDragBar = true;
8035     }
8036 
8037     if (type->IsNull() || type->IsUndefined()) {
8038         sheetStyle.sheetType.reset();
8039     } else {
8040         if (type->IsNumber()) {
8041             auto sheetType = type->ToNumber<int32_t>();
8042             if (sheetType >= static_cast<int>(NG::SheetType::SHEET_BOTTOM) &&
8043                 sheetType <= static_cast<int>(NG::SheetType::SHEET_POPUP)) {
8044                 sheetStyle.sheetType = static_cast<NG::SheetType>(sheetType);
8045             }
8046         }
8047     }
8048     if (scrollSizeMode->IsNull() || scrollSizeMode->IsUndefined()) {
8049         sheetStyle.scrollSizeMode.reset();
8050     } else if (scrollSizeMode->IsNumber()) {
8051         auto sheetScrollSizeMode = scrollSizeMode->ToNumber<int32_t>();
8052         if (sheetScrollSizeMode >= static_cast<int>(NG::ScrollSizeMode::FOLLOW_DETENT) &&
8053             sheetScrollSizeMode <= static_cast<int>(NG::ScrollSizeMode::CONTINUOUS)) {
8054             sheetStyle.scrollSizeMode = static_cast<NG::ScrollSizeMode>(sheetScrollSizeMode);
8055         }
8056     }
8057 
8058     if (keyboardAvoidMode->IsNull() || keyboardAvoidMode->IsUndefined()) {
8059         sheetStyle.sheetKeyboardAvoidMode.reset();
8060     } else if (keyboardAvoidMode->IsNumber()) {
8061         auto sheetKeyboardAvoidMode = keyboardAvoidMode->ToNumber<int32_t>();
8062         if (sheetKeyboardAvoidMode >= static_cast<int>(NG::SheetKeyboardAvoidMode::NONE) &&
8063             sheetKeyboardAvoidMode <= static_cast<int>(NG::SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL)) {
8064             sheetStyle.sheetKeyboardAvoidMode = static_cast<NG::SheetKeyboardAvoidMode>(sheetKeyboardAvoidMode);
8065         }
8066     }
8067 
8068     Color color;
8069     if (ParseJsColor(backgroundColor, color)) {
8070         sheetStyle.backgroundColor = color;
8071     }
8072     // parse maskColor
8073     Color parseMaskColor;
8074     if (!maskColor->IsNull() && !maskColor->IsUndefined() && JSViewAbstract::ParseJsColor(maskColor, parseMaskColor)) {
8075         sheetStyle.maskColor = std::move(parseMaskColor);
8076     }
8077 
8078     // Parse border width
8079     auto borderWidthValue = paramObj->GetProperty("borderWidth");
8080     NG::BorderWidthProperty borderWidth;
8081     if (ParseBorderWidthProps(borderWidthValue, borderWidth)) {
8082         sheetStyle.borderWidth = borderWidth;
8083         // Parse border color
8084         auto colorValue = paramObj->GetProperty("borderColor");
8085         NG::BorderColorProperty borderColor;
8086         if (ParseBorderColorProps(colorValue, borderColor)) {
8087             sheetStyle.borderColor = borderColor;
8088         } else {
8089             sheetStyle.borderColor =
8090                 NG::BorderColorProperty({ Color::BLACK, Color::BLACK, Color::BLACK, Color::BLACK });
8091         }
8092         // Parse border style
8093         auto styleValue = paramObj->GetProperty("borderStyle");
8094         NG::BorderStyleProperty borderStyle;
8095         if (ParseBorderStyleProps(styleValue, borderStyle)) {
8096             sheetStyle.borderStyle = borderStyle;
8097         } else {
8098             sheetStyle.borderStyle = NG::BorderStyleProperty(
8099                 { BorderStyle::SOLID, BorderStyle::SOLID, BorderStyle::SOLID, BorderStyle::SOLID });
8100         }
8101     }
8102     if (isPartialUpdate) {
8103         auto colorValue = paramObj->GetProperty("borderColor");
8104         NG::BorderColorProperty borderColor;
8105         if (ParseBorderColorProps(colorValue, borderColor)) {
8106             sheetStyle.borderColor = borderColor;
8107         } else {
8108             sheetStyle.borderColor.reset();
8109         }
8110         auto styleValue = paramObj->GetProperty("borderStyle");
8111         NG::BorderStyleProperty borderStyle;
8112         if (ParseBorderStyleProps(styleValue, borderStyle)) {
8113             sheetStyle.borderStyle = borderStyle;
8114         } else {
8115             sheetStyle.borderStyle.reset();
8116         }
8117     }
8118 
8119     // Parse shadow
8120     Shadow shadow;
8121     auto shadowValue = paramObj->GetProperty("shadow");
8122     if ((shadowValue->IsObject() || shadowValue->IsNumber()) && ParseShadowProps(shadowValue, shadow)) {
8123         sheetStyle.shadow = shadow;
8124     }
8125 
8126     // Parse hoverMode
8127     auto enableHoverModeValue = paramObj->GetProperty("enableHoverMode");
8128     if (enableHoverModeValue->IsBoolean()) {
8129         sheetStyle.enableHoverMode = enableHoverModeValue->ToBoolean();
8130     }
8131     auto hoverModeAreaValue = paramObj->GetProperty("hoverModeArea");
8132     if (hoverModeAreaValue->IsNumber()) {
8133         auto hoverModeArea = hoverModeAreaValue->ToNumber<int32_t>();
8134         if (hoverModeArea >= 0 && hoverModeArea < static_cast<int32_t>(HOVER_MODE_AREA_TYPE.size())) {
8135             sheetStyle.hoverModeArea = HOVER_MODE_AREA_TYPE[hoverModeArea];
8136         }
8137     }
8138 
8139     auto widthValue = paramObj->GetProperty("width");
8140     CalcDimension width;
8141     if (ParseJsDimensionVpNG(widthValue, width, true)) {
8142         sheetStyle.width = width;
8143     }
8144 
8145     CalcDimension sheetHeight;
8146     if (height->IsString()) {
8147         std::string heightStr = height->ToString();
8148         // Remove all " ".
8149         heightStr.erase(std::remove(heightStr.begin(), heightStr.end(), ' '), heightStr.end());
8150         std::transform(heightStr.begin(), heightStr.end(), heightStr.begin(), ::tolower);
8151         if (heightStr == SHEET_HEIGHT_MEDIUM) {
8152             sheetStyle.sheetMode = NG::SheetMode::MEDIUM;
8153             sheetStyle.height.reset();
8154             return;
8155         }
8156         if (heightStr == SHEET_HEIGHT_LARGE) {
8157             sheetStyle.sheetMode = NG::SheetMode::LARGE;
8158             sheetStyle.height.reset();
8159             return;
8160         }
8161         if (heightStr == SHEET_HEIGHT_FITCONTENT) {
8162             sheetStyle.sheetMode = NG::SheetMode::AUTO;
8163             sheetStyle.height.reset();
8164             return;
8165         }
8166         if (heightStr.find("calc") != std::string::npos) {
8167             sheetHeight = CalcDimension(heightStr, DimensionUnit::CALC);
8168         } else {
8169             sheetHeight = StringUtils::StringToDimensionWithUnit(heightStr, DimensionUnit::VP, -1.0);
8170         }
8171         if (sheetHeight.Value() < 0) {
8172             sheetStyle.sheetMode = NG::SheetMode::LARGE;
8173             sheetStyle.height.reset();
8174             return;
8175         }
8176     }
8177     if (!ParseJsDimensionVpNG(height, sheetHeight)) {
8178         if (isPartialUpdate) {
8179             sheetStyle.sheetMode.reset();
8180         } else {
8181             sheetStyle.sheetMode = NG::SheetMode::LARGE;
8182         }
8183         sheetStyle.height.reset();
8184     } else {
8185         sheetStyle.height = sheetHeight;
8186         sheetStyle.sheetMode.reset();
8187     }
8188 }
8189 
ParseSheetDetents(const JSRef<JSVal> & args,std::vector<NG::SheetHeight> & sheetDetents)8190 bool JSViewAbstract::ParseSheetDetents(const JSRef<JSVal>& args, std::vector<NG::SheetHeight>& sheetDetents)
8191 {
8192     if (!args->IsArray()) {
8193         return false;
8194     }
8195     JSRef<JSArray> array = JSRef<JSArray>::Cast(args);
8196     NG::SheetHeight sheetDetent;
8197     for (size_t i = 0; i < array->Length(); i++) {
8198         ParseSheetDetentHeight(array->GetValueAt(i), sheetDetent);
8199         if ((!sheetDetent.height.has_value()) && (!sheetDetent.sheetMode.has_value())) {
8200             continue;
8201         }
8202         sheetDetents.emplace_back(sheetDetent);
8203         sheetDetent.height.reset();
8204         sheetDetent.sheetMode.reset();
8205     }
8206     return true;
8207 }
8208 
ParseSheetDetentHeight(const JSRef<JSVal> & args,NG::SheetHeight & detent)8209 void JSViewAbstract::ParseSheetDetentHeight(const JSRef<JSVal>& args, NG::SheetHeight& detent)
8210 {
8211     CalcDimension sheetHeight;
8212     if (args->IsString()) {
8213         std::string heightStr = args->ToString();
8214         // Remove all " ".
8215         heightStr.erase(std::remove(heightStr.begin(), heightStr.end(), ' '), heightStr.end());
8216         std::transform(heightStr.begin(), heightStr.end(), heightStr.begin(), ::tolower);
8217         if (heightStr == SHEET_HEIGHT_MEDIUM) {
8218             detent.sheetMode = NG::SheetMode::MEDIUM;
8219             detent.height.reset();
8220             return;
8221         }
8222         if (heightStr == SHEET_HEIGHT_LARGE) {
8223             detent.sheetMode = NG::SheetMode::LARGE;
8224             detent.height.reset();
8225             return;
8226         }
8227         if (heightStr == SHEET_HEIGHT_FITCONTENT) {
8228             detent.sheetMode = NG::SheetMode::AUTO;
8229             detent.height.reset();
8230             return;
8231         }
8232         if (heightStr.find("calc") != std::string::npos) {
8233             sheetHeight = CalcDimension(heightStr, DimensionUnit::CALC);
8234         } else {
8235             sheetHeight = StringUtils::StringToDimensionWithUnit(heightStr, DimensionUnit::VP, -1.0);
8236         }
8237         if (sheetHeight.Value() < 0) {
8238             detent.sheetMode = NG::SheetMode::LARGE;
8239             detent.height.reset();
8240             return;
8241         }
8242     }
8243     if (!ParseJsDimensionVpNG(args, sheetHeight)) {
8244         detent.sheetMode = NG::SheetMode::LARGE;
8245         detent.height.reset();
8246     } else {
8247         detent.height = sheetHeight;
8248         detent.sheetMode.reset();
8249     }
8250 }
8251 
ParseSheetBackgroundBlurStyle(const JSRef<JSVal> & args,BlurStyleOption & blurStyleOptions)8252 bool JSViewAbstract::ParseSheetBackgroundBlurStyle(const JSRef<JSVal>& args, BlurStyleOption& blurStyleOptions)
8253 {
8254     if (args->IsNumber()) {
8255         auto sheetBlurStyle = args->ToNumber<int32_t>();
8256         if (sheetBlurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
8257             sheetBlurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
8258             blurStyleOptions.blurStyle = static_cast<BlurStyle>(sheetBlurStyle);
8259         } else {
8260             return false;
8261         }
8262     } else {
8263         return false;
8264     }
8265     return true;
8266 }
8267 
ParseSheetLevel(const JSRef<JSVal> & args,NG::SheetLevel & sheetLevel)8268 bool JSViewAbstract::ParseSheetLevel(const JSRef<JSVal>& args, NG::SheetLevel& sheetLevel)
8269 {
8270     if (!args->IsNumber()) {
8271         return false;
8272     }
8273     auto sheetMode = args->ToNumber<int32_t>();
8274     if (sheetMode >= static_cast<int>(NG::SheetLevel::OVERLAY) &&
8275         sheetMode <= static_cast<int>(NG::SheetLevel::EMBEDDED)) {
8276         sheetLevel = static_cast<NG::SheetLevel>(sheetMode);
8277         return true;
8278     }
8279     return false;
8280 }
8281 
ParseCallback(const JSRef<JSObject> & paramObj,std::function<void (const float)> & callbackDidChange,const char * prop)8282 void JSViewAbstract::ParseCallback(const JSRef<JSObject>& paramObj,
8283     std::function<void(const float)>& callbackDidChange, const char* prop)
8284 {
8285     auto callBack = paramObj->GetProperty(prop);
8286     if (callBack->IsFunction()) {
8287         RefPtr<JsFunction> jsFunc =
8288             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(callBack));
8289         callbackDidChange = [func = std::move(jsFunc)](int32_t value) {
8290             JSRef<JSVal> param = JSRef<JSVal>::Make(ToJSValue(value));
8291             func->ExecuteJS(1, &param);
8292         };
8293     }
8294 }
8295 
ParseLifeCycleCallback(const JSRef<JSObject> & paramObj,std::function<void ()> & lifeCycleCallBack,const char * prop)8296 void JSViewAbstract::ParseLifeCycleCallback(const JSRef<JSObject>& paramObj,
8297     std::function<void()>& lifeCycleCallBack, const char* prop)
8298 {
8299     auto callback = paramObj->GetProperty(prop);
8300     if (callback->IsFunction()) {
8301         RefPtr<JsFunction> jsFunc =
8302             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(callback));
8303         lifeCycleCallBack = [func = std::move(jsFunc)]() { func->Execute(); };
8304     }
8305 }
8306 
ParseSpringBackCallback(const JSRef<JSObject> & paramObj,std::function<void ()> & sheetSpringBack,const char * prop)8307 void JSViewAbstract::ParseSpringBackCallback(const JSRef<JSObject>& paramObj,
8308     std::function<void()>& sheetSpringBack, const char* prop)
8309 {
8310     auto sheetSpringBackCallback = paramObj->GetProperty(prop);
8311     if (sheetSpringBackCallback->IsFunction()) {
8312         RefPtr<JsFunction> jsFunc =
8313             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(sheetSpringBackCallback));
8314         sheetSpringBack = [func = std::move(jsFunc)]() {
8315             JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
8316             objectTemplate->SetInternalFieldCount(1);
8317             JSRef<JSObject> dismissObj = objectTemplate->NewInstance();
8318             dismissObj->SetPropertyObject(
8319                 "springBack", JSRef<JSFunc>::New<FunctionCallback>(JSViewAbstract::JsSheetSpringBack));
8320             JSRef<JSVal> newJSVal = JSRef<JSObject>::Cast(dismissObj);
8321             func->ExecuteJS(1, &newJSVal);
8322         };
8323     }
8324 }
8325 
ParseSheetCallback(const JSRef<JSObject> & paramObj,std::function<void ()> & onAppear,std::function<void ()> & onDisappear,std::function<void ()> & shouldDismiss,std::function<void (const int32_t info)> & onWillDismiss,std::function<void ()> & onWillAppear,std::function<void ()> & onWillDisappear,std::function<void (const float)> & onHeightDidChange,std::function<void (const float)> & onDetentsDidChange,std::function<void (const float)> & onWidthDidChange,std::function<void (const float)> & onTypeDidChange,std::function<void ()> & sheetSpringBack)8326 void JSViewAbstract::ParseSheetCallback(const JSRef<JSObject>& paramObj, std::function<void()>& onAppear,
8327     std::function<void()>& onDisappear, std::function<void()>& shouldDismiss,
8328     std::function<void(const int32_t info)>& onWillDismiss, std::function<void()>& onWillAppear,
8329     std::function<void()>& onWillDisappear, std::function<void(const float)>& onHeightDidChange,
8330     std::function<void(const float)>& onDetentsDidChange,
8331     std::function<void(const float)>& onWidthDidChange,
8332     std::function<void(const float)>& onTypeDidChange, std::function<void()>& sheetSpringBack)
8333 {
8334     auto shouldDismissFunc = paramObj->GetProperty("shouldDismiss");
8335     auto onWillDismissFunc = paramObj->GetProperty("onWillDismiss");
8336     ParseLifeCycleCallback(paramObj, onAppear, "onAppear");
8337     ParseLifeCycleCallback(paramObj, onDisappear, "onDisappear");
8338     ParseLifeCycleCallback(paramObj, onWillAppear, "onWillAppear");
8339     ParseLifeCycleCallback(paramObj, onWillDisappear, "onWillDisappear");
8340     if (shouldDismissFunc->IsFunction()) {
8341         RefPtr<JsFunction> jsFunc =
8342             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(shouldDismissFunc));
8343         shouldDismiss = [func = std::move(jsFunc)]() {
8344             JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
8345             objectTemplate->SetInternalFieldCount(1);
8346             JSRef<JSObject> dismissObj = objectTemplate->NewInstance();
8347             dismissObj->SetPropertyObject(
8348                 "dismiss", JSRef<JSFunc>::New<FunctionCallback>(JSViewAbstract::JsDismissSheet));
8349             JSRef<JSVal> newJSVal = JSRef<JSObject>::Cast(dismissObj);
8350             func->ExecuteJS(1, &newJSVal);
8351         };
8352     }
8353     if (onWillDismissFunc->IsFunction()) {
8354         RefPtr<JsFunction> jsFunc =
8355             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillDismissFunc));
8356         onWillDismiss = [func = std::move(jsFunc)](const int32_t info) {
8357             JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
8358             objectTemplate->SetInternalFieldCount(1);
8359             JSRef<JSObject> dismissObj = objectTemplate->NewInstance();
8360             dismissObj->SetPropertyObject(
8361                 "dismiss", JSRef<JSFunc>::New<FunctionCallback>(JSViewAbstract::JsDismissSheet));
8362             dismissObj->SetProperty<int32_t>("reason", info);
8363             JSRef<JSVal> newJSVal = JSRef<JSObject>::Cast(dismissObj);
8364             func->ExecuteJS(1, &newJSVal);
8365         };
8366     }
8367     ParseSpringBackCallback(paramObj, sheetSpringBack, "onWillSpringBackWhenDismiss");
8368     ParseCallback(paramObj, onHeightDidChange, "onHeightDidChange");
8369     ParseCallback(paramObj, onDetentsDidChange, "onDetentsDidChange");
8370     ParseCallback(paramObj, onWidthDidChange, "onWidthDidChange");
8371     ParseCallback(paramObj, onTypeDidChange, "onTypeDidChange");
8372 }
8373 
ParseSheetTitle(const JSRef<JSObject> & paramObj,NG::SheetStyle & sheetStyle,std::function<void ()> & titleBuilderFunction)8374 void JSViewAbstract::ParseSheetTitle(
8375     const JSRef<JSObject>& paramObj, NG::SheetStyle& sheetStyle, std::function<void()>& titleBuilderFunction)
8376 {
8377     auto title = paramObj->GetProperty("title");
8378     std::string mainTitle;
8379     std::string subtitle;
8380     if (title->IsFunction()) {
8381         sheetStyle.isTitleBuilder = true;
8382         auto titleBuilderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(title));
8383         CHECK_NULL_VOID(titleBuilderFunc);
8384         titleBuilderFunction = [func = std::move(titleBuilderFunc)]() {
8385             ACE_SCORING_EVENT("BindSheet");
8386             func->Execute();
8387         };
8388     } else if (title->IsObject()) {
8389         JSRef<JSObject> obj = JSRef<JSObject>::Cast(title);
8390         sheetStyle.isTitleBuilder = false;
8391         auto sheetTitle = obj->GetProperty("title");
8392         auto sheetSubtitle = obj->GetProperty("subtitle");
8393         if (ParseJsString(sheetTitle, mainTitle)) {
8394             sheetStyle.sheetTitle = mainTitle;
8395         }
8396         if (ParseJsString(sheetSubtitle, subtitle)) {
8397             sheetStyle.sheetSubtitle = subtitle;
8398         }
8399     }
8400 }
8401 
JsDismissSheet(panda::JsiRuntimeCallInfo * runtimeCallInfo)8402 panda::Local<panda::JSValueRef> JSViewAbstract::JsDismissSheet(panda::JsiRuntimeCallInfo* runtimeCallInfo)
8403 {
8404     ViewAbstractModel::GetInstance()->DismissSheet();
8405     return JSValueRef::Undefined(runtimeCallInfo->GetVM());
8406 }
8407 
JsDismissContentCover(panda::JsiRuntimeCallInfo * runtimeCallInfo)8408 panda::Local<panda::JSValueRef> JSViewAbstract::JsDismissContentCover(panda::JsiRuntimeCallInfo* runtimeCallInfo)
8409 {
8410     ViewAbstractModel::GetInstance()->DismissContentCover();
8411     return JSValueRef::Undefined(runtimeCallInfo->GetVM());
8412 }
8413 
JsSheetSpringBack(panda::JsiRuntimeCallInfo * runtimeCallInfo)8414 panda::Local<panda::JSValueRef> JSViewAbstract::JsSheetSpringBack(panda::JsiRuntimeCallInfo* runtimeCallInfo)
8415 {
8416     ViewAbstractModel::GetInstance()->SheetSpringBack();
8417     return JSValueRef::Undefined(runtimeCallInfo->GetVM());
8418 }
8419 
ParseOverlayCallback(const JSRef<JSObject> & paramObj,std::function<void ()> & onAppear,std::function<void ()> & onDisappear,std::function<void ()> & onWillAppear,std::function<void ()> & onWillDisappear,std::function<void (const int32_t & info)> & onWillDismiss)8420 void JSViewAbstract::ParseOverlayCallback(const JSRef<JSObject>& paramObj, std::function<void()>& onAppear,
8421     std::function<void()>& onDisappear, std::function<void()>& onWillAppear, std::function<void()>& onWillDisappear,
8422     std::function<void(const int32_t& info)>& onWillDismiss)
8423 {
8424     auto showCallback = paramObj->GetProperty("onAppear");
8425     auto dismissCallback = paramObj->GetProperty("onDisappear");
8426     auto willShowCallback = paramObj->GetProperty("onWillAppear");
8427     auto willDismissCallback = paramObj->GetProperty("onWillDisappear");
8428     auto onWillDismissFunc = paramObj->GetProperty("onWillDismiss");
8429     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
8430     if (showCallback->IsFunction()) {
8431         RefPtr<JsFunction> jsFunc =
8432             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(showCallback));
8433         onAppear = [func = std::move(jsFunc), node = frameNode]() {
8434             PipelineContext::SetCallBackNode(node);
8435             func->Execute();
8436         };
8437     }
8438     if (dismissCallback->IsFunction()) {
8439         RefPtr<JsFunction> jsFunc =
8440             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(dismissCallback));
8441         onDisappear = [func = std::move(jsFunc), node = frameNode]() {
8442             PipelineContext::SetCallBackNode(node);
8443             func->Execute();
8444         };
8445     }
8446     if (willShowCallback->IsFunction()) {
8447         RefPtr<JsFunction> jsFunc =
8448             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(willShowCallback));
8449         onWillAppear = [func = std::move(jsFunc)]() { func->Execute(); };
8450     }
8451     if (willDismissCallback->IsFunction()) {
8452         RefPtr<JsFunction> jsFunc =
8453             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(willDismissCallback));
8454         onWillDisappear = [func = std::move(jsFunc)]() { func->Execute(); };
8455     }
8456     if (onWillDismissFunc->IsFunction()) {
8457         RefPtr<JsFunction> jsFunc =
8458             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillDismissFunc));
8459         onWillDismiss = [func = std::move(jsFunc), node = frameNode](const int32_t& info) {
8460             ACE_SCORING_EVENT("contentCover.dismiss");
8461             PipelineContext::SetCallBackNode(node);
8462             JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
8463             objectTemplate->SetInternalFieldCount(1);
8464             JSRef<JSObject> dismissObj = objectTemplate->NewInstance();
8465             dismissObj->SetPropertyObject(
8466                 "dismiss", JSRef<JSFunc>::New<FunctionCallback>(JSViewAbstract::JsDismissContentCover));
8467             dismissObj->SetProperty<int32_t>("reason", info);
8468             JSRef<JSVal> newJSVal = JSRef<JSObject>::Cast(dismissObj);
8469             func->ExecuteJS(1, &newJSVal);
8470         };
8471     }
8472 }
8473 
JSCreateAnimatableProperty(const JSCallbackInfo & info)8474 void JSViewAbstract::JSCreateAnimatableProperty(const JSCallbackInfo& info)
8475 {
8476     if (info.Length() < 3 || !info[0]->IsString()) { /* 3:args number */
8477         return;
8478     }
8479 
8480     JSRef<JSVal> callback = info[2]; /* 2:args index */
8481     if (!callback->IsFunction()) {
8482         return;
8483     }
8484     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
8485     std::string propertyName = info[0]->ToString();
8486     if (info[1]->IsNumber()) {
8487         float numValue = info[1]->ToNumber<float>();
8488         std::function<void(float)> onCallbackEvent;
8489         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(callback));
8490         onCallbackEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), id = Container::CurrentId(),
8491                               node = frameNode](const float val) {
8492             ContainerScope scope(id);
8493             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
8494             auto newJSVal = JSRef<JSVal>::Make(ToJSValue(val));
8495             PipelineContext::SetCallBackNode(node);
8496             func->ExecuteJS(1, &newJSVal);
8497         };
8498         ViewAbstractModel::GetInstance()->CreateAnimatablePropertyFloat(propertyName, numValue, onCallbackEvent);
8499     } else if (info[1]->IsObject()) {
8500         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
8501         RefPtr<JSAnimatableArithmetic> animatableArithmeticImpl =
8502             AceType::MakeRefPtr<JSAnimatableArithmetic>(obj, info.GetExecutionContext());
8503         RefPtr<CustomAnimatableArithmetic> animatableArithmetic =
8504             AceType::DynamicCast<CustomAnimatableArithmetic>(animatableArithmeticImpl);
8505         std::function<void(const RefPtr<NG::CustomAnimatableArithmetic>&)> onCallbackEvent;
8506         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(callback));
8507         onCallbackEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), id = Container::CurrentId(),
8508                               node = frameNode](const RefPtr<NG::CustomAnimatableArithmetic>& value) {
8509             ContainerScope scope(id);
8510             RefPtr<JSAnimatableArithmetic> impl = AceType::DynamicCast<JSAnimatableArithmetic>(value);
8511             if (!impl) {
8512                 return;
8513             }
8514             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
8515             auto newJSVal = JSRef<JSVal>(impl->GetObject());
8516             PipelineContext::SetCallBackNode(node);
8517             func->ExecuteJS(1, &newJSVal);
8518         };
8519         ViewAbstractModel::GetInstance()->CreateAnimatableArithmeticProperty(
8520             propertyName, animatableArithmetic, onCallbackEvent);
8521     }
8522 }
8523 
JSUpdateAnimatableProperty(const JSCallbackInfo & info)8524 void JSViewAbstract::JSUpdateAnimatableProperty(const JSCallbackInfo& info)
8525 {
8526     if (info.Length() < 2 || !info[0]->IsString()) { /* 2:args number */
8527         return;
8528     }
8529 
8530     std::string propertyName = info[0]->ToString();
8531     float numValue = 0.0;
8532     if (info[1]->IsNumber()) {
8533         numValue = info[1]->ToNumber<float>();
8534         ViewAbstractModel::GetInstance()->UpdateAnimatablePropertyFloat(propertyName, numValue);
8535     } else if (info[1]->IsObject()) {
8536         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
8537         RefPtr<JSAnimatableArithmetic> animatableArithmeticImpl =
8538             AceType::MakeRefPtr<JSAnimatableArithmetic>(obj, info.GetExecutionContext());
8539         RefPtr<CustomAnimatableArithmetic> animatableArithmetic =
8540             AceType::DynamicCast<CustomAnimatableArithmetic>(animatableArithmeticImpl);
8541         ViewAbstractModel::GetInstance()->UpdateAnimatableArithmeticProperty(propertyName, animatableArithmetic);
8542     }
8543 }
8544 
JsExpandSafeArea(const JSCallbackInfo & info)8545 void JSViewAbstract::JsExpandSafeArea(const JSCallbackInfo& info)
8546 {
8547     NG::SafeAreaExpandOpts opts { .type = NG::SAFE_AREA_TYPE_ALL, .edges = NG::SAFE_AREA_EDGE_ALL };
8548     if (info.Length() >= 1 && info[0]->IsArray()) {
8549         auto paramArray = JSRef<JSArray>::Cast(info[0]);
8550         uint32_t safeAreaType = NG::SAFE_AREA_TYPE_NONE;
8551         for (size_t i = 0; i < paramArray->Length(); ++i) {
8552             if (!paramArray->GetValueAt(i)->IsNumber() ||
8553                 paramArray->GetValueAt(i)->ToNumber<uint32_t>() >= SAFE_AREA_TYPE_LIMIT) {
8554                 safeAreaType = NG::SAFE_AREA_TYPE_ALL;
8555                 break;
8556             }
8557             safeAreaType |= (1 << paramArray->GetValueAt(i)->ToNumber<uint32_t>());
8558         }
8559         opts.type = safeAreaType;
8560     }
8561     if (info.Length() >= 2 && info[1]->IsArray()) {
8562         auto paramArray = JSRef<JSArray>::Cast(info[1]);
8563         uint32_t safeAreaEdge = NG::SAFE_AREA_EDGE_NONE;
8564         for (size_t i = 0; i < paramArray->Length(); ++i) {
8565             if (!paramArray->GetValueAt(i)->IsNumber() ||
8566                 paramArray->GetValueAt(i)->ToNumber<uint32_t>() >= SAFE_AREA_EDGE_LIMIT) {
8567                 safeAreaEdge = NG::SAFE_AREA_EDGE_ALL;
8568                 break;
8569             }
8570             safeAreaEdge |= (1 << paramArray->GetValueAt(i)->ToNumber<uint32_t>());
8571         }
8572         opts.edges = safeAreaEdge;
8573     }
8574 
8575     ViewAbstractModel::GetInstance()->UpdateSafeAreaExpandOpts(opts);
8576 }
8577 
ParseJSLightSource(JSRef<JSObject> & lightSource)8578 void ParseJSLightSource(JSRef<JSObject>& lightSource)
8579 {
8580     if (lightSource->IsUndefined()) {
8581         return;
8582     }
8583     JSRef<JSVal> positionX = lightSource->GetProperty("positionX");
8584     JSRef<JSVal> positionY = lightSource->GetProperty("positionY");
8585     JSRef<JSVal> positionZ = lightSource->GetProperty("positionZ");
8586     JSRef<JSVal> intensity = lightSource->GetProperty("intensity");
8587     JSRef<JSVal> color = lightSource->GetProperty("color");
8588 
8589     CalcDimension dimPositionX;
8590     CalcDimension dimPositionY;
8591     CalcDimension dimPositionZ;
8592     if (JSViewAbstract::ParseJsDimensionVp(positionX, dimPositionX) &&
8593         JSViewAbstract::ParseJsDimensionVp(positionY, dimPositionY) &&
8594         JSViewAbstract::ParseJsDimensionVp(positionZ, dimPositionZ)) {
8595         ViewAbstractModel::GetInstance()->SetLightPosition(dimPositionX, dimPositionY, dimPositionZ);
8596     }
8597 
8598     if (intensity->IsNumber()) {
8599         float intensityValue = intensity->ToNumber<float>();
8600         ViewAbstractModel::GetInstance()->SetLightIntensity(intensityValue);
8601     }
8602 
8603     Color lightColor;
8604     if (JSViewAbstract::ParseJsColor(color, lightColor)) {
8605         ViewAbstractModel::GetInstance()->SetLightColor(lightColor);
8606     }
8607 }
8608 
JsPointLight(const JSCallbackInfo & info)8609 void JSViewAbstract::JsPointLight(const JSCallbackInfo& info)
8610 {
8611 #ifdef POINT_LIGHT_ENABLE
8612     if (!info[0]->IsObject()) {
8613         return;
8614     }
8615 
8616     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
8617     JSRef<JSObject> lightSource = object->GetProperty("lightSource");
8618     ParseJSLightSource(lightSource);
8619 
8620     auto resourceWrapper = CreateResourceWrapper();
8621     if (!resourceWrapper) {
8622         return;
8623     }
8624     double bloomRadius = resourceWrapper->GetDoubleByName(BLOOM_RADIUS_SYS_RES_NAME);
8625     Color bloomColor = resourceWrapper->GetColorByName(BLOOM_COLOR_SYS_RES_NAME);
8626     Dimension illuminatedBorderWidth = resourceWrapper->GetDimensionByName(ILLUMINATED_BORDER_WIDTH_SYS_RES_NAME);
8627 
8628     JSRef<JSVal> illuminated = object->GetProperty("illuminated");
8629     if (illuminated->IsNumber()) {
8630         uint32_t illuminatedValue = illuminated->ToNumber<uint32_t>();
8631         ViewAbstractModel::GetInstance()->SetLightIlluminated(illuminatedValue);
8632         ViewAbstractModel::GetInstance()->SetIlluminatedBorderWidth(illuminatedBorderWidth);
8633     }
8634 
8635     JSRef<JSVal> bloom = object->GetProperty("bloom");
8636     if (bloom->IsNumber()) {
8637         float bloomValue = bloom->ToNumber<float>();
8638         ViewAbstractModel::GetInstance()->SetBloom(bloomValue);
8639 
8640         Shadow shadow;
8641         shadow.SetBlurRadius(bloomValue * bloomRadius);
8642         shadow.SetColor(bloomColor);
8643         std::vector<Shadow> shadows { shadow };
8644         ViewAbstractModel::GetInstance()->SetBackShadow(shadows);
8645     }
8646 #endif
8647 }
8648 
JsSetDragEventStrictReportingEnabled(const JSCallbackInfo & info)8649 void JSViewAbstract::JsSetDragEventStrictReportingEnabled(const JSCallbackInfo& info)
8650 {
8651     if (info[0]->IsBoolean()) {
8652         ViewAbstractModel::GetInstance()->SetDragEventStrictReportingEnabled(info[0]->ToBoolean());
8653     }
8654 }
8655 
JSBind(BindingTarget globalObj)8656 void JSViewAbstract::JSBind(BindingTarget globalObj)
8657 {
8658     JSClass<JSViewAbstract>::Declare("JSViewAbstract");
8659 
8660     // static methods
8661     MethodOptions opt = MethodOptions::NONE;
8662     JSClass<JSViewAbstract>::StaticMethod("pop", &JSViewAbstract::Pop, opt);
8663 
8664     JSClass<JSViewAbstract>::StaticMethod("width", &JSViewAbstract::JsWidth);
8665     JSClass<JSViewAbstract>::StaticMethod("height", &JSViewAbstract::JsHeight);
8666     JSClass<JSViewAbstract>::StaticMethod("responseRegion", &JSViewAbstract::JsResponseRegion);
8667     JSClass<JSViewAbstract>::StaticMethod("mouseResponseRegion", &JSViewAbstract::JsMouseResponseRegion);
8668     JSClass<JSViewAbstract>::StaticMethod("size", &JSViewAbstract::JsSize);
8669     JSClass<JSViewAbstract>::StaticMethod("constraintSize", &JSViewAbstract::JsConstraintSize);
8670     JSClass<JSViewAbstract>::StaticMethod("layoutPriority", &JSViewAbstract::JsLayoutPriority);
8671     JSClass<JSViewAbstract>::StaticMethod("pixelRound", &JSViewAbstract::JsPixelRound);
8672     JSClass<JSViewAbstract>::StaticMethod("layoutWeight", &JSViewAbstract::JsLayoutWeight);
8673     JSClass<JSViewAbstract>::StaticMethod("chainWeight", &JSViewAbstract::JsChainWeight);
8674 
8675     JSClass<JSViewAbstract>::StaticMethod("margin", &JSViewAbstract::JsMargin);
8676     JSClass<JSViewAbstract>::StaticMethod("marginTop", &JSViewAbstract::SetMarginTop, opt);
8677     JSClass<JSViewAbstract>::StaticMethod("marginBottom", &JSViewAbstract::SetMarginBottom, opt);
8678     JSClass<JSViewAbstract>::StaticMethod("marginLeft", &JSViewAbstract::SetMarginLeft, opt);
8679     JSClass<JSViewAbstract>::StaticMethod("marginRight", &JSViewAbstract::SetMarginRight, opt);
8680 
8681     JSClass<JSViewAbstract>::StaticMethod("padding", &JSViewAbstract::JsPadding);
8682     JSClass<JSViewAbstract>::StaticMethod("paddingTop", &JSViewAbstract::SetPaddingTop, opt);
8683     JSClass<JSViewAbstract>::StaticMethod("paddingBottom", &JSViewAbstract::SetPaddingBottom, opt);
8684     JSClass<JSViewAbstract>::StaticMethod("paddingLeft", &JSViewAbstract::SetPaddingLeft, opt);
8685     JSClass<JSViewAbstract>::StaticMethod("paddingRight", &JSViewAbstract::SetPaddingRight, opt);
8686     JSClass<JSViewAbstract>::StaticMethod("safeAreaPadding", &JSViewAbstract::SetSafeAreaPadding, opt);
8687 
8688     JSClass<JSViewAbstract>::StaticMethod("foregroundColor", &JSViewAbstract::JsForegroundColor);
8689     JSClass<JSViewAbstract>::StaticMethod("foregroundEffect", &JSViewAbstract::JsForegroundEffect);
8690     JSClass<JSViewAbstract>::StaticMethod("backgroundColor", &JSViewAbstract::JsBackgroundColor);
8691     JSClass<JSViewAbstract>::StaticMethod("backgroundImage", &JSViewAbstract::JsBackgroundImage);
8692     JSClass<JSViewAbstract>::StaticMethod("backgroundImageResizable", &JSViewAbstract::JsBackgroundImageResizable);
8693     JSClass<JSViewAbstract>::StaticMethod("backgroundImageSize", &JSViewAbstract::JsBackgroundImageSize);
8694     JSClass<JSViewAbstract>::StaticMethod("backgroundImagePosition", &JSViewAbstract::JsBackgroundImagePosition);
8695     JSClass<JSViewAbstract>::StaticMethod("backgroundBlurStyle", &JSViewAbstract::JsBackgroundBlurStyle);
8696     JSClass<JSViewAbstract>::StaticMethod("backgroundEffect", &JSViewAbstract::JsBackgroundEffect);
8697     JSClass<JSViewAbstract>::StaticMethod("foregroundBlurStyle", &JSViewAbstract::JsForegroundBlurStyle);
8698     JSClass<JSViewAbstract>::StaticMethod("lightUpEffect", &JSViewAbstract::JsLightUpEffect);
8699     JSClass<JSViewAbstract>::StaticMethod("sphericalEffect", &JSViewAbstract::JsSphericalEffect);
8700     JSClass<JSViewAbstract>::StaticMethod("pixelStretchEffect", &JSViewAbstract::JsPixelStretchEffect);
8701     JSClass<JSViewAbstract>::StaticMethod("outline", &JSViewAbstract::JsOutline);
8702     JSClass<JSViewAbstract>::StaticMethod("outlineWidth", &JSViewAbstract::JsOutlineWidth);
8703     JSClass<JSViewAbstract>::StaticMethod("outlineStyle", &JSViewAbstract::JsOutlineStyle);
8704     JSClass<JSViewAbstract>::StaticMethod("outlineColor", &JSViewAbstract::JsOutlineColor);
8705     JSClass<JSViewAbstract>::StaticMethod("outlineRadius", &JSViewAbstract::JsOutlineRadius);
8706     JSClass<JSViewAbstract>::StaticMethod("border", &JSViewAbstract::JsBorder);
8707     JSClass<JSViewAbstract>::StaticMethod("borderWidth", &JSViewAbstract::JsBorderWidth);
8708     JSClass<JSViewAbstract>::StaticMethod("borderColor", &JSViewAbstract::JsBorderColor);
8709     JSClass<JSViewAbstract>::StaticMethod("borderRadius", &JSViewAbstract::JsBorderRadius);
8710     JSClass<JSViewAbstract>::StaticMethod("borderStyle", &JSViewAbstract::JsBorderStyle);
8711     JSClass<JSViewAbstract>::StaticMethod("borderImage", &JSViewAbstract::JsBorderImage);
8712 
8713     JSClass<JSViewAbstract>::StaticMethod("scale", &JSViewAbstract::JsScale);
8714     JSClass<JSViewAbstract>::StaticMethod("scaleX", &JSViewAbstract::JsScaleX);
8715     JSClass<JSViewAbstract>::StaticMethod("scaleY", &JSViewAbstract::JsScaleY);
8716     JSClass<JSViewAbstract>::StaticMethod("opacity", &JSViewAbstract::JsOpacity);
8717     JSClass<JSViewAbstract>::StaticMethod("rotate", &JSViewAbstract::JsRotate);
8718     JSClass<JSViewAbstract>::StaticMethod("rotateX", &JSViewAbstract::JsRotateX);
8719     JSClass<JSViewAbstract>::StaticMethod("rotateY", &JSViewAbstract::JsRotateY);
8720     JSClass<JSViewAbstract>::StaticMethod("translate", &JSViewAbstract::JsTranslate);
8721     JSClass<JSViewAbstract>::StaticMethod("translateX", &JSViewAbstract::JsTranslateX);
8722     JSClass<JSViewAbstract>::StaticMethod("translateY", &JSViewAbstract::JsTranslateY);
8723     JSClass<JSViewAbstract>::StaticMethod("transform", &JSViewAbstract::JsTransform);
8724     JSClass<JSViewAbstract>::StaticMethod("transition", &JSViewAbstract::JsTransition);
8725 
8726     JSClass<JSViewAbstract>::StaticMethod("align", &JSViewAbstract::JsAlign);
8727     JSClass<JSViewAbstract>::StaticMethod("position", &JSViewAbstract::JsPosition);
8728     JSClass<JSViewAbstract>::StaticMethod("markAnchor", &JSViewAbstract::JsMarkAnchor);
8729     JSClass<JSViewAbstract>::StaticMethod("offset", &JSViewAbstract::JsOffset);
8730     JSClass<JSViewAbstract>::StaticMethod("enabled", &JSViewAbstract::JsEnabled);
8731     JSClass<JSViewAbstract>::StaticMethod("aspectRatio", &JSViewAbstract::JsAspectRatio);
8732     JSClass<JSViewAbstract>::StaticMethod("overlay", &JSViewAbstract::JsOverlay);
8733 
8734     JSClass<JSViewAbstract>::StaticMethod("blur", &JSViewAbstract::JsBlur);
8735     JSClass<JSViewAbstract>::StaticMethod("motionBlur", &JSViewAbstract::JsMotionBlur);
8736     JSClass<JSViewAbstract>::StaticMethod("useEffect", &JSViewAbstract::JsUseEffect);
8737     JSClass<JSViewAbstract>::StaticMethod("useShadowBatching", &JSViewAbstract::JsUseShadowBatching);
8738     JSClass<JSViewAbstract>::StaticMethod("colorBlend", &JSViewAbstract::JsColorBlend);
8739     JSClass<JSViewAbstract>::StaticMethod("backdropBlur", &JSViewAbstract::JsBackdropBlur);
8740     JSClass<JSViewAbstract>::StaticMethod("linearGradientBlur", &JSViewAbstract::JsLinearGradientBlur);
8741     JSClass<JSViewAbstract>::StaticMethod("backgroundBrightness", &JSViewAbstract::JsBackgroundBrightness);
8742     JSClass<JSViewAbstract>::StaticMethod("backgroundBrightnessInternal",
8743         &JSViewAbstract::JsBackgroundBrightnessInternal);
8744     JSClass<JSViewAbstract>::StaticMethod("foregroundBrightness", &JSViewAbstract::JsForegroundBrightness);
8745     JSClass<JSViewAbstract>::StaticMethod("windowBlur", &JSViewAbstract::JsWindowBlur);
8746     JSClass<JSViewAbstract>::StaticMethod("visibility", &JSViewAbstract::SetVisibility);
8747     JSClass<JSViewAbstract>::StaticMethod("flexBasis", &JSViewAbstract::JsFlexBasis);
8748     JSClass<JSViewAbstract>::StaticMethod("flexGrow", &JSViewAbstract::JsFlexGrow);
8749     JSClass<JSViewAbstract>::StaticMethod("flexShrink", &JSViewAbstract::JsFlexShrink);
8750     JSClass<JSViewAbstract>::StaticMethod("alignSelf", &JSViewAbstract::JsAlignSelf);
8751     JSClass<JSViewAbstract>::StaticMethod("displayPriority", &JSViewAbstract::JsDisplayPriority);
8752     JSClass<JSViewAbstract>::StaticMethod("useAlign", &JSViewAbstract::JsUseAlign);
8753     JSClass<JSViewAbstract>::StaticMethod("zIndex", &JSViewAbstract::JsZIndex);
8754     JSClass<JSViewAbstract>::StaticMethod("sharedTransition", &JSViewAbstract::JsSharedTransition);
8755     JSClass<JSViewAbstract>::StaticMethod("direction", &JSViewAbstract::SetDirection, opt);
8756 #ifndef WEARABLE_PRODUCT
8757     JSClass<JSViewAbstract>::StaticMethod("bindPopup", &JSViewAbstract::JsBindPopup);
8758 #endif
8759 
8760     JSClass<JSViewAbstract>::StaticMethod("background", &JSViewAbstract::JsBackground);
8761     JSClass<JSViewAbstract>::StaticMethod("bindMenu", &JSViewAbstract::JsBindMenu);
8762     JSClass<JSViewAbstract>::StaticMethod("bindContextMenu", &JSViewAbstract::JsBindContextMenu);
8763     JSClass<JSViewAbstract>::StaticMethod("bindContentCover", &JSViewAbstract::JsBindContentCover);
8764     JSClass<JSViewAbstract>::StaticMethod("bindSheet", &JSViewAbstract::JsBindSheet);
8765     JSClass<JSViewAbstract>::StaticMethod("draggable", &JSViewAbstract::JsSetDraggable);
8766     JSClass<JSViewAbstract>::StaticMethod("dragPreviewOptions", &JSViewAbstract::JsSetDragPreviewOptions);
8767     JSClass<JSViewAbstract>::StaticMethod("onPreDrag", &JSViewAbstract::JsOnPreDrag);
8768     JSClass<JSViewAbstract>::StaticMethod("onDragStart", &JSViewAbstract::JsOnDragStart);
8769     JSClass<JSViewAbstract>::StaticMethod("onDragEnter", &JSViewAbstract::JsOnDragEnter);
8770     JSClass<JSViewAbstract>::StaticMethod("onDragMove", &JSViewAbstract::JsOnDragMove);
8771     JSClass<JSViewAbstract>::StaticMethod("onDragLeave", &JSViewAbstract::JsOnDragLeave);
8772     JSClass<JSViewAbstract>::StaticMethod("onDrop", &JSViewAbstract::JsOnDrop);
8773     JSClass<JSViewAbstract>::StaticMethod("onDragEnd", &JSViewAbstract::JsOnDragEnd);
8774 
8775     JSClass<JSViewAbstract>::StaticMethod("linearGradient", &JSViewAbstract::JsLinearGradient);
8776     JSClass<JSViewAbstract>::StaticMethod("sweepGradient", &JSViewAbstract::JsSweepGradient);
8777     JSClass<JSViewAbstract>::StaticMethod("radialGradient", &JSViewAbstract::JsRadialGradient);
8778     JSClass<JSViewAbstract>::StaticMethod("motionPath", &JSViewAbstract::JsMotionPath);
8779     JSClass<JSViewAbstract>::StaticMethod("gridSpan", &JSViewAbstract::JsGridSpan);
8780     JSClass<JSViewAbstract>::StaticMethod("gridOffset", &JSViewAbstract::JsGridOffset);
8781     JSClass<JSViewAbstract>::StaticMethod("useSizeType", &JSViewAbstract::JsUseSizeType);
8782     JSClass<JSViewAbstract>::StaticMethod("shadow", &JSViewAbstract::JsShadow);
8783     JSClass<JSViewAbstract>::StaticMethod("blendMode", &JSViewAbstract::JsBlendMode);
8784     JSClass<JSViewAbstract>::StaticMethod("advancedBlendMode", &JSViewAbstract::JsAdvancedBlendMode);
8785     JSClass<JSViewAbstract>::StaticMethod("grayscale", &JSViewAbstract::JsGrayScale);
8786     JSClass<JSViewAbstract>::StaticMethod("focusable", &JSViewAbstract::JsFocusable);
8787     JSClass<JSViewAbstract>::StaticMethod("tabStop", &JSViewAbstract::JsTabStop);
8788     JSClass<JSViewAbstract>::StaticMethod("focusBox", &JSViewAbstract::JsFocusBox);
8789     JSClass<JSViewAbstract>::StaticMethod("onKeyEvent", &JSViewAbstract::JsOnKeyEvent);
8790     JSClass<JSViewAbstract>::StaticMethod("onKeyPreIme", &JSInteractableView::JsOnKeyPreIme);
8791     JSClass<JSViewAbstract>::StaticMethod("onFocusMove", &JSViewAbstract::JsOnFocusMove);
8792     JSClass<JSViewAbstract>::StaticMethod("onFocus", &JSViewAbstract::JsOnFocus);
8793     JSClass<JSViewAbstract>::StaticMethod("onBlur", &JSViewAbstract::JsOnBlur);
8794     JSClass<JSViewAbstract>::StaticMethod("tabIndex", &JSViewAbstract::JsTabIndex);
8795     JSClass<JSViewAbstract>::StaticMethod("focusOnTouch", &JSViewAbstract::JsFocusOnTouch);
8796     JSClass<JSViewAbstract>::StaticMethod("defaultFocus", &JSViewAbstract::JsDefaultFocus);
8797     JSClass<JSViewAbstract>::StaticMethod("groupDefaultFocus", &JSViewAbstract::JsGroupDefaultFocus);
8798     JSClass<JSViewAbstract>::StaticMethod("brightness", &JSViewAbstract::JsBrightness);
8799     JSClass<JSViewAbstract>::StaticMethod("contrast", &JSViewAbstract::JsContrast);
8800     JSClass<JSViewAbstract>::StaticMethod("saturate", &JSViewAbstract::JsSaturate);
8801     JSClass<JSViewAbstract>::StaticMethod("sepia", &JSViewAbstract::JsSepia);
8802     JSClass<JSViewAbstract>::StaticMethod("invert", &JSViewAbstract::JsInvert);
8803     JSClass<JSViewAbstract>::StaticMethod("systemBarEffect", &JSViewAbstract::JsSystemBarEffect);
8804     JSClass<JSViewAbstract>::StaticMethod("hueRotate", &JSViewAbstract::JsHueRotate);
8805     JSClass<JSViewAbstract>::StaticMethod("clip", &JSViewAbstract::JsClip);
8806     JSClass<JSViewAbstract>::StaticMethod("clipShape", &JSViewAbstract::JsClip);
8807     JSClass<JSViewAbstract>::StaticMethod("mask", &JSViewAbstract::JsMask);
8808     JSClass<JSViewAbstract>::StaticMethod("maskShape", &JSViewAbstract::JsMask);
8809     JSClass<JSViewAbstract>::StaticMethod("key", &JSViewAbstract::JsKey);
8810     JSClass<JSViewAbstract>::StaticMethod("id", &JSViewAbstract::JsId);
8811     JSClass<JSViewAbstract>::StaticMethod("restoreId", &JSViewAbstract::JsRestoreId);
8812     JSClass<JSViewAbstract>::StaticMethod("hoverEffect", &JSViewAbstract::JsHoverEffect);
8813     JSClass<JSViewAbstract>::StaticMethod("onMouse", &JSViewAbstract::JsOnMouse);
8814     JSClass<JSViewAbstract>::StaticMethod("onHover", &JSViewAbstract::JsOnHover);
8815     JSClass<JSViewAbstract>::StaticMethod("onAccessibilityHover", &JSViewAbstract::JsOnAccessibilityHover);
8816     JSClass<JSViewAbstract>::StaticMethod("onClick", &JSViewAbstract::JsOnClick);
8817     JSClass<JSViewAbstract>::StaticMethod("onGestureJudgeBegin", &JSViewAbstract::JsOnGestureJudgeBegin);
8818     JSClass<JSViewAbstract>::StaticMethod("onTouchIntercept", &JSViewAbstract::JsOnTouchIntercept);
8819     JSClass<JSViewAbstract>::StaticMethod(
8820         "shouldBuiltInRecognizerParallelWith", &JSViewAbstract::JsShouldBuiltInRecognizerParallelWith);
8821     JSClass<JSViewAbstract>::StaticMethod(
8822         "onGestureRecognizerJudgeBegin", &JSViewAbstract::JsOnGestureRecognizerJudgeBegin);
8823     JSClass<JSViewAbstract>::StaticMethod("clickEffect", &JSViewAbstract::JsClickEffect);
8824     JSClass<JSViewAbstract>::StaticMethod("debugLine", &JSViewAbstract::JsDebugLine);
8825     JSClass<JSViewAbstract>::StaticMethod("geometryTransition", &JSViewAbstract::JsGeometryTransition);
8826     JSClass<JSViewAbstract>::StaticMethod("onAreaChange", &JSViewAbstract::JsOnAreaChange);
8827     JSClass<JSViewAbstract>::StaticMethod("onSizeChange", &JSViewAbstract::JsOnSizeChange);
8828     JSClass<JSViewAbstract>::StaticMethod("touchable", &JSInteractableView::JsTouchable);
8829     JSClass<JSViewAbstract>::StaticMethod("monopolizeEvents", &JSInteractableView::JsMonopolizeEvents);
8830 
8831     JSClass<JSViewAbstract>::StaticMethod("accessibilityGroup", &JSViewAbstract::JsAccessibilityGroup);
8832     JSClass<JSViewAbstract>::StaticMethod("accessibilityText", &JSViewAbstract::JsAccessibilityText);
8833     JSClass<JSViewAbstract>::StaticMethod("accessibilityDescription", &JSViewAbstract::JsAccessibilityDescription);
8834     JSClass<JSViewAbstract>::StaticMethod("accessibilityImportance", &JSViewAbstract::JsAccessibilityImportance);
8835     JSClass<JSViewAbstract>::StaticMethod("accessibilityLevel", &JSViewAbstract::JsAccessibilityLevel);
8836     JSClass<JSViewAbstract>::StaticMethod("accessibilityVirtualNode", &JSViewAbstract::JsAccessibilityVirtualNode);
8837     JSClass<JSViewAbstract>::StaticMethod("onAccessibility", &JSInteractableView::JsOnAccessibility);
8838     JSClass<JSViewAbstract>::StaticMethod("accessibilitySelected", &JSViewAbstract::JsAccessibilitySelected);
8839     JSClass<JSViewAbstract>::StaticMethod("accessibilityChecked", &JSViewAbstract::JsAccessibilityChecked);
8840 
8841     JSClass<JSViewAbstract>::StaticMethod("alignRules", &JSViewAbstract::JsAlignRules);
8842     JSClass<JSViewAbstract>::StaticMethod("chainMode", &JSViewAbstract::JsChainMode);
8843     JSClass<JSViewAbstract>::StaticMethod("onVisibleAreaChange", &JSViewAbstract::JsOnVisibleAreaChange);
8844     JSClass<JSViewAbstract>::StaticMethod("hitTestBehavior", &JSViewAbstract::JsHitTestBehavior);
8845     JSClass<JSViewAbstract>::StaticMethod("onChildTouchTest", &JSViewAbstract::JsOnChildTouchTest);
8846     JSClass<JSViewAbstract>::StaticMethod("keyboardShortcut", &JSViewAbstract::JsKeyboardShortcut);
8847     JSClass<JSViewAbstract>::StaticMethod("obscured", &JSViewAbstract::JsObscured);
8848     JSClass<JSViewAbstract>::StaticMethod("privacySensitive", &JSViewAbstract::JsPrivacySensitive);
8849     JSClass<JSViewAbstract>::StaticMethod("allowDrop", &JSViewAbstract::JsAllowDrop);
8850     JSClass<JSViewAbstract>::StaticMethod("dragPreview", &JSViewAbstract::JsDragPreview);
8851     JSClass<JSViewAbstract>::StaticMethod("accessibilityTextHint", &JSViewAbstract::JsAccessibilityTextHint);
8852 
8853     JSClass<JSViewAbstract>::StaticMethod("createAnimatableProperty", &JSViewAbstract::JSCreateAnimatableProperty);
8854     JSClass<JSViewAbstract>::StaticMethod("updateAnimatableProperty", &JSViewAbstract::JSUpdateAnimatableProperty);
8855     JSClass<JSViewAbstract>::StaticMethod("renderGroup", &JSViewAbstract::JSRenderGroup);
8856     JSClass<JSViewAbstract>::StaticMethod("renderFit", &JSViewAbstract::JSRenderFit);
8857 
8858     JSClass<JSViewAbstract>::StaticMethod("freeze", &JSViewAbstract::JsSetFreeze);
8859 
8860     JSClass<JSViewAbstract>::StaticMethod("expandSafeArea", &JSViewAbstract::JsExpandSafeArea);
8861 
8862     JSClass<JSViewAbstract>::StaticMethod("drawModifier", &JSViewAbstract::JsDrawModifier);
8863     JSClass<JSViewAbstract>::StaticMethod("customProperty", &JSViewAbstract::JsCustomProperty);
8864     JSClass<JSViewAbstract>::StaticMethod("gestureModifier", &JSViewAbstract::JsGestureModifier);
8865 
8866     JSClass<JSViewAbstract>::StaticMethod(
8867         "setDragEventStrictReportingEnabled", &JSViewAbstract::JsSetDragEventStrictReportingEnabled);
8868 
8869     JSClass<JSViewAbstract>::StaticMethod("focusScopeId", &JSViewAbstract::JsFocusScopeId);
8870     JSClass<JSViewAbstract>::StaticMethod("focusScopePriority", &JSViewAbstract::JsFocusScopePriority);
8871 
8872     JSClass<JSViewAbstract>::StaticMethod("visualEffect", &JSViewAbstract::JsVisualEffect);
8873     JSClass<JSViewAbstract>::StaticMethod("backgroundFilter", &JSViewAbstract::JsBackgroundFilter);
8874     JSClass<JSViewAbstract>::StaticMethod("foregroundFilter", &JSViewAbstract::JsForegroundFilter);
8875     JSClass<JSViewAbstract>::StaticMethod("compositingFilter", &JSViewAbstract::JsCompositingFilter);
8876 
8877     JSClass<JSViewAbstract>::Bind(globalObj);
8878 }
8879 
AddInvalidateFunc(JSRef<JSObject> jsDrawModifier,NG::FrameNode * frameNode)8880 void AddInvalidateFunc(JSRef<JSObject> jsDrawModifier, NG::FrameNode* frameNode)
8881 {
8882     auto invalidate = [](panda::JsiRuntimeCallInfo* info) -> panda::Local<panda::JSValueRef> {
8883         auto vm = info->GetVM();
8884         CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm));
8885         Local<JSValueRef> thisObj = info->GetFunctionRef();
8886         auto thisObjRef = panda::Local<panda::ObjectRef>(thisObj);
8887         if (thisObjRef->GetNativePointerFieldCount(vm) < 1) {
8888             return panda::JSValueRef::Undefined(vm);
8889         }
8890 
8891         auto* weak = reinterpret_cast<NG::NativeWeakRef*>(thisObjRef->GetNativePointerField(vm, 0));
8892         if (weak->Invalid()) {
8893             return panda::JSValueRef::Undefined(vm);
8894         }
8895 
8896         auto frameNode = AceType::DynamicCast<NG::FrameNode>(weak->weakRef.Upgrade());
8897         if (frameNode) {
8898             const auto& extensionHandler = frameNode->GetExtensionHandler();
8899             if (extensionHandler) {
8900                 extensionHandler->InvalidateRender();
8901             } else {
8902                 frameNode->MarkDirtyNode(NG::PROPERTY_UPDATE_RENDER);
8903             }
8904         }
8905 
8906         return panda::JSValueRef::Undefined(vm);
8907     };
8908     auto jsInvalidate = JSRef<JSFunc>::New<FunctionCallback>(invalidate);
8909     if (frameNode) {
8910         const auto& extensionHandler = frameNode->GetExtensionHandler();
8911         if (extensionHandler) {
8912             extensionHandler->InvalidateRender();
8913         } else {
8914             frameNode->MarkDirtyNode(NG::PROPERTY_UPDATE_RENDER);
8915         }
8916     }
8917     auto vm = jsInvalidate->GetEcmaVM();
8918     auto* weak = new NG::NativeWeakRef(static_cast<AceType*>(frameNode));
8919     jsInvalidate->GetHandle()->SetNativePointerFieldCount(vm, 1);
8920     jsInvalidate->GetHandle()->SetNativePointerField(vm, 0, weak, &NG::DestructorInterceptor<NG::NativeWeakRef>);
8921     jsDrawModifier->SetPropertyObject("invalidate", jsInvalidate);
8922 }
8923 
JsDrawModifier(const JSCallbackInfo & info)8924 void JSViewAbstract::JsDrawModifier(const JSCallbackInfo& info)
8925 {
8926     if (!info[0]->IsObject()) {
8927         return;
8928     }
8929 
8930     auto frameNode = static_cast<NG::FrameNode*>(ViewAbstractModel::GetInstance()->GetFrameNode());
8931     bool IsSupportDrawModifier = frameNode && frameNode->IsSupportDrawModifier();
8932     if (!IsSupportDrawModifier) {
8933         return;
8934     }
8935     auto jsDrawModifier = JSRef<JSObject>::Cast(info[0]);
8936     RefPtr<NG::DrawModifier> drawModifier = AceType::MakeRefPtr<NG::DrawModifier>();
8937     auto execCtx = info.GetExecutionContext();
8938     auto getDrawModifierFunc = [execCtx, jsDrawModifier](const char* key) -> NG::DrawModifierFunc {
8939         JSRef<JSVal> drawMethod = jsDrawModifier->GetProperty(key);
8940         if (!drawMethod->IsFunction()) {
8941             return nullptr;
8942         }
8943 
8944         auto jsDrawFunc = AceType::MakeRefPtr<JsFunction>(
8945             JSRef<JSObject>(jsDrawModifier), JSRef<JSFunc>::Cast(drawMethod));
8946 
8947         return GetDrawCallback(jsDrawFunc, execCtx);
8948     };
8949 
8950     drawModifier->drawBehindFunc = getDrawModifierFunc("drawBehind");
8951     drawModifier->drawContentFunc = getDrawModifierFunc("drawContent");
8952     drawModifier->drawFrontFunc = getDrawModifierFunc("drawFront");
8953 
8954     ViewAbstractModel::GetInstance()->SetDrawModifier(drawModifier);
8955     AddInvalidateFunc(jsDrawModifier, frameNode);
8956 }
8957 
JsAllowDrop(const JSCallbackInfo & info)8958 void JSViewAbstract::JsAllowDrop(const JSCallbackInfo& info)
8959 {
8960     std::set<std::string> allowDropSet;
8961     allowDropSet.clear();
8962     if (!info[0]->IsUndefined() && info[0]->IsArray()) {
8963         auto allowDropArray = JSRef<JSArray>::Cast(info[0]);
8964         std::string allowDrop;
8965         for (size_t i = 0; i < allowDropArray->Length(); i++) {
8966             allowDrop = allowDropArray->GetValueAt(i)->ToString();
8967             allowDropSet.insert(allowDrop);
8968         }
8969         ViewAbstractModel::GetInstance()->SetDisallowDropForcedly(false);
8970     } else if (info[0]->IsNull()) {
8971         ViewAbstractModel::GetInstance()->SetDisallowDropForcedly(true);
8972     } else {
8973         ViewAbstractModel::GetInstance()->SetDisallowDropForcedly(false);
8974     }
8975     ViewAbstractModel::GetInstance()->SetAllowDrop(allowDropSet);
8976 }
8977 
JsOnPreDrag(const JSCallbackInfo & info)8978 void JSViewAbstract::JsOnPreDrag(const JSCallbackInfo& info)
8979 {
8980     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
8981     auto jsVal = info[0];
8982     if (!CheckJSCallbackInfo("JsOnPreDrag", jsVal, checkList)) {
8983         return;
8984     }
8985     RefPtr<JsDragFunction> jsDragFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(jsVal));
8986     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
8987     auto onPreDrag = [execCtx = info.GetExecutionContext(), func = std::move(jsDragFunc), node = frameNode](
8988                          const PreDragStatus preDragStatus) {
8989         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
8990         ACE_SCORING_EVENT("onPreDrag");
8991         PipelineContext::SetCallBackNode(node);
8992         func->PreDragExecute(preDragStatus);
8993     };
8994     ViewAbstractModel::GetInstance()->SetOnPreDrag(onPreDrag);
8995 }
8996 
JsDragPreview(const JSCallbackInfo & info)8997 void JSViewAbstract::JsDragPreview(const JSCallbackInfo& info)
8998 {
8999     auto jsVal = info[0];
9000     if ((!jsVal->IsObject()) && (!jsVal->IsString())) {
9001         return;
9002     }
9003     NG::DragDropInfo dragPreviewInfo;
9004     JSRef<JSVal> builder;
9005     JSRef<JSVal> pixelMap;
9006     JSRef<JSVal> extraInfo;
9007     if (jsVal->IsFunction()) {
9008         builder = jsVal;
9009     } else if (jsVal->IsObject()) {
9010         auto dragItemInfo = JSRef<JSObject>::Cast(jsVal);
9011         builder = dragItemInfo->GetProperty("builder");
9012 #if defined(PIXEL_MAP_SUPPORTED)
9013         pixelMap = dragItemInfo->GetProperty("pixelMap");
9014         dragPreviewInfo.pixelMap = CreatePixelMapFromNapiValue(pixelMap);
9015 #endif
9016         extraInfo = dragItemInfo->GetProperty("extraInfo");
9017         ParseJsString(extraInfo, dragPreviewInfo.extraInfo);
9018     } else if (jsVal->IsString()) {
9019         auto inspectorId = jsVal;
9020         ParseJsString(inspectorId, dragPreviewInfo.inspectorId);
9021     } else {
9022         return;
9023     }
9024 
9025     if (builder->IsFunction()) {
9026         RefPtr<JsFunction> builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
9027         if (builderFunc != nullptr) {
9028             ViewStackModel::GetInstance()->NewScope();
9029             {
9030                 ACE_SCORING_EVENT("dragPreview.builder");
9031                 builderFunc->Execute();
9032             }
9033             RefPtr<AceType> node = ViewStackModel::GetInstance()->Finish();
9034             dragPreviewInfo.customNode = AceType::DynamicCast<NG::UINode>(node);
9035         }
9036     }
9037     ViewAbstractModel::GetInstance()->SetDragPreview(dragPreviewInfo);
9038 }
9039 
JsAlignRules(const JSCallbackInfo & info)9040 void JSViewAbstract::JsAlignRules(const JSCallbackInfo& info)
9041 {
9042     if (!info[0]->IsObject()) {
9043         return;
9044     }
9045 
9046     JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(info[0]);
9047     if (valueObj->IsEmpty()) {
9048         return;
9049     }
9050     const char* keys[] = { "left", "middle", "right", "top", "center", "bottom", "bias", "start", "end" };
9051     std::map<AlignDirection, AlignRule> alignRules;
9052     BiasPair biasPair(DEFAULT_BIAS, DEFAULT_BIAS);
9053     for (uint32_t i = 0; i < sizeof(keys) / sizeof(const char*); i++) {
9054         auto rule = valueObj->GetProperty(keys[i]);
9055         if (rule->IsObject()) {
9056             JSRef<JSObject> val = JSRef<JSObject>::Cast(rule);
9057             JSRef<JSVal> align = val->GetProperty("align");
9058             AlignRule alignRule;
9059             alignRule.anchor = val->GetProperty("anchor")->ToString();
9060             if (i < HORIZONTAL_DIRECTION_RANGE) {
9061                 alignRule.horizontal = static_cast<HorizontalAlign>(val->GetProperty("align")->ToNumber<int32_t>());
9062             } else {
9063                 alignRule.vertical = static_cast<VerticalAlign>(val->GetProperty("align")->ToNumber<int32_t>());
9064             }
9065             if (i < VERTICAL_DIRECTION_RANGE) {
9066                 alignRules[static_cast<AlignDirection>(i)] = alignRule;
9067             } else if (i == HORIZONTAL_DIRECTION_START_INDEX) {
9068                 alignRules[AlignDirection::LEFT] = alignRule;
9069             } else if (i == HORIZONTAL_DIRECTION_END_INDEX) {
9070                 alignRules[AlignDirection::RIGHT] = alignRule;
9071             }
9072             auto biasX = val->GetProperty("horizontal");
9073             if (biasX->IsNumber()) {
9074                 biasPair.first = biasX->ToNumber<float>();
9075             }
9076             auto biasY = val->GetProperty("vertical");
9077             if (biasY->IsNumber()) {
9078                 biasPair.second = biasY->ToNumber<float>();
9079             }
9080         }
9081     }
9082 
9083     ViewAbstractModel::GetInstance()->SetAlignRules(alignRules);
9084     ViewAbstractModel::GetInstance()->SetBias(biasPair);
9085 }
9086 
JsChainMode(const JSCallbackInfo & info)9087 void JSViewAbstract::JsChainMode(const JSCallbackInfo& info)
9088 {
9089     ChainInfo chainInfo;
9090     if (info.Length() >= 1) {
9091         auto tmpDirection = info[0];
9092         if (tmpDirection->IsUndefined()) {
9093             chainInfo.direction = std::nullopt;
9094         } else if (tmpDirection->IsNumber()) {
9095             auto direction = tmpDirection->ToNumber<int32_t>();
9096             chainInfo.direction = static_cast<LineDirection>(direction);
9097         }
9098     }
9099 
9100     if (info.Length() >= 2) { // 2 : two args
9101         auto tmpStyle = info[1];
9102         if (tmpStyle->IsUndefined()) {
9103             chainInfo.style = std::nullopt;
9104         } else if (tmpStyle->IsNumber()) {
9105             auto style = tmpStyle->ToNumber<int32_t>();
9106             chainInfo.style = static_cast<ChainStyle>(style);
9107         }
9108     }
9109     ViewAbstractModel::GetInstance()->SetChainStyle(chainInfo);
9110 }
9111 
SetMarginTop(const JSCallbackInfo & info)9112 void JSViewAbstract::SetMarginTop(const JSCallbackInfo& info)
9113 {
9114     CalcDimension value;
9115     if (!ParseJsDimensionVp(info[0], value)) {
9116         return;
9117     }
9118     ViewAbstractModel::GetInstance()->SetMargins(value, std::nullopt, std::nullopt, std::nullopt);
9119 }
9120 
SetMarginBottom(const JSCallbackInfo & info)9121 void JSViewAbstract::SetMarginBottom(const JSCallbackInfo& info)
9122 {
9123     CalcDimension value;
9124     if (!ParseJsDimensionVp(info[0], value)) {
9125         return;
9126     }
9127     ViewAbstractModel::GetInstance()->SetMargins(std::nullopt, value, std::nullopt, std::nullopt);
9128 }
9129 
SetMarginLeft(const JSCallbackInfo & info)9130 void JSViewAbstract::SetMarginLeft(const JSCallbackInfo& info)
9131 {
9132     CalcDimension value;
9133     if (!ParseJsDimensionVp(info[0], value)) {
9134         return;
9135     }
9136     ViewAbstractModel::GetInstance()->SetMargins(std::nullopt, std::nullopt, value, std::nullopt);
9137 }
9138 
SetMarginRight(const JSCallbackInfo & info)9139 void JSViewAbstract::SetMarginRight(const JSCallbackInfo& info)
9140 {
9141     CalcDimension value;
9142     if (!ParseJsDimensionVp(info[0], value)) {
9143         return;
9144     }
9145     ViewAbstractModel::GetInstance()->SetMargins(std::nullopt, std::nullopt, std::nullopt, value);
9146 }
9147 
SetPaddingTop(const JSCallbackInfo & info)9148 void JSViewAbstract::SetPaddingTop(const JSCallbackInfo& info)
9149 {
9150     CalcDimension value;
9151     if (!ParseJsDimensionVp(info[0], value)) {
9152         return;
9153     }
9154     ViewAbstractModel::GetInstance()->SetPaddings(value, std::nullopt, std::nullopt, std::nullopt);
9155 }
9156 
SetPaddingBottom(const JSCallbackInfo & info)9157 void JSViewAbstract::SetPaddingBottom(const JSCallbackInfo& info)
9158 {
9159     CalcDimension value;
9160     if (!ParseJsDimensionVp(info[0], value)) {
9161         return;
9162     }
9163     ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, value, std::nullopt, std::nullopt);
9164 }
9165 
SetPaddingLeft(const JSCallbackInfo & info)9166 void JSViewAbstract::SetPaddingLeft(const JSCallbackInfo& info)
9167 {
9168     CalcDimension value;
9169     if (!ParseJsDimensionVp(info[0], value)) {
9170         return;
9171     }
9172     ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, std::nullopt, value, std::nullopt);
9173 }
9174 
SetPaddingRight(const JSCallbackInfo & info)9175 void JSViewAbstract::SetPaddingRight(const JSCallbackInfo& info)
9176 {
9177     CalcDimension value;
9178     if (!ParseJsDimensionVp(info[0], value)) {
9179         return;
9180     }
9181     ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, std::nullopt, std::nullopt, value);
9182 }
9183 
SetSafeAreaPadding(const JSCallbackInfo & info)9184 void JSViewAbstract::SetSafeAreaPadding(const JSCallbackInfo& info)
9185 {
9186     ParseMarginOrPadding(info, EdgeType::SAFE_AREA_PADDING);
9187 }
9188 
SetColorBlend(Color color)9189 void JSViewAbstract::SetColorBlend(Color color)
9190 {
9191     ViewAbstractModel::GetInstance()->SetColorBlend(color);
9192 }
9193 
SetLinearGradientBlur(NG::LinearGradientBlurPara blurPara)9194 void JSViewAbstract::SetLinearGradientBlur(NG::LinearGradientBlurPara blurPara)
9195 {
9196     ViewAbstractModel::GetInstance()->SetLinearGradientBlur(blurPara);
9197 }
9198 
SetDynamicLightUp(float rate,float lightUpDegree)9199 void JSViewAbstract::SetDynamicLightUp(float rate, float lightUpDegree)
9200 {
9201     ViewAbstractModel::GetInstance()->SetDynamicLightUp(rate, lightUpDegree);
9202 }
9203 
SetBgDynamicBrightness(BrightnessOption brightnessOption)9204 void JSViewAbstract::SetBgDynamicBrightness(BrightnessOption brightnessOption)
9205 {
9206     ViewAbstractModel::GetInstance()->SetBgDynamicBrightness(brightnessOption);
9207 }
9208 
SetFgDynamicBrightness(BrightnessOption brightnessOption)9209 void JSViewAbstract::SetFgDynamicBrightness(BrightnessOption brightnessOption)
9210 {
9211     ViewAbstractModel::GetInstance()->SetFgDynamicBrightness(brightnessOption);
9212 }
9213 
SetWindowBlur(float progress,WindowBlurStyle blurStyle)9214 void JSViewAbstract::SetWindowBlur(float progress, WindowBlurStyle blurStyle)
9215 {
9216     ViewAbstractModel::GetInstance()->SetWindowBlur(progress, blurStyle);
9217 }
9218 
ParseJsonDimension(const std::unique_ptr<JsonValue> & jsonValue,CalcDimension & result,DimensionUnit defaultUnit,bool checkIllegal)9219 bool JSViewAbstract::ParseJsonDimension(
9220     const std::unique_ptr<JsonValue>& jsonValue, CalcDimension& result, DimensionUnit defaultUnit, bool checkIllegal)
9221 {
9222     if (!jsonValue || jsonValue->IsNull()) {
9223         return false;
9224     }
9225     if (!jsonValue->IsNumber() && !jsonValue->IsString() && !jsonValue->IsObject()) {
9226         return false;
9227     }
9228     if (jsonValue->IsNumber()) {
9229         result = Dimension(jsonValue->GetDouble(), defaultUnit);
9230         return true;
9231     }
9232     if (jsonValue->IsString()) {
9233         if (checkIllegal) {
9234             return StringUtils::StringToDimensionWithUnitNG(jsonValue->GetString(), result, defaultUnit);
9235         }
9236         result = StringUtils::StringToCalcDimension(jsonValue->GetString(), false, defaultUnit);
9237         return true;
9238     }
9239     auto resVal = JsonUtil::ParseJsonString(jsonValue->ToString());
9240     auto resId = resVal->GetValue("id");
9241     if (!resId || !resId->IsNumber()) {
9242         return false;
9243     }
9244 
9245     auto resourceWrapper = CreateResourceWrapper();
9246     if (!resourceWrapper) {
9247         return false;
9248     }
9249     result = resourceWrapper->GetDimension(resId->GetUInt());
9250     return true;
9251 }
9252 
ParseJsonDimensionVp(const std::unique_ptr<JsonValue> & jsonValue,CalcDimension & result,bool checkIllegal)9253 bool JSViewAbstract::ParseJsonDimensionVp(
9254     const std::unique_ptr<JsonValue>& jsonValue, CalcDimension& result, bool checkIllegal)
9255 {
9256     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
9257         return ParseJsonDimension(jsonValue, result, DimensionUnit::VP, true);
9258     }
9259     return ParseJsonDimension(jsonValue, result, DimensionUnit::VP, checkIllegal);
9260 }
9261 
ParseJsonDouble(const std::unique_ptr<JsonValue> & jsonValue,double & result)9262 bool JSViewAbstract::ParseJsonDouble(const std::unique_ptr<JsonValue>& jsonValue, double& result)
9263 {
9264     if (!jsonValue || jsonValue->IsNull()) {
9265         return false;
9266     }
9267     if (!jsonValue->IsNumber() && !jsonValue->IsString() && !jsonValue->IsObject()) {
9268         return false;
9269     }
9270     if (jsonValue->IsNumber()) {
9271         result = jsonValue->GetDouble();
9272         return true;
9273     }
9274     if (jsonValue->IsString()) {
9275         result = StringUtils::StringToDouble(jsonValue->GetString());
9276         return true;
9277     }
9278     // parse json Resource
9279     auto resVal = JsonUtil::ParseJsonString(jsonValue->ToString());
9280     auto resId = resVal->GetValue("id");
9281     CHECK_NULL_RETURN(resId && resId->IsNumber(), false);
9282     auto id = resId->GetUInt();
9283     auto resType = resVal->GetValue("type");
9284     CHECK_NULL_RETURN(resType && resType->IsNumber(), false);
9285     auto type = resType->GetUInt();
9286 
9287     auto resourceWrapper = CreateResourceWrapper();
9288     if (!resourceWrapper) {
9289         return false;
9290     }
9291     if (type == static_cast<uint32_t>(ResourceType::STRING)) {
9292         auto numberString = resourceWrapper->GetString(id);
9293         return StringUtils::StringToDouble(numberString, result);
9294     }
9295     if (type == static_cast<uint32_t>(ResourceType::INTEGER)) {
9296         result = resourceWrapper->GetInt(id);
9297         return true;
9298     }
9299     if (type == static_cast<uint32_t>(ResourceType::FLOAT)) {
9300         result = resourceWrapper->GetDouble(id);
9301         return true;
9302     }
9303     return false;
9304 }
9305 
ParseJsonColor(const std::unique_ptr<JsonValue> & jsonValue,Color & result)9306 bool JSViewAbstract::ParseJsonColor(const std::unique_ptr<JsonValue>& jsonValue, Color& result)
9307 {
9308     if (!jsonValue || jsonValue->IsNull()) {
9309         return false;
9310     }
9311     if (!jsonValue->IsNumber() && !jsonValue->IsString() && !jsonValue->IsObject()) {
9312         return false;
9313     }
9314     if (jsonValue->IsNumber()) {
9315         result = Color(ColorAlphaAdapt(jsonValue->GetUInt()));
9316         return true;
9317     }
9318 
9319     bool isSetColor = false;
9320     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
9321         isSetColor = jsonValue->IsString();
9322     } else {
9323         isSetColor = jsonValue->IsString() && jsonValue->GetString() != "";
9324     }
9325     if (isSetColor) {
9326         result = Color::FromString(jsonValue->GetString());
9327         return true;
9328     }
9329     auto resVal = JsonUtil::ParseJsonString(jsonValue->ToString());
9330     auto resId = resVal->GetValue("id");
9331     if (!resId || !resId->IsNumber()) {
9332         return false;
9333     }
9334     auto resourceWrapper = CreateResourceWrapper();
9335     if (!resourceWrapper) {
9336         return false;
9337     }
9338     result = resourceWrapper->GetColor(resId->GetUInt());
9339     return true;
9340 }
9341 
ParseShadowOffsetX(const JSRef<JSObject> & jsObj,CalcDimension & offsetX,Shadow & shadow)9342 void JSViewAbstract::ParseShadowOffsetX(const JSRef<JSObject>& jsObj, CalcDimension& offsetX, Shadow& shadow)
9343 {
9344     auto jsOffsetX = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::OFFSET_X));
9345     bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
9346     if (ParseJsResource(jsOffsetX, offsetX)) {
9347         double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
9348         shadow.SetOffsetX(xValue);
9349     } else {
9350         if (ParseJsDimensionVp(jsOffsetX, offsetX)) {
9351             double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
9352             shadow.SetOffsetX(xValue);
9353         }
9354     }
9355 }
9356 
ParseShadowProps(const JSRef<JSVal> & jsValue,Shadow & shadow)9357 bool JSViewAbstract::ParseShadowProps(const JSRef<JSVal>& jsValue, Shadow& shadow)
9358 {
9359     int32_t shadowStyle = 0;
9360     if (ParseJsInteger<int32_t>(jsValue, shadowStyle)) {
9361         auto style = static_cast<ShadowStyle>(shadowStyle);
9362         return GetShadowFromTheme(style, shadow);
9363     }
9364     if (!jsValue->IsObject()) {
9365         return false;
9366     }
9367     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
9368     double radius = 0.0;
9369     ParseJsDouble(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::RADIUS)), radius);
9370     if (LessNotEqual(radius, 0.0)) {
9371         radius = 0.0;
9372     }
9373     shadow.SetBlurRadius(radius);
9374     CalcDimension offsetX;
9375     ParseShadowOffsetX(jsObj, offsetX, shadow);
9376     CalcDimension offsetY;
9377     auto jsOffsetY = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::OFFSET_Y));
9378     if (ParseJsResource(jsOffsetY, offsetY)) {
9379         shadow.SetOffsetY(offsetY.Value());
9380     } else {
9381         if (ParseJsDimensionVp(jsOffsetY, offsetY)) {
9382             shadow.SetOffsetY(offsetY.Value());
9383         }
9384     }
9385     Color color;
9386     ShadowColorStrategy shadowColorStrategy;
9387     auto jsColor = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR));
9388     if (ParseJsShadowColorStrategy(jsColor, shadowColorStrategy)) {
9389         shadow.SetShadowColorStrategy(shadowColorStrategy);
9390     } else if (ParseJsColor(jsColor, color)) {
9391         shadow.SetColor(color);
9392     }
9393     int32_t type = static_cast<int32_t>(ShadowType::COLOR);
9394     JSViewAbstract::ParseJsInt32(jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::TYPE)), type);
9395     if (type != static_cast<int32_t>(ShadowType::BLUR)) {
9396         type = static_cast<int32_t>(ShadowType::COLOR);
9397     }
9398     shadow.SetShadowType(static_cast<ShadowType>(type));
9399     bool isFilled = jsObj->GetPropertyValue<bool>(static_cast<int32_t>(ArkUIIndex::FILL), false);
9400     shadow.SetIsFilled(isFilled);
9401     return true;
9402 }
9403 
GetShadowFromTheme(ShadowStyle shadowStyle,Shadow & shadow)9404 bool JSViewAbstract::GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow)
9405 {
9406     auto colorMode = SystemProperties::GetColorMode();
9407     if (shadowStyle == ShadowStyle::None) {
9408         return true;
9409     }
9410 
9411     auto container = Container::Current();
9412     CHECK_NULL_RETURN(container, false);
9413     auto pipelineContext = container->GetPipelineContext();
9414     CHECK_NULL_RETURN(pipelineContext, false);
9415 
9416     auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
9417     if (!shadowTheme) {
9418         return false;
9419     }
9420 
9421     shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
9422     return true;
9423 }
9424 
ParseJsResource(const JSRef<JSVal> & jsValue,CalcDimension & result)9425 bool JSViewAbstract::ParseJsResource(const JSRef<JSVal>& jsValue, CalcDimension& result)
9426 {
9427     if (!jsValue->IsObject()) {
9428         return false;
9429     }
9430     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
9431     uint32_t type = jsObj->GetPropertyValue<uint32_t>(static_cast<int32_t>(ArkUIIndex::TYPE), 0);
9432     if (type == 0) {
9433         return false;
9434     }
9435     auto resourceWrapper = CreateResourceWrapper();
9436     CHECK_NULL_RETURN(resourceWrapper, false);
9437     if (type == static_cast<uint32_t>(ResourceType::STRING)) {
9438         auto value = resourceWrapper->GetString(
9439             jsObj->GetPropertyValue<uint32_t>(static_cast<int32_t>(ArkUIIndex::ID), 0));
9440         return StringUtils::StringToCalcDimensionNG(value, result, false);
9441     }
9442     if (type == static_cast<uint32_t>(ResourceType::INTEGER)) {
9443         auto value = std::to_string(
9444             resourceWrapper->GetInt(jsObj->GetPropertyValue<uint32_t>(static_cast<int32_t>(ArkUIIndex::ID), 0)));
9445         StringUtils::StringToDimensionWithUnitNG(value, result);
9446         return true;
9447     }
9448 
9449     if (type == static_cast<uint32_t>(ResourceType::FLOAT)) {
9450         result = resourceWrapper->GetDimension(
9451             jsObj->GetPropertyValue<uint32_t>(static_cast<int32_t>(ArkUIIndex::ID), 0));
9452         return true;
9453     }
9454     return false;
9455 }
9456 
ParseDataDetectorConfig(const JSCallbackInfo & info,TextDetectConfig & textDetectConfig)9457 bool JSViewAbstract::ParseDataDetectorConfig(const JSCallbackInfo& info, TextDetectConfig& textDetectConfig)
9458 {
9459     JSRef<JSVal> arg = info[0];
9460     if (!arg->IsObject()) {
9461         return false;
9462     }
9463     JSRef<JSObject> obj = JSRef<JSObject>::Cast(arg);
9464     JSRef<JSVal> typeValue = obj->GetProperty("types");
9465     if (!typeValue->IsArray()) {
9466         return false;
9467     }
9468     JSRef<JSArray> array = JSRef<JSArray>::Cast(typeValue);
9469     for (size_t i = 0; i < array->Length(); i++) {
9470         JSRef<JSVal> value = array->GetValueAt(i);
9471         auto index = value->ToNumber<int32_t>();
9472         if (index < 0 || index >= static_cast<int32_t>(TEXT_DETECT_TYPES.size())) {
9473             return false;
9474         }
9475         if (i != 0) {
9476             textDetectConfig.types.append(",");
9477         }
9478         textDetectConfig.types.append(TEXT_DETECT_TYPES[index]);
9479     }
9480     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
9481     JSRef<JSVal> resultCallback = obj->GetProperty("onDetectResultUpdate");
9482     if (resultCallback->IsFunction()) {
9483         auto jsFunc = AceType::MakeRefPtr<JsClipboardFunction>(JSRef<JSFunc>::Cast(resultCallback));
9484         textDetectConfig.onResult = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
9485                        const std::string& result) {
9486             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
9487             PipelineContext::SetCallBackNode(node);
9488             func->Execute(result);
9489         };
9490     }
9491 
9492     return ParseAIEntityColor(obj, textDetectConfig);
9493 }
9494 
ParseAIEntityColor(const JSRef<JSObject> & obj,TextDetectConfig & textDetectConfig)9495 bool JSViewAbstract::ParseAIEntityColor(const JSRef<JSObject>& obj, TextDetectConfig& textDetectConfig)
9496 {
9497     JSRef<JSVal> entityColorValue = obj->GetProperty("color");
9498     ParseJsColor(entityColorValue, textDetectConfig.entityColor);
9499 
9500     JSRef<JSVal> decorationValue = obj->GetProperty("decoration");
9501     if (decorationValue->IsUndefined() || !decorationValue->IsObject()) {
9502         textDetectConfig.entityDecorationColor = textDetectConfig.entityColor;
9503         return true;
9504     }
9505     JSRef<JSObject> decorationObj = JSRef<JSObject>::Cast(decorationValue);
9506     JSRef<JSVal> typeValue = decorationObj->GetProperty("type");
9507     JSRef<JSVal> colorValue = decorationObj->GetProperty("color");
9508     JSRef<JSVal> styleValue = decorationObj->GetProperty("style");
9509 
9510     if (typeValue->IsNumber()) {
9511         textDetectConfig.entityDecorationType = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
9512     } else {
9513         textDetectConfig.entityDecorationType = TextDecoration::UNDERLINE;
9514     }
9515     if (!ParseJsColor(colorValue, textDetectConfig.entityDecorationColor)) {
9516         textDetectConfig.entityDecorationColor = textDetectConfig.entityColor;
9517     }
9518     if (styleValue->IsNumber()) {
9519          textDetectConfig.entityDecorationStyle = static_cast<TextDecorationStyle>(styleValue->ToNumber<int32_t>());
9520     } else {
9521         textDetectConfig.entityDecorationStyle = TextDecorationStyle::SOLID;
9522     }
9523 
9524     return true;
9525 }
9526 
GetAngle(const std::string & key,const std::unique_ptr<JsonValue> & jsonValue,std::optional<float> & angle)9527 void JSViewAbstract::GetAngle(
9528     const std::string& key, const std::unique_ptr<JsonValue>& jsonValue, std::optional<float>& angle)
9529 {
9530     auto value = jsonValue->GetValue(key);
9531     if (value && value->IsString()) {
9532         angle = static_cast<float>(StringUtils::StringToDegree(value->GetString()));
9533     } else if (value && value->IsNumber()) {
9534         angle = static_cast<float>(value->GetDouble());
9535     }
9536 }
9537 
GetJsAngle(int32_t key,const JSRef<JSVal> & jsValue,std::optional<float> & angle)9538 void JSViewAbstract::GetJsAngle(
9539     int32_t key, const JSRef<JSVal>& jsValue, std::optional<float>& angle)
9540 {
9541     if (!jsValue->IsObject()) {
9542         return;
9543     }
9544     JSRef<JSVal> value = JSRef<JSObject>::Cast(jsValue)->GetProperty(key);
9545     if (value->IsString()) {
9546         angle = static_cast<float>(StringUtils::StringToDegree(value->ToString()));
9547     } else if (value->IsNumber()) {
9548         angle = value->ToNumber<float>();
9549     }
9550 }
9551 
9552 // if angle is not string or number, return directly. If angle is invalid string, use defaultValue.
GetJsAngleWithDefault(int32_t key,const JSRef<JSObject> & jsObj,std::optional<float> & angle,float defaultValue)9553 void JSViewAbstract::GetJsAngleWithDefault(
9554     int32_t key, const JSRef<JSObject>& jsObj, std::optional<float>& angle, float defaultValue)
9555 {
9556     JSRef<JSVal> value = jsObj->GetProperty(key);
9557     if (value->IsString()) {
9558         double temp = 0.0;
9559         if (StringUtils::StringToDegree(value->ToString(), temp)) {
9560             angle = static_cast<float>(temp);
9561         } else {
9562             angle = defaultValue;
9563         }
9564     } else if (value->IsNumber()) {
9565         angle = value->ToNumber<float>();
9566     }
9567 }
9568 
CheckAngle(std::optional<float> & angle)9569 inline void JSViewAbstract::CheckAngle(std::optional<float>& angle)
9570 {
9571     angle = std::clamp(angle.value(), 0.0f, MAX_ANGLE);
9572 }
9573 
GetPerspective(const std::string & key,const std::unique_ptr<JsonValue> & jsonValue,float & perspective)9574 void JSViewAbstract::GetPerspective(
9575     const std::string& key, const std::unique_ptr<JsonValue>& jsonValue, float& perspective)
9576 {
9577     auto value = jsonValue->GetValue(key);
9578     if (value && value->IsNumber()) {
9579         perspective = static_cast<float>(value->GetDouble());
9580     }
9581 }
9582 
GetJsPerspective(int32_t key,const JSRef<JSObject> & jsValue,float & perspective)9583 void JSViewAbstract::GetJsPerspective(int32_t key, const JSRef<JSObject>& jsValue, float& perspective)
9584 {
9585     auto value = jsValue->GetProperty(key);
9586     if (value->IsNumber()) {
9587         perspective = value->ToNumber<float>();
9588     }
9589 }
9590 
GetGradientColorStops(Gradient & gradient,const std::unique_ptr<JsonValue> & colorStops)9591 void JSViewAbstract::GetGradientColorStops(Gradient& gradient, const std::unique_ptr<JsonValue>& colorStops)
9592 {
9593     if (!colorStops || colorStops->IsNull() || !colorStops->IsArray()) {
9594         return;
9595     }
9596 
9597     for (int32_t i = 0; i < colorStops->GetArraySize(); i++) {
9598         GradientColor gradientColor;
9599         auto item = colorStops->GetArrayItem(i);
9600         if (item && !item->IsNull() && item->IsArray() && item->GetArraySize() >= 1) {
9601             auto colorParams = item->GetArrayItem(0);
9602             // color
9603             Color color;
9604             if (!ParseJsonColor(colorParams, color)) {
9605                 continue;
9606             }
9607             gradientColor.SetColor(color);
9608             gradientColor.SetHasValue(false);
9609             // stop value
9610             if (item->GetArraySize() <= 1) {
9611                 continue;
9612             }
9613             auto stopValue = item->GetArrayItem(1);
9614             double value = 0.0;
9615             if (ParseJsonDouble(stopValue, value)) {
9616                 value = std::clamp(value, 0.0, 1.0);
9617                 gradientColor.SetHasValue(true);
9618                 gradientColor.SetDimension(CalcDimension(value * 100.0, DimensionUnit::PERCENT));
9619             }
9620             gradient.AddColor(gradientColor);
9621         }
9622     }
9623 }
9624 
NewGetGradientColorStops(NG::Gradient & gradient,const std::unique_ptr<JsonValue> & colorStops)9625 void JSViewAbstract::NewGetGradientColorStops(NG::Gradient& gradient, const std::unique_ptr<JsonValue>& colorStops)
9626 {
9627     if (!colorStops || colorStops->IsNull() || !colorStops->IsArray()) {
9628         return;
9629     }
9630 
9631     for (int32_t i = 0; i < colorStops->GetArraySize(); i++) {
9632         NG::GradientColor gradientColor;
9633         auto item = colorStops->GetArrayItem(i);
9634         if (item && !item->IsNull() && item->IsArray() && item->GetArraySize() >= 1) {
9635             auto colorParams = item->GetArrayItem(0);
9636             // color
9637             Color color;
9638             if (!ParseJsonColor(colorParams, color)) {
9639                 continue;
9640             }
9641             gradientColor.SetColor(color);
9642             gradientColor.SetHasValue(false);
9643             // stop value
9644             if (item->GetArraySize() <= 1) {
9645                 continue;
9646             }
9647             auto stopValue = item->GetArrayItem(1);
9648             double value = 0.0;
9649             if (ParseJsonDouble(stopValue, value)) {
9650                 value = std::clamp(value, 0.0, 1.0);
9651                 gradientColor.SetHasValue(true);
9652                 //  [0, 1] -> [0, 100.0];
9653                 gradientColor.SetDimension(CalcDimension(value * 100.0, DimensionUnit::PERCENT));
9654             }
9655             gradient.AddColor(gradientColor);
9656         }
9657     }
9658 }
9659 
NewGetJsGradientColorStops(NG::Gradient & gradient,const JSRef<JSVal> & colorStops)9660 void JSViewAbstract::NewGetJsGradientColorStops(NG::Gradient& gradient, const JSRef<JSVal>& colorStops)
9661 {
9662     if (!colorStops->IsArray()) {
9663         return;
9664     }
9665 
9666     JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(colorStops);
9667     size_t length = jsArray->Length();
9668     for (size_t i = 0; i < length; i++) {
9669         NG::GradientColor gradientColor;
9670         JSRef<JSVal> item = jsArray->GetValueAt(i);
9671         if (!item->IsArray()) {
9672             continue;
9673         }
9674         JSRef<JSArray> subArray = JSRef<JSArray>::Cast(item);
9675         if (subArray->Length() < 2) {
9676             continue;
9677         }
9678         // color
9679         Color color;
9680         if (!ParseJsColor(subArray->GetValueAt(0), color)) {
9681             continue;
9682         }
9683         gradientColor.SetColor(color);
9684         gradientColor.SetHasValue(false);
9685         // stop value
9686         double value = 0.0;
9687         if (ParseJsDouble(subArray->GetValueAt(1), value)) {
9688             value = std::clamp(value, 0.0, 1.0);
9689             gradientColor.SetHasValue(true);
9690         }
9691         //  [0, 1] -> [0, 100.0];
9692         gradientColor.SetDimension(CalcDimension(value * 100.0, DimensionUnit::PERCENT));
9693         gradient.AddColor(gradientColor);
9694     }
9695 }
9696 
SetDirection(const std::string & dir)9697 void JSViewAbstract::SetDirection(const std::string& dir)
9698 {
9699     TextDirection direction = TextDirection::AUTO;
9700     if (dir == "Ltr") {
9701         direction = TextDirection::LTR;
9702     } else if (dir == "Rtl") {
9703         direction = TextDirection::RTL;
9704     } else if (dir == "Auto") {
9705         direction = TextDirection::AUTO;
9706     } else if (dir == "undefined" && Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
9707         direction = TextDirection::AUTO;
9708     }
9709     ViewAbstractModel::GetInstance()->SetLayoutDirection(direction);
9710 }
9711 
GetThemeConstants(const JSRef<JSObject> & jsObj)9712 RefPtr<ThemeConstants> JSViewAbstract::GetThemeConstants(const JSRef<JSObject>& jsObj)
9713 {
9714     std::string bundleName;
9715     std::string moduleName;
9716     if (!jsObj->IsUndefined()) {
9717         JSRef<JSVal> bundle = jsObj->GetProperty("bundleName");
9718         JSRef<JSVal> module = jsObj->GetProperty("moduleName");
9719         if (bundle->IsString() && module->IsString()) {
9720             bundleName = bundle->ToString();
9721             moduleName = module->ToString();
9722         }
9723     }
9724 
9725     auto cardId = CardScope::CurrentId();
9726     if (cardId != INVALID_CARD_ID) {
9727         auto container = Container::Current();
9728         auto weak = container->GetCardPipeline(cardId);
9729         auto cardPipelineContext = weak.Upgrade();
9730         CHECK_NULL_RETURN(cardPipelineContext, nullptr);
9731         auto cardThemeManager = cardPipelineContext->GetThemeManager();
9732         CHECK_NULL_RETURN(cardThemeManager, nullptr);
9733         return cardThemeManager->GetThemeConstants(bundleName, moduleName);
9734     }
9735 
9736 #ifdef PLUGIN_COMPONENT_SUPPORTED
9737     if (Container::CurrentId() >= MIN_PLUGIN_SUBCONTAINER_ID) {
9738         auto pluginContainer = PluginManager::GetInstance().GetPluginSubContainer(Container::CurrentId());
9739         if (!pluginContainer) {
9740             return nullptr;
9741         }
9742         auto pluginPipelineContext = pluginContainer->GetPipelineContext();
9743         if (!pluginPipelineContext) {
9744             return nullptr;
9745         }
9746         auto pluginThemeManager = pluginPipelineContext->GetThemeManager();
9747         if (!pluginThemeManager) {
9748             return nullptr;
9749         }
9750         return pluginThemeManager->GetThemeConstants(bundleName, moduleName);
9751     }
9752 #endif
9753     auto container = Container::Current();
9754     CHECK_NULL_RETURN(container, nullptr);
9755     auto pipelineContext = container->GetPipelineContext();
9756     CHECK_NULL_RETURN(pipelineContext, nullptr);
9757     auto themeManager = pipelineContext->GetThemeManager();
9758     CHECK_NULL_RETURN(themeManager, nullptr);
9759     return themeManager->GetThemeConstants(bundleName, moduleName);
9760 }
9761 
JsHoverEffect(const JSCallbackInfo & info)9762 void JSViewAbstract::JsHoverEffect(const JSCallbackInfo& info)
9763 {
9764     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
9765     auto jsVal = info[0];
9766     if (!CheckJSCallbackInfo("HoverEffect", jsVal, checkList)) {
9767         ViewAbstractModel::GetInstance()->SetHoverEffect(HoverEffectType::AUTO);
9768         return;
9769     }
9770     if (!jsVal->IsNumber()) {
9771         return;
9772     }
9773     ViewAbstractModel::GetInstance()->SetHoverEffect(static_cast<HoverEffectType>(jsVal->ToNumber<int32_t>()));
9774 }
9775 
JsOnMouse(const JSCallbackInfo & info)9776 void JSViewAbstract::JsOnMouse(const JSCallbackInfo& info)
9777 {
9778     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
9779         ViewAbstractModel::GetInstance()->DisableOnMouse();
9780         return;
9781     }
9782     if (!info[0]->IsFunction()) {
9783         return;
9784     }
9785 
9786     RefPtr<JsClickFunction> jsOnMouseFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
9787     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
9788     auto onMouse = [execCtx = info.GetExecutionContext(), func = std::move(jsOnMouseFunc), node = targetNode](
9789                        MouseInfo& mouseInfo) {
9790         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
9791         ACE_SCORING_EVENT("onMouse");
9792         PipelineContext::SetCallBackNode(node);
9793         func->Execute(mouseInfo);
9794     };
9795     ViewAbstractModel::GetInstance()->SetOnMouse(std::move(onMouse));
9796 }
9797 
JsOnHover(const JSCallbackInfo & info)9798 void JSViewAbstract::JsOnHover(const JSCallbackInfo& info)
9799 {
9800     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
9801         ViewAbstractModel::GetInstance()->DisableOnHover();
9802         return;
9803     }
9804     if (!info[0]->IsFunction()) {
9805         return;
9806     }
9807 
9808     RefPtr<JsHoverFunction> jsOnHoverFunc = AceType::MakeRefPtr<JsHoverFunction>(JSRef<JSFunc>::Cast(info[0]));
9809     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
9810     auto onHover = [execCtx = info.GetExecutionContext(), func = std::move(jsOnHoverFunc), node = frameNode](
9811                        bool isHover, HoverInfo& hoverInfo) {
9812         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
9813         ACE_SCORING_EVENT("onHover");
9814         PipelineContext::SetCallBackNode(node);
9815         func->HoverExecute(isHover, hoverInfo);
9816     };
9817     ViewAbstractModel::GetInstance()->SetOnHover(std::move(onHover));
9818 }
9819 
JsOnAccessibilityHover(const JSCallbackInfo & info)9820 void JSViewAbstract::JsOnAccessibilityHover(const JSCallbackInfo& info)
9821 {
9822     if (info[0]->IsUndefined()) {
9823         ViewAbstractModel::GetInstance()->DisableOnAccessibilityHover();
9824         return;
9825     }
9826     if (!info[0]->IsFunction()) {
9827         return;
9828     }
9829 
9830     RefPtr<JsHoverFunction> jsOnHoverFunc = AceType::MakeRefPtr<JsHoverFunction>(JSRef<JSFunc>::Cast(info[0]));
9831     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
9832     auto onAccessibilityHover = [execCtx = info.GetExecutionContext(), func = std::move(jsOnHoverFunc),
9833                                     node = frameNode](bool isHover, AccessibilityHoverInfo& hoverInfo) {
9834         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
9835         ACE_SCORING_EVENT("onAccessibilityHover");
9836         PipelineContext::SetCallBackNode(node);
9837         func->AccessibilityHoverExecute(isHover, hoverInfo);
9838     };
9839     ViewAbstractModel::GetInstance()->SetOnAccessibilityHover(std::move(onAccessibilityHover));
9840 }
9841 
JsOnClick(const JSCallbackInfo & info)9842 void JSViewAbstract::JsOnClick(const JSCallbackInfo& info)
9843 {
9844     auto arg = info[0];
9845     if (arg->IsUndefined() && IsDisableEventVersion()) {
9846         ViewAbstractModel::GetInstance()->DisableOnClick();
9847         return;
9848     }
9849     if (!arg->IsFunction()) {
9850         return;
9851     }
9852 
9853     auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(arg));
9854     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
9855     auto onTap = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), node = targetNode](
9856                      BaseEventInfo* info) {
9857         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
9858         auto* tapInfo = TypeInfoHelper::DynamicCast<GestureEvent>(info);
9859         ACE_SCORING_EVENT("onClick");
9860         PipelineContext::SetCallBackNode(node);
9861         func->Execute(*tapInfo);
9862 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
9863         JSInteractableView::ReportClickEvent(node);
9864 #endif
9865     };
9866     auto tmpOnTap = [func = std::move(onTap)](GestureEvent& info) { func(&info); };
9867     auto onClick = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, node = targetNode](
9868                        const ClickInfo* info) {
9869         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
9870         ACE_SCORING_EVENT("onClick");
9871         PipelineContext::SetCallBackNode(node);
9872         func->Execute(*info);
9873 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
9874         JSInteractableView::ReportClickEvent(node);
9875 #endif
9876     };
9877 
9878     double distanceThreshold = std::numeric_limits<double>::infinity();
9879     if (info.Length() > 1 && info[1]->IsNumber()) {
9880         distanceThreshold = info[1]->ToNumber<double>();
9881         if (distanceThreshold < 0) {
9882             distanceThreshold = std::numeric_limits<double>::infinity();
9883         }
9884     }
9885     distanceThreshold = Dimension(distanceThreshold, DimensionUnit::VP).ConvertToPx();
9886     ViewAbstractModel::GetInstance()->SetOnClick(std::move(tmpOnTap), std::move(onClick), distanceThreshold);
9887 }
9888 
JsOnGestureJudgeBegin(const JSCallbackInfo & info)9889 void JSViewAbstract::JsOnGestureJudgeBegin(const JSCallbackInfo& info)
9890 {
9891     if (info[0]->IsUndefined() || !info[0]->IsFunction()) {
9892         ViewAbstractModel::GetInstance()->SetOnGestureJudgeBegin(nullptr);
9893         return;
9894     }
9895 
9896     auto jsOnGestureJudgeFunc = AceType::MakeRefPtr<JsGestureJudgeFunction>(JSRef<JSFunc>::Cast(info[0]));
9897     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
9898     auto onGestureJudgefunc = [execCtx = info.GetExecutionContext(), func = jsOnGestureJudgeFunc, node = frameNode](
9899                                   const RefPtr<NG::GestureInfo>& gestureInfo,
9900                                   const std::shared_ptr<BaseGestureEvent>& info) -> GestureJudgeResult {
9901         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, GestureJudgeResult::CONTINUE);
9902         ACE_SCORING_EVENT("onGestureJudgeBegin");
9903         return func->Execute(gestureInfo, info);
9904     };
9905     ViewAbstractModel::GetInstance()->SetOnGestureJudgeBegin(std::move(onGestureJudgefunc));
9906 }
9907 
JsOnTouchIntercept(const JSCallbackInfo & info)9908 void JSViewAbstract::JsOnTouchIntercept(const JSCallbackInfo& info)
9909 {
9910     if (info[0]->IsUndefined() || !info[0]->IsFunction()) {
9911         ViewAbstractModel::GetInstance()->SetOnTouchIntercept(nullptr);
9912         return;
9913     }
9914 
9915     auto jsOnTouchInterceptFunc = AceType::MakeRefPtr<JsTouchInterceptFunction>(JSRef<JSFunc>::Cast(info[0]));
9916     auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
9917     auto onTouchInterceptfunc = [execCtx = info.GetExecutionContext(), func = jsOnTouchInterceptFunc, node = frameNode](
9918                                     TouchEventInfo& info) -> NG::HitTestMode {
9919         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, NG::HitTestMode::HTMDEFAULT);
9920         ACE_SCORING_EVENT("onTouchIntercept");
9921         PipelineContext::SetCallBackNode(node);
9922         return func->Execute(info);
9923     };
9924     ViewAbstractModel::GetInstance()->SetOnTouchIntercept(std::move(onTouchInterceptfunc));
9925 }
9926 
JsShouldBuiltInRecognizerParallelWith(const JSCallbackInfo & info)9927 void JSViewAbstract::JsShouldBuiltInRecognizerParallelWith(const JSCallbackInfo& info)
9928 {
9929     if (info[0]->IsUndefined() || !info[0]->IsFunction()) {
9930         ViewAbstractModel::GetInstance()->SetShouldBuiltInRecognizerParallelWith(nullptr);
9931         return;
9932     }
9933 
9934     auto jsParallelInnerGestureToFunc =
9935         AceType::MakeRefPtr<JsShouldBuiltInRecognizerParallelWithFunction>(JSRef<JSFunc>::Cast(info[0]));
9936     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
9937     auto shouldBuiltInRecognizerParallelWithFunc =
9938         [execCtx = info.GetExecutionContext(), func = jsParallelInnerGestureToFunc, node = frameNode](
9939             const RefPtr<NG::NGGestureRecognizer>& current,
9940             const std::vector<RefPtr<NG::NGGestureRecognizer>>& others) -> RefPtr<NG::NGGestureRecognizer> {
9941         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, nullptr);
9942         ACE_SCORING_EVENT("shouldBuiltInRecognizerParallelWith");
9943         PipelineContext::SetCallBackNode(node);
9944         return func->Execute(current, others);
9945     };
9946     ViewAbstractModel::GetInstance()->SetShouldBuiltInRecognizerParallelWith(
9947         std::move(shouldBuiltInRecognizerParallelWithFunc));
9948 }
9949 
JsOnGestureRecognizerJudgeBegin(const JSCallbackInfo & info)9950 void JSViewAbstract::JsOnGestureRecognizerJudgeBegin(const JSCallbackInfo& info)
9951 {
9952     if (info[0]->IsUndefined() || !info[0]->IsFunction()) {
9953         ViewAbstractModel::GetInstance()->SetOnGestureRecognizerJudgeBegin(nullptr, false);
9954         return;
9955     }
9956 
9957     auto jsOnGestureRecognizerJudgeFunc = AceType::MakeRefPtr<JsGestureJudgeFunction>(JSRef<JSFunc>::Cast(info[0]));
9958     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
9959     auto onGestureRecognizerJudgefunc =
9960         [execCtx = info.GetExecutionContext(), func = jsOnGestureRecognizerJudgeFunc, node = frameNode](
9961             const std::shared_ptr<BaseGestureEvent>& info, const RefPtr<NG::NGGestureRecognizer>& current,
9962             const std::list<RefPtr<NG::NGGestureRecognizer>>& others) -> GestureJudgeResult {
9963         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, GestureJudgeResult::CONTINUE);
9964         ACE_SCORING_EVENT("onGestureRecognizerJudgeBegin");
9965         PipelineContext::SetCallBackNode(node);
9966         return func->Execute(info, current, others);
9967     };
9968 
9969     bool exposeInnerGestureFlag = false;
9970     if (info.Length() > 1 && info[1]->IsBoolean()) {
9971         exposeInnerGestureFlag = info[1]->ToBoolean();
9972     }
9973     ViewAbstractModel::GetInstance()->SetOnGestureRecognizerJudgeBegin(
9974         std::move(onGestureRecognizerJudgefunc), exposeInnerGestureFlag);
9975 }
9976 
JsClickEffect(const JSCallbackInfo & info)9977 void JSViewAbstract::JsClickEffect(const JSCallbackInfo& info)
9978 {
9979     JSRef<JSVal> arg = info[0];
9980     if (arg->IsUndefined() || arg->IsNull()) {
9981         ViewAbstractModel::GetInstance()->SetClickEffectLevel(ClickEffectLevel::UNDEFINED, DEFAULT_SCALE_LIGHT);
9982         return;
9983     }
9984     if (!arg->IsObject()) {
9985         return;
9986     }
9987     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
9988     JSRef<JSVal> clickEffectLevel = obj->GetProperty("level");
9989     int32_t clickEffectLevelValue = 0;
9990     if (clickEffectLevel->IsNumber()) {
9991         clickEffectLevelValue = clickEffectLevel->ToNumber<int32_t>();
9992         if (clickEffectLevelValue < static_cast<int32_t>(ClickEffectLevel::LIGHT) ||
9993             clickEffectLevelValue > static_cast<int32_t>(ClickEffectLevel::HEAVY)) {
9994             clickEffectLevelValue = 0;
9995         }
9996     }
9997 
9998     JSRef<JSVal> scaleNumber = obj->GetProperty("scale");
9999     float scaleNumberValue = DEFAULT_SCALE_LIGHT;
10000     if (!scaleNumber->IsNumber()) {
10001         if ((ClickEffectLevel)clickEffectLevelValue == ClickEffectLevel::MIDDLE ||
10002             (ClickEffectLevel)clickEffectLevelValue == ClickEffectLevel::HEAVY) {
10003             scaleNumberValue = DEFAULT_SCALE_MIDDLE_OR_HEAVY;
10004         }
10005         ViewAbstractModel::GetInstance()->SetClickEffectLevel(
10006             (ClickEffectLevel)clickEffectLevelValue, scaleNumberValue);
10007         return;
10008     }
10009 
10010     scaleNumberValue = scaleNumber->ToNumber<float>();
10011     if (LessNotEqual(scaleNumberValue, 0.0) || GreatNotEqual(scaleNumberValue, 1.0)) {
10012         if ((ClickEffectLevel)clickEffectLevelValue == ClickEffectLevel::MIDDLE ||
10013             (ClickEffectLevel)clickEffectLevelValue == ClickEffectLevel::HEAVY) {
10014             scaleNumberValue = DEFAULT_SCALE_MIDDLE_OR_HEAVY;
10015         } else {
10016             scaleNumberValue = DEFAULT_SCALE_LIGHT;
10017         }
10018     }
10019 
10020     ViewAbstractModel::GetInstance()->SetClickEffectLevel((ClickEffectLevel)clickEffectLevelValue, scaleNumberValue);
10021 }
10022 
JsOnVisibleAreaChange(const JSCallbackInfo & info)10023 void JSViewAbstract::JsOnVisibleAreaChange(const JSCallbackInfo& info)
10024 {
10025     if (info.Length() != 2) {
10026         return;
10027     }
10028 
10029     if (!info[0]->IsArray() || !info[1]->IsFunction()) {
10030         return;
10031     }
10032 
10033     auto ratioArray = JSRef<JSArray>::Cast(info[0]);
10034     size_t size = ratioArray->Length();
10035     std::vector<double> ratioVec(size);
10036     ratioVec.clear();
10037     for (size_t i = 0; i < size; i++) {
10038         double ratio = 0.0;
10039         ParseJsDouble(ratioArray->GetValueAt(i), ratio);
10040         if (LessOrEqual(ratio, VISIBLE_RATIO_MIN)) {
10041             ratio = VISIBLE_RATIO_MIN;
10042         }
10043 
10044         if (GreatOrEqual(ratio, VISIBLE_RATIO_MAX)) {
10045             ratio = VISIBLE_RATIO_MAX;
10046         }
10047         ratioVec.push_back(ratio);
10048     }
10049 
10050     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[1]));
10051     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
10052     auto onVisibleChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
10053                                bool visible, double ratio) {
10054         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
10055         ACE_SCORING_EVENT("onVisibleAreaChange");
10056 
10057         JSRef<JSVal> params[2];
10058         params[0] = JSRef<JSVal>::Make(ToJSValue(visible));
10059         params[1] = JSRef<JSVal>::Make(ToJSValue(ratio));
10060         PipelineContext::SetCallBackNode(node);
10061         func->ExecuteJS(2, params);
10062     };
10063     ViewAbstractModel::GetInstance()->SetOnVisibleChange(std::move(onVisibleChange), ratioVec);
10064 }
10065 
JsHitTestBehavior(const JSCallbackInfo & info)10066 void JSViewAbstract::JsHitTestBehavior(const JSCallbackInfo& info)
10067 {
10068     if (info.Length() != 1 || !info[0]->IsNumber()) {
10069         return;
10070     }
10071 
10072     NG::HitTestMode hitTestModeNG = NG::HitTestMode::HTMDEFAULT;
10073     hitTestModeNG = static_cast<NG::HitTestMode>(info[0]->ToNumber<int32_t>());
10074     ViewAbstractModel::GetInstance()->SetHitTestMode(hitTestModeNG);
10075 }
10076 
JsOnChildTouchTest(const JSCallbackInfo & info)10077 void JSViewAbstract::JsOnChildTouchTest(const JSCallbackInfo& info)
10078 {
10079     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
10080     auto jsVal = info[0];
10081     if (!CheckJSCallbackInfo("onChildTouchTest", jsVal, checkList)) {
10082         return;
10083     }
10084 
10085     RefPtr<JsOnChildTouchTestFunction> jsOnChildTouchTestFunc =
10086         AceType::MakeRefPtr<JsOnChildTouchTestFunction>(JSRef<JSFunc>::Cast(jsVal));
10087 
10088     auto onTouchTestFunc = [execCtx = info.GetExecutionContext(), func = std::move(jsOnChildTouchTestFunc)](
10089                                const std::vector<NG::TouchTestInfo>& touchInfo) -> NG::TouchResult {
10090         NG::TouchResult touchRes;
10091         NG::TouchResult defaultRes;
10092         defaultRes.strategy = NG::TouchTestStrategy::DEFAULT;
10093         defaultRes.id = "";
10094         auto ret = func->Execute(touchInfo);
10095         if (!ret->IsObject()) {
10096             TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest return value is not object, parse failed.");
10097             return defaultRes;
10098         }
10099 
10100         auto retObj = JSRef<JSObject>::Cast(ret);
10101         auto strategy = retObj->GetProperty("strategy");
10102         if (!strategy->IsNumber()) {
10103             TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest return value strategy is not number, parse failed.");
10104             return defaultRes;
10105         }
10106         touchRes.strategy = static_cast<NG::TouchTestStrategy>(strategy->ToNumber<int32_t>());
10107         auto id = retObj->GetProperty("id");
10108         if (!id->IsString()) {
10109             TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest return value id is not string, parse failed.");
10110             return defaultRes;
10111         }
10112         touchRes.id = id->ToString();
10113         return touchRes;
10114     };
10115     ViewAbstractModel::GetInstance()->SetOnTouchTestFunc(std::move(onTouchTestFunc));
10116 }
10117 
JsForegroundColor(const JSCallbackInfo & info)10118 void JSViewAbstract::JsForegroundColor(const JSCallbackInfo& info)
10119 {
10120     Color foregroundColor = Color::TRANSPARENT;
10121     ForegroundColorStrategy strategy;
10122     if (ParseJsColorStrategy(info[0], strategy)) {
10123         ViewAbstractModel::GetInstance()->SetForegroundColorStrategy(strategy);
10124         return;
10125     }
10126     ParseJsColor(info[0], foregroundColor);
10127     ViewAbstractModel::GetInstance()->SetForegroundColor(foregroundColor);
10128 }
10129 
JsKeyboardShortcut(const JSCallbackInfo & info)10130 void JSViewAbstract::JsKeyboardShortcut(const JSCallbackInfo& info)
10131 {
10132     // KeyboardShortcut only allows 2 or 3 params.
10133     if (info.Length() < 2 || info.Length() > 3) {
10134         return;
10135     }
10136     if ((!info[0]->IsString() && !info[0]->IsNumber()) || !info[1]->IsArray()) {
10137         // clear shortcut key
10138         ViewAbstractModel::GetInstance()->SetKeyboardShortcut({}, {}, nullptr);
10139         return;
10140     }
10141 
10142     std::string value;
10143     if (info[0]->IsString()) {
10144         // common letter/number/symbol
10145         value = info[0]->ToString();
10146         if (value.size() != 1) {
10147             // clear shortcut key
10148             ViewAbstractModel::GetInstance()->SetKeyboardShortcut({}, {}, nullptr);
10149             return;
10150         }
10151     } else {
10152         // function keys such as F1-F10/ESC
10153         FunctionKey functionkey = static_cast<FunctionKey>(info[0]->ToNumber<int32_t>());
10154         value = GetFunctionKeyName(functionkey);
10155     }
10156 
10157     auto keysArray = JSRef<JSArray>::Cast(info[1]);
10158     size_t size = keysArray->Length();
10159     std::vector<ModifierKey> keys(size);
10160     keys.clear();
10161     for (size_t i = 0; i < size; i++) {
10162         JSRef<JSVal> key = keysArray->GetValueAt(i);
10163         if (key->IsNumber()) {
10164             keys.emplace_back(static_cast<ModifierKey>(key->ToNumber<int32_t>()));
10165         }
10166     }
10167 
10168     // KeyboardShortcut allows 3 params, the third param is function callback.
10169     if (info.Length() == 3 && info[2]->IsFunction()) {
10170         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[2]));
10171         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
10172         auto onKeyboardShortcutAction = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
10173                                             node = frameNode]() {
10174             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
10175             ACE_SCORING_EVENT("onKeyboardShortcutAction");
10176             PipelineContext::SetCallBackNode(node);
10177             func->ExecuteJS();
10178         };
10179         ViewAbstractModel::GetInstance()->SetKeyboardShortcut(value, keys, std::move(onKeyboardShortcutAction));
10180         return;
10181     }
10182     ViewAbstractModel::GetInstance()->SetKeyboardShortcut(value, keys, nullptr);
10183 }
10184 
CheckColor(const JSRef<JSVal> & jsValue,Color & result,const char * componentName,const char * propName)10185 bool JSViewAbstract::CheckColor(
10186     const JSRef<JSVal>& jsValue, Color& result, const char* componentName, const char* propName)
10187 {
10188     // Color is undefined or null
10189     if (jsValue->IsUndefined() || jsValue->IsNull()) {
10190         return false;
10191     }
10192     // input type is not in [number, string, Resource]
10193     if (!jsValue->IsNumber() && !jsValue->IsString() && !jsValue->IsObject()) {
10194         return false;
10195     }
10196     // Correct type, incorrect value parsing
10197     if (!ParseJsColor(jsValue, result)) {
10198         return false;
10199     }
10200     return true;
10201 }
10202 
CheckLength(const JSRef<JSVal> & jsValue,CalcDimension & result,const char * componentName,const char * propName)10203 bool JSViewAbstract::CheckLength(
10204     const JSRef<JSVal>& jsValue, CalcDimension& result, const char* componentName, const char* propName)
10205 {
10206     // Length is undefined or null
10207     if (jsValue->IsUndefined() || jsValue->IsNull()) {
10208         return false;
10209     }
10210     // input type is not in [number, string, Resource]
10211     if (!jsValue->IsNumber() && !jsValue->IsString() && !jsValue->IsObject()) {
10212         return false;
10213     }
10214     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
10215         return ParseJsDimensionVpNG(jsValue, result);
10216     }
10217     // Correct type, incorrect value parsing
10218     if (!ParseJsDimensionVp(jsValue, result)) {
10219         return false;
10220     }
10221     return true;
10222 }
10223 
10224 // obscured means that the developer calls the component to be private style.
JsObscured(const JSCallbackInfo & info)10225 void JSViewAbstract::JsObscured(const JSCallbackInfo& info)
10226 {
10227     JSRef<JSVal> arg = info[0];
10228     if (arg->IsUndefined() || arg->IsNull()) {
10229         std::vector<ObscuredReasons> reasons(0);
10230         ViewAbstractModel::GetInstance()->SetObscured(reasons);
10231         return;
10232     }
10233     if (!arg->IsArray()) {
10234         return;
10235     }
10236 
10237     auto obscuredArray = JSRef<JSArray>::Cast(arg);
10238     size_t size = obscuredArray->Length();
10239     std::vector<ObscuredReasons> reasons(size);
10240     reasons.clear();
10241     for (size_t i = 0; i < size; i++) {
10242         JSRef<JSVal> reason = obscuredArray->GetValueAt(i);
10243         if (reason->IsNumber()) {
10244             reasons.emplace_back(static_cast<ObscuredReasons>(reason->ToNumber<int32_t>()));
10245         }
10246     }
10247 
10248     ViewAbstractModel::GetInstance()->SetObscured(reasons);
10249 }
10250 
10251 // PrivacySensitive means that the component will change style when system calls the app to be privated.
JsPrivacySensitive(const JSCallbackInfo & info)10252 void JSViewAbstract::JsPrivacySensitive(const JSCallbackInfo& info)
10253 {
10254     auto sensitiveInfo = info[0];
10255     if (sensitiveInfo->IsUndefined()) {
10256         ViewAbstractModel::GetInstance()->SetPrivacySensitive(false);
10257         return;
10258     }
10259     bool sensitive = false;
10260     if (sensitiveInfo->IsBoolean()) {
10261         sensitive = sensitiveInfo->ToBoolean();
10262     }
10263     ViewAbstractModel::GetInstance()->SetPrivacySensitive(sensitive);
10264 }
10265 
JSRenderGroup(const JSCallbackInfo & info)10266 void JSViewAbstract::JSRenderGroup(const JSCallbackInfo& info)
10267 {
10268     if (info.Length() != 1) {
10269         return;
10270     }
10271     bool isRenderGroup = false;
10272     if (info[0]->IsBoolean()) {
10273         isRenderGroup = info[0]->ToBoolean();
10274     }
10275     ViewAbstractModel::GetInstance()->SetRenderGroup(isRenderGroup);
10276 }
10277 
JSRenderFit(const JSCallbackInfo & info)10278 void JSViewAbstract::JSRenderFit(const JSCallbackInfo& info)
10279 {
10280     if (info.Length() != 1) {
10281         return;
10282     }
10283     RenderFit renderFit = RenderFit::TOP_LEFT;
10284     if (info[0]->IsNumber()) {
10285         int32_t fitNumber = info[0]->ToNumber<int32_t>();
10286         if (fitNumber >= static_cast<int32_t>(RenderFit::CENTER) &&
10287             fitNumber <= static_cast<int32_t>(RenderFit::RESIZE_COVER_BOTTOM_RIGHT)) {
10288             renderFit = static_cast<RenderFit>(fitNumber);
10289         }
10290     }
10291     // how content fills the node duration implicit animation
10292     ViewAbstractModel::GetInstance()->SetRenderFit(renderFit);
10293 }
10294 
GetJsMediaBundleInfo(const JSRef<JSVal> & jsValue,std::string & bundleName,std::string & moduleName)10295 bool JSViewAbstract::GetJsMediaBundleInfo(const JSRef<JSVal>& jsValue, std::string& bundleName, std::string& moduleName)
10296 {
10297     if (!jsValue->IsObject() || jsValue->IsString()) {
10298         return false;
10299     }
10300     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
10301     if (!jsObj->IsUndefined()) {
10302         JSRef<JSVal> bundle = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::BUNDLE_NAME));
10303         JSRef<JSVal> module = jsObj->GetProperty(static_cast<int32_t>(ArkUIIndex::MODULE_NAME));
10304         if (bundle->IsString() && module->IsString()) {
10305             bundleName = bundle->ToString();
10306             moduleName = module->ToString();
10307             return true;
10308         }
10309     }
10310     return false;
10311 }
10312 
GetDrawCallback(const RefPtr<JsFunction> & jsDraw,const JSExecutionContext & execCtx)10313 std::function<void(NG::DrawingContext& context)> JSViewAbstract::GetDrawCallback(
10314     const RefPtr<JsFunction>& jsDraw, const JSExecutionContext& execCtx)
10315 {
10316     std::function<void(NG::DrawingContext & context)> drawCallback = [func = std::move(jsDraw), execCtx](
10317                                                                          NG::DrawingContext& context) -> void {
10318         JAVASCRIPT_EXECUTION_SCOPE(execCtx);
10319 
10320         JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
10321         objectTemplate->SetInternalFieldCount(1);
10322         JSRef<JSObject> contextObj = objectTemplate->NewInstance();
10323         JSRef<JSObject> sizeObj = objectTemplate->NewInstance();
10324         sizeObj->SetProperty<float>("height", PipelineBase::Px2VpWithCurrentDensity(context.height));
10325         sizeObj->SetProperty<float>("width", PipelineBase::Px2VpWithCurrentDensity(context.width));
10326         contextObj->SetPropertyObject("size", sizeObj);
10327 
10328         JSRef<JSObject> sizeInPxObj = objectTemplate->NewInstance();
10329         sizeInPxObj->SetProperty<float>("height", context.height);
10330         sizeInPxObj->SetProperty<float>("width", context.width);
10331         contextObj->SetPropertyObject("sizeInPixel", sizeInPxObj);
10332 
10333         auto engine = EngineHelper::GetCurrentEngine();
10334         CHECK_NULL_VOID(engine);
10335         NativeEngine* nativeEngine = engine->GetNativeEngine();
10336         napi_env env = reinterpret_cast<napi_env>(nativeEngine);
10337         ScopeRAII scope(env);
10338 
10339         auto jsCanvas = OHOS::Rosen::Drawing::JsCanvas::CreateJsCanvas(env, &context.canvas);
10340         OHOS::Rosen::Drawing::JsCanvas* unwrapCanvas = nullptr;
10341         napi_unwrap(env, jsCanvas, reinterpret_cast<void**>(&unwrapCanvas));
10342         if (unwrapCanvas) {
10343             unwrapCanvas->SaveCanvas();
10344             unwrapCanvas->ClipCanvas(context.width, context.height);
10345         }
10346         JsiRef<JsiValue> jsCanvasVal = JsConverter::ConvertNapiValueToJsVal(jsCanvas);
10347         contextObj->SetPropertyObject("canvas", jsCanvasVal);
10348 
10349         auto jsVal = JSRef<JSVal>::Cast(contextObj);
10350         panda::Local<JsiValue> value = jsVal.Get().GetLocalHandle();
10351         JSValueWrapper valueWrapper = value;
10352         napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
10353 
10354         napi_wrap(
10355             env, nativeValue, &context.canvas, [](napi_env, void*, void*) {}, nullptr, nullptr);
10356 
10357         JSRef<JSVal> result = func->ExecuteJS(1, &jsVal);
10358         if (unwrapCanvas) {
10359             unwrapCanvas->RestoreCanvas();
10360             unwrapCanvas->ResetCanvas();
10361         }
10362     };
10363     return drawCallback;
10364 }
10365 
ParseBorderColorProps(const JSRef<JSVal> & args,NG::BorderColorProperty & colorProperty)10366 bool JSViewAbstract::ParseBorderColorProps(const JSRef<JSVal>& args, NG::BorderColorProperty& colorProperty)
10367 {
10368     if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
10369         return false;
10370     }
10371     Color borderColor;
10372     if (ParseJsColor(args, borderColor)) {
10373         colorProperty.SetColor(borderColor);
10374         return true;
10375     } else if (args->IsObject()) {
10376         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args);
10377         CommonColor commonColor;
10378         ParseCommonEdgeColors(obj, commonColor);
10379         colorProperty.topColor = commonColor.top;
10380         colorProperty.bottomColor = commonColor.bottom;
10381         colorProperty.leftColor = commonColor.left;
10382         colorProperty.rightColor = commonColor.right;
10383         colorProperty.multiValued = true;
10384         return true;
10385     }
10386     return false;
10387 }
10388 
ParseBorderWidthProps(const JSRef<JSVal> & args,NG::BorderWidthProperty & borderWidthProperty)10389 bool JSViewAbstract::ParseBorderWidthProps(const JSRef<JSVal>& args, NG::BorderWidthProperty& borderWidthProperty)
10390 {
10391     if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
10392         return false;
10393     }
10394     CalcDimension borderWidth;
10395     if (ParseJsDimensionVpNG(args, borderWidth, true)) {
10396         if (borderWidth.IsNegative()) {
10397             borderWidth.Reset();
10398         }
10399         borderWidthProperty = NG::BorderWidthProperty({ borderWidth, borderWidth, borderWidth, borderWidth });
10400         return true;
10401     } else if (args->IsObject()) {
10402         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args);
10403         CommonCalcDimension commonCalcDimension;
10404         ParseCommonEdgeWidthsProps(obj, commonCalcDimension);
10405         borderWidthProperty.topDimen = commonCalcDimension.top;
10406         borderWidthProperty.bottomDimen = commonCalcDimension.bottom;
10407         borderWidthProperty.leftDimen = commonCalcDimension.left;
10408         borderWidthProperty.rightDimen = commonCalcDimension.right;
10409         borderWidthProperty.multiValued = true;
10410         return true;
10411     }
10412     return false;
10413 }
10414 
ParseBorderStyleProps(const JSRef<JSVal> & args,NG::BorderStyleProperty & borderStyleProperty)10415 bool JSViewAbstract::ParseBorderStyleProps(const JSRef<JSVal>& args, NG::BorderStyleProperty& borderStyleProperty)
10416 {
10417     if (!args->IsObject() && !args->IsNumber()) {
10418         return false;
10419     }
10420     if (args->IsObject()) {
10421         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args);
10422         auto leftValue = obj->GetProperty("left");
10423         if (!leftValue->IsUndefined() && leftValue->IsNumber()) {
10424             ConvertOptionBorderStyle(leftValue->ToNumber<int32_t>(), borderStyleProperty.styleLeft);
10425         }
10426         auto rightValue = obj->GetProperty("right");
10427         if (!rightValue->IsUndefined() && rightValue->IsNumber()) {
10428             ConvertOptionBorderStyle(rightValue->ToNumber<int32_t>(), borderStyleProperty.styleRight);
10429         }
10430         auto topValue = obj->GetProperty("top");
10431         if (!topValue->IsUndefined() && topValue->IsNumber()) {
10432             ConvertOptionBorderStyle(topValue->ToNumber<int32_t>(), borderStyleProperty.styleTop);
10433         }
10434         auto bottomValue = obj->GetProperty("bottom");
10435         if (!bottomValue->IsUndefined() && bottomValue->IsNumber()) {
10436             ConvertOptionBorderStyle(bottomValue->ToNumber<int32_t>(), borderStyleProperty.styleBottom);
10437         }
10438         borderStyleProperty.multiValued = true;
10439         return true;
10440     }
10441     std::optional<BorderStyle> borderStyle;
10442     if (ConvertOptionBorderStyle(args->ToNumber<int32_t>(), borderStyle)) {
10443         borderStyleProperty = NG::BorderStyleProperty({ borderStyle, borderStyle, borderStyle, borderStyle });
10444         return true;
10445     }
10446     return false;
10447 }
10448 
ParseBorderRadiusProps(const JSRef<JSObject> & object,NG::BorderRadiusProperty & radius)10449 void JSViewAbstract::ParseBorderRadiusProps(const JSRef<JSObject>& object, NG::BorderRadiusProperty& radius)
10450 {
10451     std::optional<CalcDimension> radiusTopLeft;
10452     std::optional<CalcDimension> radiusTopRight;
10453     std::optional<CalcDimension> radiusBottomLeft;
10454     std::optional<CalcDimension> radiusBottomRight;
10455     CalcDimension topLeft;
10456     if (ParseJsDimensionVpNG(object->GetProperty("topLeft"), topLeft, true)) {
10457         radiusTopLeft = topLeft;
10458     }
10459     CalcDimension topRight;
10460     if (ParseJsDimensionVpNG(object->GetProperty("topRight"), topRight, true)) {
10461         radiusTopRight = topRight;
10462     }
10463     CalcDimension bottomLeft;
10464     if (ParseJsDimensionVpNG(object->GetProperty("bottomLeft"), bottomLeft, true)) {
10465         radiusBottomLeft = bottomLeft;
10466     }
10467     CalcDimension bottomRight;
10468     if (ParseJsDimensionVpNG(object->GetProperty("bottomRight"), bottomRight, true)) {
10469         radiusBottomRight = bottomRight;
10470     }
10471     CheckLengthMetrics(object);
10472     radius.radiusTopLeft = radiusTopLeft;
10473     radius.radiusTopRight = radiusTopRight;
10474     radius.radiusBottomLeft = radiusBottomLeft;
10475     radius.radiusBottomRight = radiusBottomRight;
10476     radius.multiValued = true;
10477     return;
10478 }
10479 
ParseCommonBorderRadiusProps(const JSRef<JSObject> & object,NG::BorderRadiusProperty & radius)10480 void JSViewAbstract::ParseCommonBorderRadiusProps(const JSRef<JSObject>& object, NG::BorderRadiusProperty& radius)
10481 {
10482     if (CheckLengthMetrics(object)) {
10483         std::optional<CalcDimension> radiusTopStart;
10484         std::optional<CalcDimension> radiusTopEnd;
10485         std::optional<CalcDimension> radiusBottomStart;
10486         std::optional<CalcDimension> radiusBottomEnd;
10487         if (object->HasProperty(TOP_START_PROPERTY) && object->GetProperty(TOP_START_PROPERTY)->IsObject()) {
10488             JSRef<JSObject> topStartObj = JSRef<JSObject>::Cast(object->GetProperty(TOP_START_PROPERTY));
10489             CalcDimension calcDimension;
10490             if (ParseJsLengthMetrics(topStartObj, calcDimension)) {
10491                 CheckDimensionUnit(calcDimension, false, true);
10492                 radiusTopStart = calcDimension;
10493             }
10494         }
10495         if (object->HasProperty(TOP_END_PROPERTY) && object->GetProperty(TOP_END_PROPERTY)->IsObject()) {
10496             JSRef<JSObject> topEndObj = JSRef<JSObject>::Cast(object->GetProperty(TOP_END_PROPERTY));
10497             CalcDimension calcDimension;
10498             if (ParseJsLengthMetrics(topEndObj, calcDimension)) {
10499                 CheckDimensionUnit(calcDimension, false, true);
10500                 radiusTopEnd = calcDimension;
10501             }
10502         }
10503         if (object->HasProperty(BOTTOM_START_PROPERTY) && object->GetProperty(BOTTOM_START_PROPERTY)->IsObject()) {
10504             JSRef<JSObject> bottomStartObj = JSRef<JSObject>::Cast(object->GetProperty(BOTTOM_START_PROPERTY));
10505             CalcDimension calcDimension;
10506             if (ParseJsLengthMetrics(bottomStartObj, calcDimension)) {
10507                 CheckDimensionUnit(calcDimension, false, true);
10508                 radiusBottomStart = calcDimension;
10509             }
10510         }
10511         if (object->HasProperty(BOTTOM_END_PROPERTY) && object->GetProperty(BOTTOM_END_PROPERTY)->IsObject()) {
10512             JSRef<JSObject> bottomEndObj = JSRef<JSObject>::Cast(object->GetProperty(BOTTOM_END_PROPERTY));
10513             CalcDimension calcDimension;
10514             if (ParseJsLengthMetrics(bottomEndObj, calcDimension)) {
10515                 CheckDimensionUnit(calcDimension, false, true);
10516                 radiusBottomEnd = calcDimension;
10517             }
10518         }
10519         auto isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
10520         radius.radiusTopLeft = isRightToLeft ? radiusTopEnd : radiusTopStart;
10521         radius.radiusTopRight = isRightToLeft ? radiusTopStart : radiusTopEnd;
10522         radius.radiusBottomLeft = isRightToLeft ? radiusBottomEnd : radiusBottomStart;
10523         radius.radiusBottomRight = isRightToLeft ? radiusBottomStart : radiusBottomEnd;
10524         radius.multiValued = true;
10525         return;
10526     }
10527     ParseBorderRadiusProps(object, radius);
10528 }
10529 
ParseBorderRadius(const JSRef<JSVal> & args,NG::BorderRadiusProperty & radius)10530 bool JSViewAbstract::ParseBorderRadius(const JSRef<JSVal>& args, NG::BorderRadiusProperty& radius)
10531 {
10532     if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
10533         return false;
10534     }
10535     CalcDimension borderRadius;
10536     if (ParseJsDimensionVpNG(args, borderRadius, true)) {
10537         radius = NG::BorderRadiusProperty(borderRadius);
10538         radius.multiValued = false;
10539     } else if (args->IsObject()) {
10540         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
10541         ParseCommonBorderRadiusProps(object, radius);
10542     } else {
10543         return false;
10544     }
10545     return true;
10546 }
10547 
SetDragPreviewOptionApply(const JSCallbackInfo & info,NG::DragPreviewOption & option)10548 void JSViewAbstract::SetDragPreviewOptionApply(const JSCallbackInfo& info, NG::DragPreviewOption& option)
10549 {
10550     JSRef<JSVal> arg = info[0];
10551     if (!arg->IsObject()) {
10552         return;
10553     }
10554     JSRef<JSObject> obj = JSRef<JSObject>::Cast(arg);
10555     auto vm = info.GetVm();
10556     auto globalObj = JSNApi::GetGlobalObject(vm);
10557     auto globalFunc = globalObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "applyImageModifierToNode"));
10558     JsiValue jsiValue(globalFunc);
10559     JsiRef<JsiValue> globalFuncRef = JsiRef<JsiValue>::Make(jsiValue);
10560     if (globalFuncRef->IsFunction()) {
10561         auto modifierObj = obj->GetProperty("modifier");
10562         if (modifierObj->IsUndefined()) {
10563             option.onApply = nullptr;
10564         } else {
10565             RefPtr<JsFunction> jsFunc =
10566                 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(globalFuncRef));
10567             auto onApply = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
10568                                modifier = std::move(modifierObj)](WeakPtr<NG::FrameNode> frameNode) {
10569                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
10570                 auto node = frameNode.Upgrade();
10571                 JSRef<JSVal> params[PARAMETER_LENGTH_SECOND];
10572                 params[0] = modifier;
10573                 params[1] = JSRef<JSVal>::Make(panda::NativePointerRef::New(execCtx.vm_, AceType::RawPtr(node)));
10574                 PipelineContext::SetCallBackNode(node);
10575                 func->ExecuteJS(PARAMETER_LENGTH_SECOND, params);
10576             };
10577             option.onApply = onApply;
10578         }
10579     }
10580 }
10581 
SetDragNumberBadge(const JSCallbackInfo & info,NG::DragPreviewOption & option)10582 void JSViewAbstract::SetDragNumberBadge(const JSCallbackInfo& info, NG::DragPreviewOption& option)
10583 {
10584     if (!info[0]->IsObject()) {
10585         return;
10586     }
10587     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
10588     auto numberBadge = obj->GetProperty("numberBadge");
10589     if (!numberBadge->IsEmpty()) {
10590         if (numberBadge->IsNumber()) {
10591             int64_t number = numberBadge->ToNumber<int64_t>();
10592             if (number < 0 || number > INT_MAX) {
10593                 option.isNumber = false;
10594                 option.isShowBadge = true;
10595             } else {
10596                 option.isNumber = true;
10597                 option.badgeNumber = numberBadge->ToNumber<int>();
10598             }
10599         } else if (numberBadge->IsBoolean()) {
10600             option.isNumber = false;
10601             option.isShowBadge = numberBadge->ToBoolean();
10602         }
10603     } else {
10604         option.isNumber = false;
10605         option.isShowBadge = true;
10606     }
10607 }
10608 
SetDialogProperties(const JSRef<JSObject> & obj,DialogProperties & properties)10609 void JSViewAbstract::SetDialogProperties(const JSRef<JSObject>& obj, DialogProperties& properties)
10610 {
10611     // Parse cornerRadius.
10612     auto cornerRadiusValue = obj->GetProperty("cornerRadius");
10613     NG::BorderRadiusProperty radius;
10614     if (ParseBorderRadius(cornerRadiusValue, radius)) {
10615         properties.borderRadius = radius;
10616     }
10617     // Parse border width
10618     auto borderWidthValue = obj->GetProperty("borderWidth");
10619     NG::BorderWidthProperty borderWidth;
10620     if (ParseBorderWidthProps(borderWidthValue, borderWidth)) {
10621         properties.borderWidth = borderWidth;
10622         auto colorValue = obj->GetProperty("borderColor");
10623         NG::BorderColorProperty borderColor;
10624         if (ParseBorderColorProps(colorValue, borderColor)) {
10625             properties.borderColor = borderColor;
10626         } else {
10627             borderColor.SetColor(Color::BLACK);
10628             properties.borderColor = borderColor;
10629         }
10630         // Parse border style
10631         auto styleValue = obj->GetProperty("borderStyle");
10632         NG::BorderStyleProperty borderStyle;
10633         if (ParseBorderStyleProps(styleValue, borderStyle)) {
10634             properties.borderStyle = borderStyle;
10635         } else {
10636             properties.borderStyle = NG::BorderStyleProperty(
10637                 { BorderStyle::SOLID, BorderStyle::SOLID, BorderStyle::SOLID, BorderStyle::SOLID });
10638         }
10639     }
10640     auto shadowValue = obj->GetProperty("shadow");
10641     Shadow shadow;
10642     if ((shadowValue->IsObject() || shadowValue->IsNumber()) && ParseShadowProps(shadowValue, shadow)) {
10643         properties.shadow = shadow;
10644     }
10645     auto widthValue = obj->GetProperty("width");
10646     CalcDimension width;
10647     if (ParseJsDimensionVpNG(widthValue, width, true)) {
10648         properties.width = width;
10649     }
10650     auto heightValue = obj->GetProperty("height");
10651     CalcDimension height;
10652     if (ParseJsDimensionVpNG(heightValue, height, true)) {
10653         properties.height = height;
10654     }
10655 }
10656 
SetDialogHoverModeProperties(const JSRef<JSObject> & obj,DialogProperties & properties)10657 void JSViewAbstract::SetDialogHoverModeProperties(const JSRef<JSObject>& obj, DialogProperties& properties)
10658 {
10659     auto enableHoverModeValue = obj->GetProperty("enableHoverMode");
10660     if (enableHoverModeValue->IsBoolean()) {
10661         properties.enableHoverMode = enableHoverModeValue->ToBoolean();
10662     }
10663 
10664     // Parse hoverModeArea
10665     auto hoverModeAreaValue = obj->GetProperty("hoverModeArea");
10666     if (hoverModeAreaValue->IsNumber()) {
10667         auto hoverModeArea = hoverModeAreaValue->ToNumber<int32_t>();
10668         if (hoverModeArea >= 0 && hoverModeArea < static_cast<int32_t>(HOVER_MODE_AREA_TYPE.size())) {
10669             properties.hoverModeArea = HOVER_MODE_AREA_TYPE[hoverModeArea];
10670         }
10671     }
10672 }
10673 
ParseJsGetFunc(const JSCallbackInfo & info,int32_t nodeId)10674 std::function<std::string(const std::string&)> ParseJsGetFunc(const JSCallbackInfo& info, int32_t nodeId)
10675 {
10676     auto* vm = info.GetVm();
10677     return [vm, nodeId](const std::string& key) -> std::string {
10678         std::string resultString = std::string();
10679         CHECK_NULL_RETURN(vm, resultString);
10680         panda::LocalScope scope(vm);
10681         auto global = JSNApi::GetGlobalObject(vm);
10682         auto getCustomProperty = global->Get(vm, panda::StringRef::NewFromUtf8(vm, "__getCustomPropertyString__"));
10683         if (getCustomProperty->IsUndefined() || !getCustomProperty->IsFunction(vm)) {
10684             return resultString;
10685         }
10686         auto obj = getCustomProperty->ToObject(vm);
10687         panda::Local<panda::FunctionRef> func = obj;
10688         panda::Local<panda::JSValueRef> params2[2] = { panda::NumberRef::New(vm, nodeId),
10689             panda::StringRef::NewFromUtf8(vm, key.c_str()) };
10690         auto function = panda::CopyableGlobal(vm, func);
10691         auto callValue = function->Call(vm, function.ToLocal(), params2, 2);
10692         if (callValue.IsNull() || callValue->IsUndefined() || !callValue->IsString(vm)) {
10693             return resultString;
10694         }
10695         auto value = callValue->ToString(vm)->ToString(vm);
10696         return value;
10697     };
10698 }
10699 
ParseJsFunc(const JSCallbackInfo & info,int32_t nodeId)10700 std::function<bool()> ParseJsFunc(const JSCallbackInfo& info, int32_t nodeId)
10701 {
10702     auto* vm = info.GetVm();
10703     panda::Local<panda::JSValueRef> params3[3] = { panda::NumberRef::New(vm, nodeId), info[0]->GetLocalHandle(),
10704         info[1]->GetLocalHandle() };
10705     return [vm, params3]() -> bool {
10706         CHECK_NULL_RETURN(vm, false);
10707         panda::LocalScope scope(vm);
10708         auto global = JSNApi::GetGlobalObject(vm);
10709         auto setCustomProperty = global->Get(vm, panda::StringRef::NewFromUtf8(vm, "__setCustomProperty__"));
10710         if (setCustomProperty->IsUndefined() || !setCustomProperty->IsFunction(vm)) {
10711             return false;
10712         }
10713         auto obj = setCustomProperty->ToObject(vm);
10714         panda::Local<panda::FunctionRef> func = obj;
10715         auto frameNode = static_cast<NG::FrameNode*>(ViewAbstractModel::GetInstance()->GetFrameNode());
10716         auto nodeId = frameNode->GetId();
10717         auto function = panda::CopyableGlobal(vm, func);
10718         auto customPropertyExisted = function->Call(vm, function.ToLocal(), params3, 3)->ToBoolean(vm)->Value();
10719         if (customPropertyExisted) {
10720             frameNode->SetRemoveCustomProperties([vm, nodeId]() -> void {
10721                 CHECK_NULL_VOID(vm);
10722                 panda::LocalScope scope(vm);
10723                 auto global = JSNApi::GetGlobalObject(vm);
10724                 auto removeCustomProperty =
10725                     global->Get(vm, panda::StringRef::NewFromUtf8(vm, "__removeCustomProperties__"));
10726                 if (removeCustomProperty->IsUndefined() || !removeCustomProperty->IsFunction(vm)) {
10727                     return;
10728                 }
10729                 auto obj = removeCustomProperty->ToObject(vm);
10730                 panda::Local<panda::FunctionRef> func = obj;
10731                 panda::Local<panda::JSValueRef> params[1] = { panda::NumberRef::New(vm, nodeId) };
10732                 auto function = panda::CopyableGlobal(vm, func);
10733                 function->Call(vm, function.ToLocal(), params, 1);
10734             });
10735         }
10736         return true;
10737     };
10738 }
10739 
JsCustomProperty(const JSCallbackInfo & info)10740 void JSViewAbstract::JsCustomProperty(const JSCallbackInfo& info)
10741 {
10742     if (info[0]->GetLocalHandle()->IsUndefined()) {
10743         return;
10744     }
10745     auto* vm = info.GetVm();
10746     CHECK_NULL_VOID(vm);
10747     auto frameNode = static_cast<NG::FrameNode*>(ViewAbstractModel::GetInstance()->GetFrameNode());
10748     auto nodeId = frameNode->GetId();
10749     auto getFunc = ParseJsGetFunc(info, nodeId);
10750     auto func = ParseJsFunc(info, nodeId);
10751     frameNode->SetJSCustomProperty(func, getFunc);
10752 }
10753 
JsGestureModifier(const JSCallbackInfo & info)10754 void JSViewAbstract::JsGestureModifier(const JSCallbackInfo& info)
10755 {
10756     auto* vm = info.GetExecutionContext().vm_;
10757     CHECK_NULL_VOID(vm);
10758     auto global = JSNApi::GetGlobalObject(vm);
10759     auto gestureModifier = global->Get(vm, panda::StringRef::NewFromUtf8(vm, "__gestureModifier__"));
10760     if (gestureModifier->IsUndefined() || !gestureModifier->IsFunction(vm)) {
10761         return;
10762     }
10763     auto obj = gestureModifier->ToObject(vm);
10764     panda::Local<panda::FunctionRef> func = obj;
10765     auto thisObj = info.This()->GetLocalHandle();
10766     panda::Local<panda::JSValueRef> params[1] = { info[0]->GetLocalHandle() };
10767     func->Call(vm, thisObj, params, 1);
10768 }
10769 
JsBackgroundImageResizable(const JSCallbackInfo & info)10770 void JSViewAbstract::JsBackgroundImageResizable(const JSCallbackInfo& info)
10771 {
10772     auto infoObj = info[0];
10773     ImageResizableSlice sliceResult;
10774     if (!infoObj->IsObject()) {
10775         ViewAbstractModel::GetInstance()->SetBackgroundImageResizableSlice(sliceResult);
10776         return;
10777     }
10778     JSRef<JSObject> resizableObject = JSRef<JSObject>::Cast(infoObj);
10779     if (resizableObject->IsEmpty()) {
10780         ViewAbstractModel::GetInstance()->SetBackgroundImageResizableSlice(sliceResult);
10781         return;
10782     }
10783     auto sliceValue = resizableObject->GetProperty("slice");
10784     if (!sliceValue->IsObject()) {
10785         return;
10786     }
10787     JSRef<JSObject> sliceObj = JSRef<JSObject>::Cast(sliceValue);
10788     if (sliceObj->IsEmpty()) {
10789         ViewAbstractModel::GetInstance()->SetBackgroundImageResizableSlice(sliceResult);
10790         return;
10791     }
10792     for (uint32_t i = 0; i < SLICE_KEYS.size(); i++) {
10793         auto sliceSize = sliceObj->GetProperty(SLICE_KEYS.at(i).c_str());
10794         CalcDimension sliceDimension;
10795         if (!ParseJsDimensionVp(sliceSize, sliceDimension)) {
10796             continue;
10797         }
10798         if (!sliceDimension.IsValid()) {
10799             continue;
10800         }
10801         switch (static_cast<BorderImageDirection>(i)) {
10802             case BorderImageDirection::LEFT:
10803                 sliceResult.left = sliceDimension;
10804                 break;
10805             case BorderImageDirection::RIGHT:
10806                 sliceResult.right = sliceDimension;
10807                 break;
10808             case BorderImageDirection::TOP:
10809                 sliceResult.top = sliceDimension;
10810                 break;
10811             case BorderImageDirection::BOTTOM:
10812                 sliceResult.bottom = sliceDimension;
10813                 break;
10814             default:
10815                 break;
10816         }
10817     }
10818     ViewAbstractModel::GetInstance()->SetBackgroundImageResizableSlice(sliceResult);
10819 }
10820 
JsFocusScopeId(const JSCallbackInfo & info)10821 void JSViewAbstract::JsFocusScopeId(const JSCallbackInfo& info)
10822 {
10823     if (info.Length() == 0) {
10824         return;
10825     }
10826 
10827     std::string focusScopeId;
10828     if (info[0]->IsString()) {
10829         focusScopeId = info[0]->ToString();
10830     }
10831 
10832     bool isGroup = false;
10833     if (info.Length() >= PARAMETER_LENGTH_SECOND && !info[1]->IsNull() && !info[1]->IsUndefined() &&
10834         info[1]->IsBoolean()) {
10835         isGroup = info[1]->ToBoolean();
10836     }
10837     bool arrowKeyStepOut = true;
10838     if (info.Length() >= PARAMETER_LENGTH_THIRD && !info[2]->IsNull() && !info[2]->IsUndefined() &&
10839         info[2]->IsBoolean()) {
10840         arrowKeyStepOut = info[2]->ToBoolean();
10841     }
10842     ViewAbstractModel::GetInstance()->SetFocusScopeId(focusScopeId, isGroup, arrowKeyStepOut);
10843 }
10844 
JsFocusScopePriority(const JSCallbackInfo & info)10845 void JSViewAbstract::JsFocusScopePriority(const JSCallbackInfo& info)
10846 {
10847     if (info.Length() == 0) {
10848         return;
10849     }
10850 
10851     if (!info[0]->IsString() || info[0]->IsNull() || info[0]->IsUndefined()) {
10852         return;
10853     }
10854     std::string focusScopeId = info[0]->ToString();
10855 
10856     int32_t focusPriority = 0;
10857     if (info.Length() == PARAMETER_LENGTH_SECOND && !info[0]->IsNull() && !info[0]->IsUndefined() &&
10858         info[1]->IsNumber()) {
10859         focusPriority = info[1]->ToNumber<int32_t>();
10860     }
10861     ViewAbstractModel::GetInstance()->SetFocusScopePriority(focusScopeId, focusPriority);
10862 }
10863 
ParseJsPropertyId(const JSRef<JSVal> & jsValue)10864 int32_t JSViewAbstract::ParseJsPropertyId(const JSRef<JSVal>& jsValue)
10865 {
10866     int32_t resId = 0;
10867     if (jsValue->IsObject()) {
10868         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
10869         JSRef<JSVal> tmp = jsObj->GetProperty("id");
10870         if (!tmp->IsNull() && tmp->IsNumber()) {
10871             resId = tmp->ToNumber<int32_t>();
10872         }
10873     }
10874     return resId;
10875 }
10876 
JsVisualEffect(const JSCallbackInfo & info)10877 void JSViewAbstract::JsVisualEffect(const JSCallbackInfo& info)
10878 {
10879     if (!info[0]->IsObject()) {
10880         return;
10881     }
10882     auto visualEffect = CreateRSEffectFromNapiValue(info[0]);
10883     ViewAbstractModel::GetInstance()->SetVisualEffect(visualEffect);
10884 }
10885 
JsBackgroundFilter(const JSCallbackInfo & info)10886 void JSViewAbstract::JsBackgroundFilter(const JSCallbackInfo& info)
10887 {
10888     if (!info[0]->IsObject()) {
10889         return;
10890     }
10891     auto backgroundFilter = CreateRSFilterFromNapiValue(info[0]);
10892     ViewAbstractModel::GetInstance()->SetBackgroundFilter(backgroundFilter);
10893 }
10894 
JsForegroundFilter(const JSCallbackInfo & info)10895 void JSViewAbstract::JsForegroundFilter(const JSCallbackInfo& info)
10896 {
10897     if (!info[0]->IsObject()) {
10898         return;
10899     }
10900     auto foregroundFilter = CreateRSFilterFromNapiValue(info[0]);
10901     ViewAbstractModel::GetInstance()->SetForegroundFilter(foregroundFilter);
10902 }
10903 
JsCompositingFilter(const JSCallbackInfo & info)10904 void JSViewAbstract::JsCompositingFilter(const JSCallbackInfo& info)
10905 {
10906     if (!info[0]->IsObject()) {
10907         return;
10908     }
10909     auto compositingFilter = CreateRSFilterFromNapiValue(info[0]);
10910     ViewAbstractModel::GetInstance()->SetCompositingFilter(compositingFilter);
10911 }
10912 
ParseOnCreateMenu(const JSCallbackInfo & info,const JSRef<JSVal> & jsFunc,NG::OnCreateMenuCallback & onCreateMenuCallback)10913 void JSViewAbstract::ParseOnCreateMenu(
10914     const JSCallbackInfo& info, const JSRef<JSVal>& jsFunc, NG::OnCreateMenuCallback& onCreateMenuCallback)
10915 {
10916     if (jsFunc.IsEmpty() || !jsFunc->IsFunction()) {
10917         return;
10918     }
10919     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
10920     auto jsOnCreateMenu = AceType::MakeRefPtr<JsEventFunction<std::vector<NG::MenuItemParam>, 1>>(
10921         JSRef<JSFunc>::Cast(jsFunc), CreateJsSystemMenuItems);
10922     auto jsCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsOnCreateMenu),
10923                           instanceId = Container::CurrentId(), node = frameNode](
10924                           const std::vector<NG::MenuItemParam>& systemMenuItems) -> std::vector<NG::MenuOptionsParam> {
10925         ContainerScope scope(instanceId);
10926         std::vector<NG::MenuOptionsParam> menuParams;
10927         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, menuParams);
10928         auto pipelineContext = PipelineContext::GetCurrentContext();
10929         CHECK_NULL_RETURN(pipelineContext, menuParams);
10930 
10931         pipelineContext->UpdateCurrentActiveNode(node);
10932         auto menuItem = func->ExecuteWithValue(systemMenuItems);
10933         if (!menuItem->IsArray()) {
10934             return menuParams;
10935         }
10936         auto menuItemsArray = JSRef<JSArray>::Cast(menuItem);
10937         for (size_t i = 0; i <= menuItemsArray->Length(); i++) {
10938             auto menuItem = menuItemsArray->GetValueAt(i);
10939             if (!menuItem->IsObject()) {
10940                 continue;
10941             }
10942             auto menuItemObject = JSRef<JSObject>::Cast(menuItem);
10943             NG::MenuOptionsParam menuOptionsParam;
10944             auto jsContent = menuItemObject->GetProperty("content");
10945             std::string content;
10946             ParseJsString(jsContent, content);
10947             menuOptionsParam.content = content;
10948             auto jsStartIcon = menuItemObject->GetProperty("icon");
10949             std::string icon;
10950             ParseJsMedia(jsStartIcon, icon);
10951             menuOptionsParam.icon = icon;
10952             auto jsTextMenuId = menuItemObject->GetProperty("id");
10953             std::string id;
10954             if (jsTextMenuId->IsObject()) {
10955                 auto textMenuIdObject = JSRef<JSObject>::Cast(jsTextMenuId);
10956                 auto jsId = textMenuIdObject->GetProperty("id_");
10957                 ParseJsString(jsId, id);
10958             }
10959             menuOptionsParam.id = id;
10960             menuParams.emplace_back(menuOptionsParam);
10961         }
10962         return menuParams;
10963     };
10964     onCreateMenuCallback = jsCallback;
10965 }
10966 
CreateJsSystemMenuItems(const std::vector<NG::MenuItemParam> & systemMenuItems)10967 JSRef<JSVal> JSViewAbstract::CreateJsSystemMenuItems(const std::vector<NG::MenuItemParam>& systemMenuItems)
10968 {
10969     JSRef<JSArray> systemMenuItemsArray = JSRef<JSArray>::New();
10970     uint32_t idx = 0;
10971     for (const auto& item : systemMenuItems) {
10972         systemMenuItemsArray->SetValueAt(idx++, CreateJsTextMenuItem(item));
10973     }
10974     return systemMenuItemsArray;
10975 }
10976 
ParseEditMenuOptions(const JSCallbackInfo & info,NG::OnCreateMenuCallback & onCreateMenuCallback,NG::OnMenuItemClickCallback & onMenuItemClick)10977 bool JSViewAbstract::ParseEditMenuOptions(const JSCallbackInfo& info, NG::OnCreateMenuCallback& onCreateMenuCallback,
10978     NG::OnMenuItemClickCallback& onMenuItemClick)
10979 {
10980     auto tmpInfo = info[0];
10981     if (info.Length() != 1 || !tmpInfo->IsObject()) {
10982         return false;
10983     }
10984     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
10985     auto menuOptionsObject = JSRef<JSObject>::Cast(tmpInfo);
10986     auto jsValueOnCreateMenu = menuOptionsObject->GetProperty("onCreateMenu");
10987     ParseOnCreateMenu(info, jsValueOnCreateMenu, onCreateMenuCallback);
10988 
10989     auto jsValue = menuOptionsObject->GetProperty("onMenuItemClick");
10990     if (jsValue.IsEmpty() || !jsValue->IsFunction()) {
10991         return false;
10992     }
10993     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(jsValue));
10994     auto jsCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
10995                           onMenuItemCallback = std::move(CreateJsOnMenuItemClick), instanceId = Container::CurrentId(),
10996                           node = frameNode](NG::MenuItemParam menuOptionsParam) -> bool {
10997         ContainerScope scope(instanceId);
10998         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, false);
10999         auto pipelineContext = PipelineContext::GetCurrentContext();
11000         CHECK_NULL_RETURN(pipelineContext, false);
11001         pipelineContext->UpdateCurrentActiveNode(node);
11002         auto paramArray = onMenuItemCallback(menuOptionsParam);
11003         if (paramArray->Length() != 2) {
11004             return false;
11005         }
11006         JSRef<JSVal> params[2];
11007         params[0] = JSRef<JSVal>::Cast(paramArray->GetValueAt(0));
11008         params[1] = JSRef<JSVal>::Cast(paramArray->GetValueAt(1));
11009         auto ret = func->ExecuteJS(2, params);
11010         if (ret->IsBoolean()) {
11011             return ret->ToBoolean();
11012         }
11013         return false;
11014     };
11015     onMenuItemClick = jsCallback;
11016     return true;
11017 }
11018 
CreateJsTextMenuId(const std::string & id)11019 JSRef<JSObject> JSViewAbstract::CreateJsTextMenuId(const std::string& id)
11020 {
11021     JSRef<JSObject> empty;
11022     auto engine = EngineHelper::GetCurrentEngine();
11023     CHECK_NULL_RETURN(engine, empty);
11024     NativeEngine* nativeEngine = engine->GetNativeEngine();
11025     CHECK_NULL_RETURN(nativeEngine, empty);
11026     auto env = reinterpret_cast<napi_env>(nativeEngine);
11027 
11028     napi_value global;
11029     napi_status ret = napi_get_global(env, &global);
11030     if (ret != napi_ok) {
11031         return empty;
11032     }
11033     napi_value constructor;
11034     ret = napi_get_named_property(env, global, JS_TEXT_MENU_ID_CLASS_NAME, &constructor);
11035     if (ret != napi_ok) {
11036         return empty;
11037     }
11038 
11039     napi_value obj;
11040     napi_value menuId = nullptr;
11041 
11042     ret = napi_create_string_utf8(env, id.c_str(), id.length(), &menuId);
11043     if (ret != napi_ok) {
11044         return empty;
11045     }
11046     ret = napi_new_instance(env, constructor, NUM1, &menuId, &obj);
11047     if (ret != napi_ok) {
11048         return empty;
11049     }
11050 
11051     JSRef<JSVal> value = JsConverter::ConvertNapiValueToJsVal(obj);
11052     if (!value->IsObject()) {
11053         return empty;
11054     }
11055 
11056     return JSRef<JSObject>::Cast(value);
11057 }
11058 
CreateJsOnMenuItemClick(const NG::MenuItemParam & menuItemParam)11059 JSRef<JSArray> JSViewAbstract::CreateJsOnMenuItemClick(const NG::MenuItemParam& menuItemParam)
11060 {
11061     JSRef<JSArray> params = JSRef<JSArray>::New();
11062     params->SetValueAt(0, CreateJsTextMenuItem(menuItemParam));
11063     params->SetValueAt(1, CreateJsTextRange(menuItemParam));
11064     return params;
11065 }
11066 
CreateJsTextMenuItem(const NG::MenuItemParam & menuItemParam)11067 JSRef<JSVal> JSViewAbstract::CreateJsTextMenuItem(const NG::MenuItemParam& menuItemParam)
11068 {
11069     JSRef<JSObject> TextMenuItem = JSRef<JSObject>::New();
11070     TextMenuItem->SetProperty<std::string>("content", menuItemParam.menuOptionsParam.content.value_or(""));
11071     JSRef<JSObject> obj = CreateJsTextMenuId(menuItemParam.menuOptionsParam.id);
11072     TextMenuItem->SetPropertyObject("id", obj);
11073     return JSRef<JSVal>::Cast(TextMenuItem);
11074 }
11075 
CreateJsTextRange(const NG::MenuItemParam & menuItemParam)11076 JSRef<JSVal> JSViewAbstract::CreateJsTextRange(const NG::MenuItemParam& menuItemParam)
11077 {
11078     JSRef<JSObject> textRange = JSRef<JSObject>::New();
11079     textRange->SetProperty<int32_t>("start", menuItemParam.start);
11080     textRange->SetProperty<int32_t>("end", menuItemParam.end);
11081     return JSRef<JSVal>::Cast(textRange);
11082 }
11083 
OHOS_ACE_ParseJsMedia(void * value,void * resource)11084 extern "C" ACE_FORCE_EXPORT void OHOS_ACE_ParseJsMedia(void* value, void* resource)
11085 {
11086     napi_value napiValue = reinterpret_cast<napi_value>(value);
11087     ArkUI_Resource* res = reinterpret_cast<ArkUI_Resource*>(resource);
11088     if (!napiValue || !res) {
11089         return;
11090     }
11091     JSRef<JSVal> jsVal = JsConverter::ConvertNapiValueToJsVal(napiValue);
11092     std::string src;
11093     std::string bundleName;
11094     std::string moduleName;
11095     JSViewAbstract::ParseJsMedia(jsVal, src);
11096     JSViewAbstract::GetJsMediaBundleInfo(jsVal, bundleName, moduleName);
11097     res->resId = JSViewAbstract::ParseJsPropertyId(jsVal);
11098     res->src = src;
11099     res->bundleName = bundleName;
11100     res->moduleName = moduleName;
11101 }
11102 
SetTextStyleApply(const JSCallbackInfo & info,std::function<void (WeakPtr<NG::FrameNode>)> & textStyleApply,const JSRef<JSVal> & modifierObj)11103 void JSViewAbstract::SetTextStyleApply(const JSCallbackInfo& info,
11104     std::function<void(WeakPtr<NG::FrameNode>)>& textStyleApply, const JSRef<JSVal>& modifierObj)
11105 {
11106     if (!modifierObj->IsObject()) {
11107         textStyleApply = nullptr;
11108         return;
11109     }
11110     auto vm = info.GetVm();
11111     auto globalObj = JSNApi::GetGlobalObject(vm);
11112     auto globalFunc = globalObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "applyTextModifierToNode"));
11113     JsiValue jsiValue(globalFunc);
11114     JsiRef<JsiValue> globalFuncRef = JsiRef<JsiValue>::Make(jsiValue);
11115     if (!globalFuncRef->IsFunction()) {
11116         textStyleApply = nullptr;
11117         return;
11118     }
11119     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(globalFuncRef));
11120     auto onApply = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
11121                     modifierParam = std::move(modifierObj)](WeakPtr<NG::FrameNode> frameNode) {
11122         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
11123         auto node = frameNode.Upgrade();
11124         CHECK_NULL_VOID(node);
11125         JSRef<JSVal> params[2];
11126         params[0] = modifierParam;
11127         params[1] = JSRef<JSVal>::Make(panda::NativePointerRef::New(execCtx.vm_, AceType::RawPtr(node)));
11128         PipelineContext::SetCallBackNode(node);
11129         func->ExecuteJS(2, params);
11130     };
11131     textStyleApply = onApply;
11132 }
11133 
SetSymbolOptionApply(const JSCallbackInfo & info,std::function<void (WeakPtr<NG::FrameNode>)> & symbolApply,const JSRef<JSVal> modifierObj)11134 void JSViewAbstract::SetSymbolOptionApply(const JSCallbackInfo& info,
11135     std::function<void(WeakPtr<NG::FrameNode>)>& symbolApply, const JSRef<JSVal> modifierObj)
11136 {
11137     auto vm = info.GetVm();
11138     auto globalObj = JSNApi::GetGlobalObject(vm);
11139     auto globalFunc = globalObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "applySymbolGlyphModifierToNode"));
11140     JsiValue jsiValue(globalFunc);
11141     JsiRef<JsiValue> globalFuncRef = JsiRef<JsiValue>::Make(jsiValue);
11142     if (globalFuncRef->IsFunction()) {
11143         RefPtr<JsFunction> jsFunc =
11144             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(globalFuncRef));
11145         if (!modifierObj->IsObject()) {
11146             symbolApply = nullptr;
11147         } else {
11148             auto onApply = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
11149                                modifierParam = std::move(modifierObj)](WeakPtr<NG::FrameNode> frameNode) {
11150                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
11151                 auto node = frameNode.Upgrade();
11152                 CHECK_NULL_VOID(node);
11153                 JSRef<JSVal> params[2];
11154                 params[0] = modifierParam;
11155                 params[1] = JSRef<JSVal>::Make(panda::NativePointerRef::New(execCtx.vm_, AceType::RawPtr(node)));
11156                 PipelineContext::SetCallBackNode(node);
11157                 func->ExecuteJS(2, params);
11158             };
11159             symbolApply = onApply;
11160         }
11161     }
11162 }
11163 } // namespace OHOS::Ace::Framework
11164