• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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/utils.h"
42 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
43 #include "bridge/declarative_frontend/engine/functions/js_clipboard_function.h"
44 #include "bridge/declarative_frontend/engine/functions/js_drag_function.h"
45 #include "bridge/declarative_frontend/engine/functions/js_on_child_touch_test_function.h"
46 #include "bridge/declarative_frontend/engine/functions/js_focus_function.h"
47 #include "bridge/declarative_frontend/engine/functions/js_function.h"
48 #include "bridge/declarative_frontend/engine/functions/js_gesture_judge_function.h"
49 #include "bridge/declarative_frontend/engine/functions/js_hover_function.h"
50 #include "bridge/declarative_frontend/engine/functions/js_key_function.h"
51 #include "bridge/declarative_frontend/engine/functions/js_on_area_change_function.h"
52 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
53 #include "bridge/declarative_frontend/jsview/js_animatable_arithmetic.h"
54 #include "bridge/declarative_frontend/jsview/js_grid_container.h"
55 #include "bridge/declarative_frontend/jsview/js_shape_abstract.h"
56 #include "bridge/declarative_frontend/jsview/js_utils.h"
57 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
58 #include "bridge/declarative_frontend/jsview/js_view_context.h"
59 #include "bridge/declarative_frontend/jsview/models/view_abstract_model_impl.h"
60 #include "core/common/resource/resource_manager.h"
61 #include "core/common/resource/resource_object.h"
62 #include "core/components/common/layout/constants.h"
63 #include "core/components/common/layout/screen_system_manager.h"
64 #include "core/components/common/properties/animation_option.h"
65 #include "core/components/common/properties/border_image.h"
66 #include "core/components/common/properties/color.h"
67 #include "core/components/common/properties/decoration.h"
68 #include "core/components/common/properties/invert.h"
69 #include "core/components/common/properties/shadow.h"
70 #include "core/components/common/properties/shadow_config.h"
71 #include "core/components/theme/resource_adapter.h"
72 #include "core/components/theme/shadow_theme.h"
73 #include "core/components_ng/base/view_abstract_model.h"
74 #include "core/components_ng/base/view_stack_processor.h"
75 #include "core/components_ng/gestures/base_gesture_event.h"
76 #include "core/components_ng/pattern/menu/menu_pattern.h"
77 #include "core/components_ng/pattern/overlay/modal_style.h"
78 #include "core/components_ng/property/safe_area_insets.h"
79 #include "core/gestures/gesture_info.h"
80 #include "core/image/image_source_info.h"
81 #ifdef PLUGIN_COMPONENT_SUPPORTED
82 #include "core/common/plugin_manager.h"
83 #endif
84 #include "core/common/card_scope.h"
85 #include "core/common/container.h"
86 #include "core/components/progress/progress_theme.h"
87 #include "core/components_ng/base/view_abstract_model_ng.h"
88 #include "core/components_ng/base/view_stack_model.h"
89 #include "core/components_ng/property/progress_mask_property.h"
90 
91 namespace OHOS::Ace {
92 
93 std::unique_ptr<ViewAbstractModel> ViewAbstractModel::instance_ = nullptr;
94 std::mutex ViewAbstractModel::mutex_;
95 using DoubleBindCallback = std::function<void(const std::string&)>;
96 
GetInstance()97 ViewAbstractModel* ViewAbstractModel::GetInstance()
98 {
99     if (!instance_) {
100         std::lock_guard<std::mutex> lock(mutex_);
101         if (!instance_) {
102 #ifdef NG_BUILD
103             instance_.reset(new NG::ViewAbstractModelNG());
104 #else
105             if (Container::IsCurrentUseNewPipeline()) {
106                 instance_.reset(new NG::ViewAbstractModelNG());
107             } else {
108                 instance_.reset(new Framework::ViewAbstractModelImpl());
109             }
110 #endif
111         }
112     }
113     return instance_.get();
114 }
115 
116 } // namespace OHOS::Ace
117 
118 namespace OHOS::Ace::Framework {
119 namespace {
120 
121 constexpr uint32_t DEFAULT_DURATION = 1000; // ms
122 constexpr int64_t MICROSEC_TO_MILLISEC = 1000;
123 constexpr uint32_t COLOR_ALPHA_OFFSET = 24;
124 constexpr uint32_t COLOR_ALPHA_VALUE = 0xFF000000;
125 constexpr uint32_t SAFE_AREA_TYPE_LIMIT = 3;
126 constexpr uint32_t SAFE_AREA_EDGE_LIMIT = 4;
127 constexpr int32_t MAX_ALIGN_VALUE = 8;
128 constexpr int32_t UNKNOWN_RESOURCE_ID = -1;
129 constexpr int32_t UNKNOWN_RESOURCE_TYPE = -1;
130 const std::regex RESOURCE_APP_STRING_PLACEHOLDER(R"(\%((\d+)(\$)){0,1}([dsf]))", std::regex::icase);
131 const std::regex FLOAT_PATTERN(R"(-?(0|[1-9]\d*)(\.\d+))", std::regex::icase);
132 constexpr double FULL_DIMENSION = 100.0;
133 constexpr double HALF_DIMENSION = 50.0;
134 constexpr double ROUND_UNIT = 360.0;
135 constexpr double VISIBLE_RATIO_MIN = 0.0;
136 constexpr double VISIBLE_RATIO_MAX = 1.0;
137 constexpr int32_t PARAMETER_LENGTH_FIRST = 1;
138 constexpr int32_t PARAMETER_LENGTH_SECOND = 2;
139 constexpr int32_t PARAMETER_LENGTH_THIRD = 3;
140 constexpr float DEFAULT_SCALE_LIGHT = 0.9f;
141 constexpr float DEFAULT_SCALE_MIDDLE_OR_HEAVY = 0.95f;
142 constexpr float MAX_ANGLE = 360.0f;
143 constexpr float DEFAULT_BIAS = 0.5f;
144 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
145 const std::vector<std::string> TEXT_DETECT_TYPES = { "phoneNum", "url", "email", "location" };
146 const std::vector<std::string> RESOURCE_HEADS = { "app", "sys" };
147 const std::string SHEET_HEIGHT_MEDIUM = "medium";
148 const std::string SHEET_HEIGHT_LARGE = "large";
149 const std::string SHEET_HEIGHT_AUTO = "auto";
150 const std::string SHEET_HEIGHT_FITCONTENT = "fit_content";
151 const std::string BLOOM_RADIUS_SYS_RES_NAME = "sys.float.ohos_id_point_light_bloom_radius";
152 const std::string BLOOM_COLOR_SYS_RES_NAME = "sys.color.ohos_id_point_light_bloom_color";
153 const std::string ILLUMINATED_BORDER_WIDTH_SYS_RES_NAME = "sys.float.ohos_id_point_light_illuminated_border_width";
154 
155 constexpr Dimension ARROW_ZERO_PERCENT_VALUE = 0.0_pct;
156 constexpr Dimension ARROW_HALF_PERCENT_VALUE = 0.5_pct;
157 constexpr Dimension ARROW_ONE_HUNDRED_PERCENT_VALUE = 1.0_pct;
158 
CheckJSCallbackInfo(const std::string & callerName,const JSCallbackInfo & info,std::vector<JSCallbackInfoType> & infoTypes)159 bool CheckJSCallbackInfo(
160     const std::string& callerName, const JSCallbackInfo& info, std::vector<JSCallbackInfoType>& infoTypes)
161 {
162     bool typeVerified = false;
163     std::string unrecognizedType;
164     auto tmpInfo = info[0];
165     for (const auto& infoType : infoTypes) {
166         switch (infoType) {
167             case JSCallbackInfoType::STRING:
168                 if (tmpInfo->IsString()) {
169                     typeVerified = true;
170                 } else {
171                     unrecognizedType += "string|";
172                 }
173                 break;
174             case JSCallbackInfoType::NUMBER:
175                 if (tmpInfo->IsNumber()) {
176                     typeVerified = true;
177                 } else {
178                     unrecognizedType += "number|";
179                 }
180                 break;
181             case JSCallbackInfoType::OBJECT:
182                 if (tmpInfo->IsObject()) {
183                     typeVerified = true;
184                 } else {
185                     unrecognizedType += "object|";
186                 }
187                 break;
188             case JSCallbackInfoType::FUNCTION:
189                 if (tmpInfo->IsFunction()) {
190                     typeVerified = true;
191                 } else {
192                     unrecognizedType += "Function|";
193                 }
194                 break;
195             default:
196                 break;
197         }
198     }
199     if (!typeVerified) {
200         LOGD("%{public}s: info[0] is not a [%{public}s]", callerName.c_str(),
201             unrecognizedType.substr(0, unrecognizedType.size() - 1).c_str());
202     }
203     return typeVerified || infoTypes.size() == 0;
204 }
205 
ParseJsonScale(std::unique_ptr<JsonValue> & argsPtrItem,float & scaleX,float & scaleY,float & scaleZ,CalcDimension & centerX,CalcDimension & centerY)206 void ParseJsonScale(std::unique_ptr<JsonValue>& argsPtrItem, float& scaleX, float& scaleY, float& scaleZ,
207     CalcDimension& centerX, CalcDimension& centerY)
208 {
209     double xVal = 1.0;
210     double yVal = 1.0;
211     double zVal = 1.0;
212     if (!argsPtrItem->IsObject() && !argsPtrItem->IsNumber() && !argsPtrItem->IsString()) {
213         scaleX = static_cast<float>(xVal);
214         scaleY = static_cast<float>(yVal);
215         scaleZ = static_cast<float>(zVal);
216         CalcDimension length;
217         centerX = length;
218         centerY = length;
219         return;
220     }
221     JSViewAbstract::ParseJsonDouble(argsPtrItem->GetValue("x"), xVal);
222     JSViewAbstract::ParseJsonDouble(argsPtrItem->GetValue("y"), yVal);
223     JSViewAbstract::ParseJsonDouble(argsPtrItem->GetValue("z"), zVal);
224     scaleX = static_cast<float>(xVal);
225     scaleY = static_cast<float>(yVal);
226     scaleZ = static_cast<float>(zVal);
227     // if specify centerX
228     CalcDimension length;
229     if (JSViewAbstract::ParseJsonDimensionVp(argsPtrItem->GetValue("centerX"), length)) {
230         centerX = length;
231     }
232     // if specify centerY
233     if (JSViewAbstract::ParseJsonDimensionVp(argsPtrItem->GetValue("centerY"), length)) {
234         centerY = length;
235     }
236 }
237 
ParseJsScale(const JSRef<JSVal> & jsValue,float & scaleX,float & scaleY,float & scaleZ,CalcDimension & centerX,CalcDimension & centerY)238 void ParseJsScale(const JSRef<JSVal>& jsValue, float& scaleX, float& scaleY, float& scaleZ,
239     CalcDimension& centerX, CalcDimension& centerY)
240 {
241     double xVal = 1.0;
242     double yVal = 1.0;
243     double zVal = 1.0;
244     if (!jsValue->IsObject()) {
245         scaleX = static_cast<float>(xVal);
246         scaleY = static_cast<float>(yVal);
247         scaleZ = static_cast<float>(zVal);
248         CalcDimension length;
249         centerX = length;
250         centerY = length;
251         return;
252     }
253     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
254     JSViewAbstract::ParseJsDouble(jsObj->GetProperty("x"), xVal);
255     JSViewAbstract::ParseJsDouble(jsObj->GetProperty("y"), yVal);
256     JSViewAbstract::ParseJsDouble(jsObj->GetProperty("z"), zVal);
257     scaleX = static_cast<float>(xVal);
258     scaleY = static_cast<float>(yVal);
259     scaleZ = static_cast<float>(zVal);
260     // if specify centerX
261     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty("centerX"), centerX);
262     // if specify centerY
263     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty("centerY"), centerY);
264 }
265 
ParseJsonTranslate(std::unique_ptr<JsonValue> & argsPtrItem,CalcDimension & translateX,CalcDimension & translateY,CalcDimension & translateZ)266 void ParseJsonTranslate(std::unique_ptr<JsonValue>& argsPtrItem, CalcDimension& translateX, CalcDimension& translateY,
267     CalcDimension& translateZ)
268 {
269     CalcDimension length;
270     if (JSViewAbstract::ParseJsonDimensionVp(argsPtrItem->GetValue("x"), length)) {
271         translateX = length;
272     }
273     if (JSViewAbstract::ParseJsonDimensionVp(argsPtrItem->GetValue("y"), length)) {
274         translateY = length;
275     }
276     if (JSViewAbstract::ParseJsonDimensionVp(argsPtrItem->GetValue("z"), length)) {
277         translateZ = length;
278     }
279 }
280 
ParseJsTranslate(const JSRef<JSVal> & jsValue,CalcDimension & translateX,CalcDimension & translateY,CalcDimension & translateZ)281 void ParseJsTranslate(const JSRef<JSVal>& jsValue, CalcDimension& translateX, CalcDimension& translateY,
282     CalcDimension& translateZ)
283 {
284     if (!jsValue->IsObject()) {
285         return;
286     }
287     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
288     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty("x"), translateX);
289     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty("y"), translateY);
290     JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty("z"), translateZ);
291 }
292 
GetDefaultRotateVector(double & dx,double & dy,double & dz)293 void GetDefaultRotateVector(double& dx, double& dy, double& dz)
294 {
295     dx = 0.0;
296     dy = 0.0;
297     dz = 0.0;
298     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_NINE)) {
299         dz = 1.0;
300     }
301 }
302 
ParseJsonRotate(std::unique_ptr<JsonValue> & argsPtrItem,NG::RotateOptions & rotate,std::optional<float> & angle)303 void ParseJsonRotate(std::unique_ptr<JsonValue>& argsPtrItem, NG::RotateOptions& rotate, std::optional<float>& angle)
304 {
305     // default: dx, dy, dz (0.0, 0.0, 0.0)
306     double dxVal = 0.0;
307     double dyVal = 0.0;
308     double dzVal = 0.0;
309     if (!argsPtrItem->Contains("x") && !argsPtrItem->Contains("y") && !argsPtrItem->Contains("z")) {
310         GetDefaultRotateVector(dxVal, dyVal, dzVal);
311     }
312     JSViewAbstract::ParseJsonDouble(argsPtrItem->GetValue("x"), dxVal);
313     JSViewAbstract::ParseJsonDouble(argsPtrItem->GetValue("y"), dyVal);
314     JSViewAbstract::ParseJsonDouble(argsPtrItem->GetValue("z"), dzVal);
315     rotate.xDirection = static_cast<float>(dxVal);
316     rotate.yDirection = static_cast<float>(dyVal);
317     rotate.zDirection = static_cast<float>(dzVal);
318     // if specify centerX
319     CalcDimension length;
320     if (!JSViewAbstract::ParseJsonDimensionVp(argsPtrItem->GetValue("centerX"), length, true)) {
321         length = Dimension(0.5f, DimensionUnit::PERCENT);
322     }
323     rotate.centerX = length;
324     // if specify centerY
325 
326     if (!JSViewAbstract::ParseJsonDimensionVp(argsPtrItem->GetValue("centerY"), length, true)) {
327         length = Dimension(0.5f, DimensionUnit::PERCENT);
328     }
329     rotate.centerY = length;
330 
331     // if specify centerZ
332     if (!JSViewAbstract::ParseJsonDimensionVp(argsPtrItem->GetValue("centerZ"), length, true)) {
333         length = Dimension(0.5f, DimensionUnit::PERCENT);
334     }
335     rotate.centerZ = length;
336     // if specify angle
337     JSViewAbstract::GetAngle("angle", argsPtrItem, angle);
338     float perspective = 0.0f;
339     JSViewAbstract::GetPerspective("perspective", argsPtrItem, perspective);
340     rotate.perspective = perspective;
341 }
342 
ParseJsRotate(const JSRef<JSVal> & jsValue,NG::RotateOptions & rotate,std::optional<float> & angle)343 void ParseJsRotate(const JSRef<JSVal>& jsValue, NG::RotateOptions& rotate, std::optional<float>& angle)
344 {
345     if (!jsValue->IsObject()) {
346         return;
347     }
348     // default: dx, dy, dz (0.0, 0.0, 0.0)
349     double dxVal = 0.0;
350     double dyVal = 0.0;
351     double dzVal = 0.0;
352     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
353     if (!jsObj->HasProperty("x") && !jsObj->HasProperty("y") && !jsObj->HasProperty("z")) {
354         GetDefaultRotateVector(dxVal, dyVal, dzVal);
355     } else {
356         JSViewAbstract::ParseJsDouble(jsObj->GetProperty("x"), dxVal);
357         JSViewAbstract::ParseJsDouble(jsObj->GetProperty("y"), dyVal);
358         JSViewAbstract::ParseJsDouble(jsObj->GetProperty("z"), dzVal);
359     }
360     rotate.xDirection = static_cast<float>(dxVal);
361     rotate.yDirection = static_cast<float>(dyVal);
362     rotate.zDirection = static_cast<float>(dzVal);
363     // if specify centerX
364     if (!JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty("centerX"), rotate.centerX)) {
365         rotate.centerX = Dimension(0.5f, DimensionUnit::PERCENT);
366     }
367     // if specify centerY
368     if (!JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty("centerY"), rotate.centerY)) {
369         rotate.centerY = Dimension(0.5f, DimensionUnit::PERCENT);
370     }
371     // if specify centerZ
372     if (!JSViewAbstract::ParseJsDimensionVp(jsObj->GetProperty("centerZ"), rotate.centerZ)) {
373         rotate.centerZ = Dimension(0.5f, DimensionUnit::PERCENT);
374     }
375     // if specify angle
376     JSViewAbstract::GetJsAngle("angle", jsObj, angle);
377     rotate.perspective = 0.0f;
378     JSViewAbstract::GetJsPerspective("perspective", jsObj, rotate.perspective);
379 }
380 
ParseMotionPath(const JSRef<JSVal> & jsValue,MotionPathOption & option)381 bool ParseMotionPath(const JSRef<JSVal>& jsValue, MotionPathOption& option)
382 {
383     if (!jsValue->IsObject()) {
384         return false;
385     }
386 
387     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
388     auto path = jsObj->GetPropertyValue<std::string>("path", "");
389     if (path.empty()) {
390         return false;
391     }
392     option.SetPath(path);
393     double from = 0.0;
394     double to = 1.0;
395     JSViewAbstract::ParseJsDouble(jsObj->GetProperty("from"), from);
396     JSViewAbstract::ParseJsDouble(jsObj->GetProperty("to"), to);
397     if (GreatNotEqual(from, 1.0) || LessNotEqual(from, 0.0)) {
398         from = 0.0;
399     }
400     if (GreatNotEqual(to, 1.0) || LessNotEqual(to, 0.0)) {
401         to = 1.0;
402     } else if (to < from) {
403         to = from;
404     }
405     option.SetBegin(static_cast<float>(from));
406     option.SetEnd(static_cast<float>(to));
407     option.SetRotate(jsObj->GetPropertyValue<bool>("rotatable", false));
408     return true;
409 }
410 
SetBgImgPosition(const DimensionUnit & typeX,const DimensionUnit & typeY,const double valueX,const double valueY,BackgroundImagePosition & bgImgPosition)411 void SetBgImgPosition(const DimensionUnit& typeX, const DimensionUnit& typeY, const double valueX, const double valueY,
412     BackgroundImagePosition& bgImgPosition)
413 {
414     AnimationOption option = ViewStackModel::GetInstance()->GetImplicitAnimationOption();
415     bgImgPosition.SetSizeX(AnimatableDimension(valueX, typeX, option));
416     bgImgPosition.SetSizeY(AnimatableDimension(valueY, typeY, option));
417 }
418 
GetReplaceContentStr(int pos,const std::string & type,JSRef<JSArray> params,int32_t containCount)419 std::string GetReplaceContentStr(int pos, const std::string& type, JSRef<JSArray> params, int32_t containCount)
420 {
421     JSRef<JSVal> item = params->GetValueAt(pos + containCount);
422     if (type == "d") {
423         if (item->IsNumber()) {
424             return std::to_string(item->ToNumber<uint32_t>());
425         }
426     } else if (type == "s") {
427         if (item->IsString()) {
428             return item->ToString();
429         }
430     } else if (type == "f") {
431         if (item->IsNumber()) {
432             return std::to_string(item->ToNumber<float>());
433         }
434     }
435     return std::string();
436 }
437 
ReplaceHolder(std::string & originStr,JSRef<JSArray> params,int32_t containCount)438 void ReplaceHolder(std::string& originStr, JSRef<JSArray> params, int32_t containCount)
439 {
440     auto size = static_cast<int32_t>(params->Length());
441     if (containCount == size) {
442         return;
443     }
444     std::string::const_iterator start = originStr.begin();
445     std::string::const_iterator end = originStr.end();
446     std::smatch matches;
447     bool shortHolderType = false;
448     bool firstMatch = true;
449     int searchTime = 0;
450     while (std::regex_search(start, end, matches, RESOURCE_APP_STRING_PLACEHOLDER)) {
451         std::string pos = matches[2];
452         std::string type = matches[4];
453         if (firstMatch) {
454             firstMatch = false;
455             shortHolderType = pos.length() == 0;
456         } else {
457             if (shortHolderType ^ (pos.length() == 0)) {
458                 return;
459             }
460         }
461 
462         std::string replaceContentStr;
463         if (shortHolderType) {
464             replaceContentStr = GetReplaceContentStr(searchTime, type, params, containCount);
465         } else {
466             replaceContentStr = GetReplaceContentStr(StringToInt(pos) - 1, type, params, containCount);
467         }
468 
469         originStr.replace(matches[0].first - originStr.begin(), matches[0].length(), replaceContentStr);
470         start = originStr.begin() + matches.prefix().length() + replaceContentStr.length();
471         end = originStr.end();
472         searchTime++;
473     }
474 }
475 
ParseLocationProps(const JSCallbackInfo & info,CalcDimension & x,CalcDimension & y)476 bool ParseLocationProps(const JSCallbackInfo& info, CalcDimension& x, CalcDimension& y)
477 {
478     JSRef<JSVal> arg = info[0];
479     if (!arg->IsObject()) {
480         return false;
481     }
482     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(arg);
483     JSRef<JSVal> xVal = sizeObj->GetProperty("x");
484     JSRef<JSVal> yVal = sizeObj->GetProperty("y");
485     bool hasX = JSViewAbstract::ParseJsDimension(xVal, x, DimensionUnit::VP);
486     bool hasY = JSViewAbstract::ParseJsDimension(yVal, y, DimensionUnit::VP);
487     return hasX || hasY;
488 }
489 
ParseDragStartBuilderFunc(const JSRef<JSVal> & info)490 RefPtr<JsFunction> ParseDragStartBuilderFunc(const JSRef<JSVal>& info)
491 {
492     JSRef<JSVal> builder;
493     if (info->IsObject()) {
494         auto builderObj = JSRef<JSObject>::Cast(info);
495         builder = builderObj->GetProperty("builder");
496     } else if (info->IsFunction()) {
497         builder = info;
498     } else {
499         return nullptr;
500     }
501 
502     if (!builder->IsFunction()) {
503         return nullptr;
504     }
505 
506     return AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
507 }
508 
509 RefPtr<NG::ChainedTransitionEffect> ParseChainedTransition(
510     const JSRef<JSObject>& object, const JSExecutionContext& context);
511 
ParseChainedRotateTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)512 RefPtr<NG::ChainedTransitionEffect> ParseChainedRotateTransition(
513     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
514 {
515     RefPtr<NG::ChainedTransitionEffect> effect;
516     if (effectOption->IsObject()) {
517         NG::RotateOptions rotate(0.0f, 0.0f, 0.0f, 0.0f, 0.5_pct, 0.5_pct);
518         std::optional<float> angle;
519         ParseJsRotate(effectOption, rotate, angle);
520         if (angle.has_value()) {
521             rotate.angle = angle.value();
522             return AceType::MakeRefPtr<NG::ChainedRotateEffect>(rotate);
523         }
524     }
525     return nullptr;
526 }
527 
ParseChainedOpacityTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)528 RefPtr<NG::ChainedTransitionEffect> ParseChainedOpacityTransition(
529     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
530 {
531     double opacity = 1.0;
532     if (JSViewAbstract::ParseJsDouble(effectOption, opacity)) {
533         if ((LessNotEqual(opacity, 0.0)) || opacity > 1.0) {
534             opacity = 1.0;
535         }
536         return AceType::MakeRefPtr<NG::ChainedOpacityEffect>(opacity);
537     }
538     return nullptr;
539 }
540 
ParseChainedTranslateTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)541 RefPtr<NG::ChainedTransitionEffect> ParseChainedTranslateTransition(
542     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
543 {
544     if (effectOption->IsObject()) {
545         // default: x, y, z (0.0, 0.0, 0.0)
546         NG::TranslateOptions translate;
547         ParseJsTranslate(effectOption, translate.x, translate.y, translate.z);
548         return AceType::MakeRefPtr<NG::ChainedTranslateEffect>(translate);
549     }
550     return nullptr;
551 }
552 
ParseChainedScaleTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)553 RefPtr<NG::ChainedTransitionEffect> ParseChainedScaleTransition(
554     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
555 {
556     if (effectOption->IsObject()) {
557         // default: x, y, z (1.0, 1.0, 1.0), centerX, centerY 50% 50%;
558         NG::ScaleOptions scale(1.0f, 1.0f, 1.0f, 0.5_pct, 0.5_pct);
559         ParseJsScale(effectOption, scale.xScale, scale.yScale, scale.zScale, scale.centerX, scale.centerY);
560         return AceType::MakeRefPtr<NG::ChainedScaleEffect>(scale);
561     }
562     return nullptr;
563 }
564 
ParseChainedMoveTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)565 RefPtr<NG::ChainedTransitionEffect> ParseChainedMoveTransition(
566     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
567 {
568     int32_t edge = 0;
569     if (JSViewAbstract::ParseJsInt32(effectOption, edge)) {
570         if (edge < static_cast<int32_t>(NG::TransitionEdge::TOP) ||
571             edge > static_cast<int32_t>(NG::TransitionEdge::END)) {
572             edge = static_cast<int32_t>(NG::TransitionEdge::START);
573         }
574         return AceType::MakeRefPtr<NG::ChainedMoveEffect>(static_cast<NG::TransitionEdge>(edge));
575     }
576     return nullptr;
577 }
578 
ParseChainedAsymmetricTransition(const JSRef<JSVal> & effectOption,const JSExecutionContext & context)579 RefPtr<NG::ChainedTransitionEffect> ParseChainedAsymmetricTransition(
580     const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
581 {
582     if (effectOption->IsObject()) {
583         auto effectObj = JSRef<JSObject>::Cast(effectOption);
584         auto appearJsVal = effectObj->GetProperty("appear");
585         auto disappearJsVal = effectObj->GetProperty("disappear");
586         RefPtr<NG::ChainedTransitionEffect> appearEffect;
587         RefPtr<NG::ChainedTransitionEffect> disappearEffect;
588         if (appearJsVal->IsObject()) {
589             auto appearObj = JSRef<JSObject>::Cast(appearJsVal);
590             appearEffect = ParseChainedTransition(appearObj, context);
591         }
592         if (disappearJsVal->IsObject()) {
593             auto disappearObj = JSRef<JSObject>::Cast(disappearJsVal);
594             disappearEffect = ParseChainedTransition(disappearObj, context);
595         }
596         return AceType::MakeRefPtr<NG::ChainedAsymmetricEffect>(appearEffect, disappearEffect);
597     }
598     return nullptr;
599 }
600 
GetFormAnimationTimeInterval(const RefPtr<PipelineBase> & pipelineContext)601 int64_t GetFormAnimationTimeInterval(const RefPtr<PipelineBase>& pipelineContext)
602 {
603     CHECK_NULL_RETURN(pipelineContext, 0);
604     return (GetMicroTickCount() - pipelineContext->GetFormAnimationStartTime()) / MICROSEC_TO_MILLISEC;
605 }
606 
607 using ChainedTransitionEffectCreator = RefPtr<NG::ChainedTransitionEffect> (*)(
608     const JSRef<JSVal>&, const JSExecutionContext&);
609 
ParseChainedTransition(const JSRef<JSObject> & object,const JSExecutionContext & context)610 RefPtr<NG::ChainedTransitionEffect> ParseChainedTransition(
611     const JSRef<JSObject>& object, const JSExecutionContext& context)
612 {
613     auto propType = object->GetProperty("type_");
614     if (!propType->IsString()) {
615         return nullptr;
616     }
617     std::string type = propType->ToString();
618     auto propEffectOption = object->GetProperty("effect_");
619     auto propAnimationOption = object->GetProperty("animation_");
620     auto propSuccessor = object->GetProperty("successor_");
621     static const LinearMapNode<ChainedTransitionEffectCreator> creatorMap[] = {
622         { "asymmetric", ParseChainedAsymmetricTransition },
623         { "identity",
624             [](const JSRef<JSVal>& effectOption, const JSExecutionContext& context)
625                 -> RefPtr<NG::ChainedTransitionEffect> { return AceType::MakeRefPtr<NG::ChainedIdentityEffect>(); } },
626         { "move", ParseChainedMoveTransition },
627         { "opacity", ParseChainedOpacityTransition },
628         { "rotate", ParseChainedRotateTransition },
629         { "scale", ParseChainedScaleTransition },
630         { "slideSwitch",
631             [](const JSRef<JSVal>& effectOption,
632                 const JSExecutionContext& context) -> RefPtr<NG::ChainedTransitionEffect> {
633                 return AceType::MakeRefPtr<NG::ChainedSlideSwitchEffect>();
634             } },
635         { "translate", ParseChainedTranslateTransition },
636     };
637     int64_t index = BinarySearchFindIndex(creatorMap, ArraySize(creatorMap), type.c_str());
638     if (index < 0) {
639         return nullptr;
640     }
641     RefPtr<NG::ChainedTransitionEffect> result = creatorMap[index].value(propEffectOption, context);
642     if (!result) {
643         return nullptr;
644     }
645     if (propAnimationOption->IsObject()) {
646         auto container = Container::Current();
647         CHECK_NULL_RETURN(container, nullptr);
648         auto pipelineContext = container->GetPipelineContext();
649         CHECK_NULL_RETURN(pipelineContext, nullptr);
650         auto animationOptionResult = std::make_shared<AnimationOption>(
651             JSViewContext::CreateAnimation(propAnimationOption, pipelineContext->IsFormRender()));
652         // The maximum of the form-animation-playback duration value is 1000 ms.
653         if (pipelineContext->IsFormRender() && pipelineContext->IsFormAnimation()) {
654             auto formAnimationTimeInterval = GetFormAnimationTimeInterval(pipelineContext);
655             // If the duration exceeds 1000ms, init it to 0 ms.
656             if (formAnimationTimeInterval > DEFAULT_DURATION) {
657                 animationOptionResult->SetDuration(0);
658             } else if (animationOptionResult->GetDuration() > (DEFAULT_DURATION - formAnimationTimeInterval)) {
659                 // If remaining time is less than 1000ms, check for update duration.
660                 animationOptionResult->SetDuration(DEFAULT_DURATION - formAnimationTimeInterval);
661                 TAG_LOGI(AceLogTag::ACE_FORM, "[Form animation]  Form Transition SetDuration: %{public}lld ms",
662                     static_cast<long long>(DEFAULT_DURATION - formAnimationTimeInterval));
663             }
664         }
665         auto animationOptionObj = JSRef<JSObject>::Cast(propAnimationOption);
666         JSRef<JSVal> onFinish = animationOptionObj->GetProperty("onFinish");
667         WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
668         if (onFinish->IsFunction()) {
669             RefPtr<JsFunction> jsFunc =
670                 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onFinish));
671             std::function<void()> onFinishEvent = [execCtx = context, func = std::move(jsFunc),
672                                                       id = Container::CurrentId(), node = targetNode]() {
673                 ContainerScope scope(id);
674                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
675                 PipelineContext::SetCallBackNode(node);
676                 func->Execute();
677             };
678             animationOptionResult->SetOnFinishEvent(onFinishEvent);
679         }
680         result->SetAnimationOption(animationOptionResult);
681     }
682     if (propSuccessor->IsObject()) {
683         result->SetNext(ParseChainedTransition(JSRef<JSObject>::Cast(propSuccessor), context));
684     }
685     return result;
686 }
687 
688 #ifndef WEARABLE_PRODUCT
689 const std::vector<Placement> PLACEMENT = { Placement::LEFT, Placement::RIGHT, Placement::TOP, Placement::BOTTOM,
690     Placement::TOP_LEFT, Placement::TOP_RIGHT, Placement::BOTTOM_LEFT, Placement::BOTTOM_RIGHT, Placement::LEFT_TOP,
691     Placement::LEFT_BOTTOM, Placement::RIGHT_TOP, Placement::RIGHT_BOTTOM };
692 
ParseDoubleBindCallback(const JSCallbackInfo & info,const JSRef<JSObject> & callbackObj)693 DoubleBindCallback ParseDoubleBindCallback(const JSCallbackInfo& info, const JSRef<JSObject>& callbackObj)
694 {
695     JSRef<JSVal> changeEvent = callbackObj->GetProperty("changeEvent");
696     if (!changeEvent->IsFunction()) {
697         return {};
698     }
699     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEvent));
700     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
701     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
702                         const std::string& param) {
703         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
704         if (param != "true" && param != "false") {
705             return;
706         }
707         PipelineContext::SetCallBackNode(node);
708         bool newValue = StringToBool(param);
709         JSRef<JSVal> newJSVal = JSRef<JSVal>::Make(ToJSValue(newValue));
710         func->ExecuteJS(1, &newJSVal);
711     };
712     return callback;
713 }
714 
SetPopupMessageOptions(const JSRef<JSObject> messageOptionsObj,const RefPtr<PopupParam> & popupParam)715 void SetPopupMessageOptions(const JSRef<JSObject> messageOptionsObj, const RefPtr<PopupParam>& popupParam)
716 {
717     auto colorValue = messageOptionsObj->GetProperty("textColor");
718     Color textColor;
719     if (JSViewAbstract::ParseJsColor(colorValue, textColor)) {
720         if (popupParam) {
721             popupParam->SetTextColor(textColor);
722         }
723     }
724 
725     auto font = messageOptionsObj->GetProperty("font");
726     if (!font->IsNull() && font->IsObject()) {
727         JSRef<JSObject> fontObj = JSRef<JSObject>::Cast(font);
728         auto fontSizeValue = fontObj->GetProperty("size");
729         CalcDimension fontSize;
730         if (JSViewAbstract::ParseJsDimensionFp(fontSizeValue, fontSize)) {
731             if (popupParam) {
732                 popupParam->SetFontSize(fontSize);
733             }
734         }
735         auto fontWeightValue = fontObj->GetProperty("weight");
736         if (fontWeightValue->IsString()) {
737             if (popupParam) {
738                 popupParam->SetFontWeight(ConvertStrToFontWeight(fontWeightValue->ToString()));
739             }
740         }
741         auto fontStyleValue = fontObj->GetProperty("style");
742         if (fontStyleValue->IsNumber()) {
743             int32_t value = fontStyleValue->ToNumber<int32_t>();
744             if (value < 0 || value >= static_cast<int32_t>(FONT_STYLES.size())) {
745                 return;
746             }
747             if (popupParam) {
748                 popupParam->SetFontStyle(FONT_STYLES[value]);
749             }
750         }
751     }
752 }
753 
SetPlacementOnTopVal(const JSRef<JSObject> & popupObj,const RefPtr<PopupParam> & popupParam)754 void SetPlacementOnTopVal(const JSRef<JSObject>& popupObj, const RefPtr<PopupParam>& popupParam)
755 {
756     JSRef<JSVal> placementOnTopVal = popupObj->GetProperty("placementOnTop");
757     if (placementOnTopVal->IsBoolean() && popupParam) {
758         popupParam->SetPlacement(placementOnTopVal->ToBoolean() ? Placement::TOP : Placement::BOTTOM);
759     }
760 }
761 
ParsePopupCommonParam(const JSCallbackInfo & info,const JSRef<JSObject> & popupObj,const RefPtr<PopupParam> & popupParam)762 void ParsePopupCommonParam(
763     const JSCallbackInfo& info, const JSRef<JSObject>& popupObj, const RefPtr<PopupParam>& popupParam)
764 {
765     auto arrowOffset = popupObj->GetProperty("arrowOffset");
766     CalcDimension offset;
767     if (JSViewAbstract::ParseJsDimensionVp(arrowOffset, offset)) {
768         if (popupParam) {
769             popupParam->SetArrowOffset(offset);
770         }
771     }
772 
773     auto arrowPointPosition = popupObj->GetProperty("arrowPointPosition");
774     if (arrowPointPosition->IsString()) {
775         char* pEnd = nullptr;
776         std::strtod(arrowPointPosition->ToString().c_str(), &pEnd);
777         if (pEnd != nullptr) {
778             if (std::strcmp(pEnd, "Start") == 0) {
779                 offset = ARROW_ZERO_PERCENT_VALUE;
780             }
781             if (std::strcmp(pEnd, "Center") == 0) {
782                 offset = ARROW_HALF_PERCENT_VALUE;
783             }
784             if (std::strcmp(pEnd, "End") == 0) {
785                 offset = ARROW_ONE_HUNDRED_PERCENT_VALUE;
786             }
787             if (popupParam) {
788                 popupParam->SetArrowOffset(offset);
789             }
790         }
791     }
792 
793     auto targetSpace = popupObj->GetProperty("targetSpace");
794     if (!targetSpace->IsNull()) {
795         CalcDimension space;
796         if (JSViewAbstract::ParseJsDimensionVp(targetSpace, space)) {
797             if (popupParam) {
798                 popupParam->SetTargetSpace(space);
799             }
800         }
801     }
802 
803     JSRef<JSVal> showInSubWindowValue = popupObj->GetProperty("showInSubWindow");
804     if (showInSubWindowValue->IsBoolean()) {
805         bool showInSubBoolean = showInSubWindowValue->ToBoolean();
806 #if defined(PREVIEW)
807         if (showInSubBoolean) {
808             LOGI("[Engine Log] Unable to use the SubWindow in the Previewer. Use normal type instead.");
809             showInSubBoolean = false;
810         }
811 #endif
812         if (popupParam) {
813             popupParam->SetShowInSubWindow(showInSubBoolean);
814         }
815     }
816 
817     auto placementValue = popupObj->GetProperty("placement");
818     if (placementValue->IsNumber()) {
819         auto placement = placementValue->ToNumber<int32_t>();
820         if (placement >= 0 && placement <= static_cast<int32_t>(PLACEMENT.size())) {
821             popupParam->SetPlacement(PLACEMENT[placement]);
822         }
823     } else {
824         SetPlacementOnTopVal(popupObj, popupParam);
825     }
826 
827     auto enableArrowValue = popupObj->GetProperty("enableArrow");
828     if (enableArrowValue->IsBoolean()) {
829         popupParam->SetEnableArrow(enableArrowValue->ToBoolean());
830     }
831 
832     JSRef<JSVal> maskValue = popupObj->GetProperty("mask");
833     if (maskValue->IsBoolean()) {
834         if (popupParam) {
835             popupParam->SetBlockEvent(maskValue->ToBoolean());
836         }
837     }
838     if (maskValue->IsObject()) {
839         auto maskObj = JSRef<JSObject>::Cast(maskValue);
840         auto colorValue = maskObj->GetProperty("color");
841         Color maskColor;
842         if (JSViewAbstract::ParseJsColor(colorValue, maskColor)) {
843             popupParam->SetMaskColor(maskColor);
844         }
845     }
846 
847     JSRef<JSVal> onStateChangeVal = popupObj->GetProperty("onStateChange");
848     if (onStateChangeVal->IsFunction()) {
849         std::vector<std::string> keys = { "isVisible" };
850         RefPtr<JsFunction> jsFunc =
851             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onStateChangeVal));
852         WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
853         if (popupParam) {
854             auto onStateChangeCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), keys,
855                                              node = targetNode](const std::string& param) {
856                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
857                 ACE_SCORING_EVENT("Popup.onStateChange");
858                 PipelineContext::SetCallBackNode(node);
859                 func->Execute(keys, param);
860             };
861             popupParam->SetOnStateChange(onStateChangeCallback);
862         }
863     }
864 
865     auto offsetVal = popupObj->GetProperty("offset");
866     if (offsetVal->IsObject()) {
867         auto offsetObj = JSRef<JSObject>::Cast(offsetVal);
868         auto xVal = offsetObj->GetProperty("x");
869         auto yVal = offsetObj->GetProperty("y");
870         Offset popupOffset;
871         CalcDimension dx;
872         CalcDimension dy;
873         if (JSViewAbstract::ParseJsDimensionVp(xVal, dx)) {
874             popupOffset.SetX(dx.ConvertToPx());
875         }
876         if (JSViewAbstract::ParseJsDimensionVp(yVal, dy)) {
877             popupOffset.SetY(dy.ConvertToPx());
878         }
879         if (popupParam) {
880             popupParam->SetTargetOffset(popupOffset);
881         }
882     }
883 
884     Color backgroundColor;
885     auto popupColorVal = popupObj->GetProperty("popupColor");
886     if (JSViewAbstract::ParseJsColor(popupColorVal, backgroundColor)) {
887         popupParam->SetBackgroundColor(backgroundColor);
888     }
889 
890     auto autoCancelVal = popupObj->GetProperty("autoCancel");
891     if (autoCancelVal->IsBoolean()) {
892         popupParam->SetHasAction(!autoCancelVal->ToBoolean());
893     }
894 
895     auto childWidthVal = popupObj->GetProperty("width");
896     if (!childWidthVal->IsNull()) {
897         CalcDimension width;
898         if (JSViewAbstract::ParseJsDimensionVp(childWidthVal, width)) {
899             if (width.Value() > 0) {
900                 popupParam->SetChildWidth(width);
901             }
902         }
903     }
904 
905     auto arrowWidthVal = popupObj->GetProperty("arrowWidth");
906     if (!arrowWidthVal->IsNull()) {
907         bool setError = true;
908         CalcDimension arrowWidth;
909         if (JSViewAbstract::ParseJsDimensionVp(arrowWidthVal, arrowWidth)) {
910             if (arrowWidth.Value() > 0 && arrowWidth.Unit() != DimensionUnit::PERCENT) {
911                 popupParam->SetArrowWidth(arrowWidth);
912                 setError = false;
913             }
914         }
915         popupParam->SetErrorArrowWidth(setError);
916     }
917 
918     auto arrowHeightVal = popupObj->GetProperty("arrowHeight");
919     if (!arrowHeightVal->IsNull()) {
920         bool setError = true;
921         CalcDimension arrowHeight;
922         if (JSViewAbstract::ParseJsDimensionVp(arrowHeightVal, arrowHeight)) {
923             if (arrowHeight.Value() > 0 && arrowHeight.Unit() != DimensionUnit::PERCENT) {
924                 popupParam->SetArrowHeight(arrowHeight);
925                 setError = false;
926             }
927         }
928         popupParam->SetErrorArrowHeight(setError);
929     }
930 
931     auto radiusVal = popupObj->GetProperty("radius");
932     if (!radiusVal->IsNull()) {
933         bool setError = true;
934         CalcDimension radius;
935         if (JSViewAbstract::ParseJsDimensionVp(radiusVal, radius)) {
936             if (radius.Value() >= 0) {
937                 popupParam->SetRadius(radius);
938                 setError = false;
939             }
940         }
941         popupParam->SetErrorRadius(setError);
942     }
943 
944     Shadow shadow;
945     auto shadowVal = popupObj->GetProperty("shadow");
946     if (shadowVal->IsObject() || shadowVal->IsNumber()) {
947         auto ret = JSViewAbstract::ParseShadowProps(shadowVal, shadow);
948         if (!ret) {
949             JSViewAbstract::GetShadowFromTheme(ShadowStyle::OuterDefaultMD, shadow);
950         }
951     } else {
952         JSViewAbstract::GetShadowFromTheme(ShadowStyle::OuterDefaultMD, shadow);
953     }
954     popupParam->SetShadow(shadow);
955 
956     auto blurStyleValue = popupObj->GetProperty("backgroundBlurStyle");
957     if (blurStyleValue->IsNumber()) {
958         auto blurStyle = blurStyleValue->ToNumber<int32_t>();
959         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
960             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
961             popupParam->SetBlurStyle(static_cast<BlurStyle>(blurStyle));
962         }
963     }
964 }
965 
ParsePopupParam(const JSCallbackInfo & info,const JSRef<JSObject> & popupObj,const RefPtr<PopupParam> & popupParam)966 void ParsePopupParam(const JSCallbackInfo& info, const JSRef<JSObject>& popupObj, const RefPtr<PopupParam>& popupParam)
967 {
968     ParsePopupCommonParam(info, popupObj, popupParam);
969     JSRef<JSVal> messageVal = popupObj->GetProperty("message");
970     if (popupParam) {
971         popupParam->SetMessage(messageVal->ToString());
972     }
973 
974     auto messageOptions = popupObj->GetProperty("messageOptions");
975     JSRef<JSObject> messageOptionsObj;
976     if (!messageOptions->IsNull() && messageOptions->IsObject()) {
977         messageOptionsObj = JSRef<JSObject>::Cast(messageOptions);
978         SetPopupMessageOptions(messageOptionsObj, popupParam);
979     }
980 
981     JSRef<JSVal> primaryButtonVal = popupObj->GetProperty("primaryButton");
982     if (primaryButtonVal->IsObject()) {
983         ButtonProperties properties;
984         JSRef<JSObject> obj = JSRef<JSObject>::Cast(primaryButtonVal);
985         JSRef<JSVal> value = obj->GetProperty("value");
986         if (value->IsString()) {
987             properties.value = value->ToString();
988         }
989 
990         JSRef<JSVal> actionValue = obj->GetProperty("action");
991         if (actionValue->IsFunction()) {
992             auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(actionValue));
993             WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
994             if (popupParam) {
995                 auto clickCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc),
996                                          node = targetNode](GestureEvent& info) {
997                     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
998                     ACE_SCORING_EVENT("primaryButton.action");
999                     PipelineContext::SetCallBackNode(node);
1000                     func->Execute(info);
1001                 };
1002                 properties.action = AceType::MakeRefPtr<NG::ClickEvent>(clickCallback);
1003             }
1004         }
1005         properties.showButton = true;
1006         if (popupParam) {
1007             popupParam->SetPrimaryButtonProperties(properties);
1008         }
1009     }
1010 
1011     JSRef<JSVal> secondaryButtonVal = popupObj->GetProperty("secondaryButton");
1012     if (secondaryButtonVal->IsObject()) {
1013         ButtonProperties properties;
1014         JSRef<JSObject> obj = JSRef<JSObject>::Cast(secondaryButtonVal);
1015         JSRef<JSVal> value = obj->GetProperty("value");
1016         if (value->IsString()) {
1017             properties.value = value->ToString();
1018         }
1019 
1020         JSRef<JSVal> actionValue = obj->GetProperty("action");
1021         if (actionValue->IsFunction()) {
1022             auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(actionValue));
1023             WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
1024             if (popupParam) {
1025                 auto clickCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc),
1026                                          node = targetNode](GestureEvent& info) {
1027                     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1028                     ACE_SCORING_EVENT("secondaryButton.action");
1029                     PipelineContext::SetCallBackNode(node);
1030                     func->Execute(info);
1031                 };
1032                 properties.action = AceType::MakeRefPtr<NG::ClickEvent>(clickCallback);
1033             }
1034         }
1035         properties.showButton = true;
1036         if (popupParam) {
1037             popupParam->SetSecondaryButtonProperties(properties);
1038         }
1039     }
1040 }
1041 
ParseCustomPopupParam(const JSCallbackInfo & info,const JSRef<JSObject> & popupObj,const RefPtr<PopupParam> & popupParam)1042 void ParseCustomPopupParam(
1043     const JSCallbackInfo& info, const JSRef<JSObject>& popupObj, const RefPtr<PopupParam>& popupParam)
1044 {
1045     auto builderValue = popupObj->GetProperty("builder");
1046     if (!builderValue->IsObject()) {
1047         return;
1048     }
1049     if (!builderValue->IsFunction()) {
1050         JSRef<JSObject> builderObj;
1051         builderObj = JSRef<JSObject>::Cast(builderValue);
1052         auto builder = builderObj->GetProperty("builder");
1053         if (!builder->IsFunction()) {
1054             return;
1055         }
1056         auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
1057         if (!builderFunc) {
1058             return;
1059         }
1060     }
1061     if (popupParam) {
1062         popupParam->SetUseCustomComponent(true);
1063     }
1064 
1065     auto focusableValue = popupObj->GetProperty("focusable");
1066     if (focusableValue->IsBoolean()) {
1067         popupParam->SetFocusable(focusableValue->ToBoolean());
1068     }
1069 
1070     ParsePopupCommonParam(info, popupObj, popupParam);
1071 }
1072 #endif
1073 
1074 } // namespace
1075 
GetResourceObject(const JSRef<JSObject> & jsObj)1076 RefPtr<ResourceObject> GetResourceObject(const JSRef<JSObject>& jsObj)
1077 {
1078     auto id = jsObj->GetProperty("id")->ToNumber<uint32_t>();
1079     auto type = jsObj->GetProperty("type")->ToNumber<uint32_t>();
1080     auto args = jsObj->GetProperty("params");
1081 
1082     std::string bundleName;
1083     std::string moduleName;
1084     auto bundle = jsObj->GetProperty("bundleName");
1085     auto module = jsObj->GetProperty("moduleName");
1086     if (bundle->IsString() && module->IsString()) {
1087         bundleName = bundle->ToString();
1088         moduleName = module->ToString();
1089     }
1090 
1091     JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
1092     std::vector<ResourceObjectParams> resObjParamsList;
1093     auto size = static_cast<int32_t>(params->Length());
1094     for (int32_t i = 0; i < size; i++) {
1095         auto item = params->GetValueAt(i);
1096         ResourceObjectParams resObjParams { .value = item->ToString().c_str() };
1097         if (item->IsString()) {
1098             resObjParams.type = ResourceObjectParamType::STRING;
1099         } else if (item->IsNumber()) {
1100             if (std::regex_match(item->ToString(), FLOAT_PATTERN)) {
1101                 resObjParams.type = ResourceObjectParamType::FLOAT;
1102             } else {
1103                 resObjParams.type = ResourceObjectParamType::INT;
1104             }
1105         }
1106         resObjParamsList.push_back(resObjParams);
1107     }
1108     auto resourceObject = AceType::MakeRefPtr<ResourceObject>(id, type, resObjParamsList, bundleName, moduleName);
1109     return resourceObject;
1110 }
1111 
GetResourceObjectByBundleAndModule(const JSRef<JSObject> & jsObj)1112 RefPtr<ResourceObject> GetResourceObjectByBundleAndModule(const JSRef<JSObject>& jsObj)
1113 {
1114     auto bundleName = jsObj->GetPropertyValue<std::string>("bundleName", "");
1115     auto moduleName = jsObj->GetPropertyValue<std::string>("moduleName", "");
1116     auto resourceObject = AceType::MakeRefPtr<ResourceObject>(bundleName, moduleName);
1117     return resourceObject;
1118 }
1119 
CreateResourceWrapper(const JSRef<JSObject> & jsObj,RefPtr<ResourceObject> & resourceObject)1120 RefPtr<ResourceWrapper> CreateResourceWrapper(const JSRef<JSObject>& jsObj, RefPtr<ResourceObject>& resourceObject)
1121 {
1122     RefPtr<ResourceAdapter> resourceAdapter = nullptr;
1123     RefPtr<ThemeConstants> themeConstants = nullptr;
1124     if (SystemProperties::GetResourceDecoupling()) {
1125         resourceAdapter = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resourceObject);
1126         if (!resourceAdapter) {
1127             return nullptr;
1128         }
1129     } else {
1130         themeConstants = JSViewAbstract::GetThemeConstants(jsObj);
1131         if (!themeConstants) {
1132             return nullptr;
1133         }
1134     }
1135     auto resourceWrapper = AceType::MakeRefPtr<ResourceWrapper>(themeConstants, resourceAdapter);
1136     return resourceWrapper;
1137 }
1138 
CreateResourceWrapper()1139 RefPtr<ResourceWrapper> CreateResourceWrapper()
1140 {
1141     RefPtr<ResourceAdapter> resourceAdapter = nullptr;
1142     RefPtr<ThemeConstants> themeConstants = nullptr;
1143     if (SystemProperties::GetResourceDecoupling()) {
1144         resourceAdapter = ResourceManager::GetInstance().GetResourceAdapter();
1145         if (!resourceAdapter) {
1146             return nullptr;
1147         }
1148     } else {
1149         themeConstants = JSViewAbstract::GetThemeConstants();
1150         if (!themeConstants) {
1151             return nullptr;
1152         }
1153     }
1154     auto resourceWrapper = AceType::MakeRefPtr<ResourceWrapper>(themeConstants, resourceAdapter);
1155     return resourceWrapper;
1156 }
1157 
ColorAlphaAdapt(uint32_t origin)1158 uint32_t ColorAlphaAdapt(uint32_t origin)
1159 {
1160     uint32_t result = origin;
1161     if (origin >> COLOR_ALPHA_OFFSET == 0) {
1162         result = origin | COLOR_ALPHA_VALUE;
1163     }
1164     return result;
1165 }
1166 
JsScale(const JSCallbackInfo & info)1167 void JSViewAbstract::JsScale(const JSCallbackInfo& info)
1168 {
1169     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
1170     if (!CheckJSCallbackInfo("JsScale", info, checkList)) {
1171         SetDefaultScale();
1172         return;
1173     }
1174 
1175     if (info[0]->IsObject()) {
1176         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
1177         if (jsObj->HasProperty("x") || jsObj->HasProperty("y") || jsObj->HasProperty("z")) {
1178             // default: x, y, z (1.0, 1.0, 1.0)
1179             auto scaleX = 1.0f;
1180             auto scaleY = 1.0f;
1181             auto scaleZ = 1.0f;
1182             // default centerX, centerY 50% 50%;
1183             CalcDimension centerX = 0.5_pct;
1184             CalcDimension centerY = 0.5_pct;
1185             ParseJsScale(info[0], scaleX, scaleY, scaleZ, centerX, centerY);
1186             ViewAbstractModel::GetInstance()->SetScale(scaleX, scaleY, scaleZ);
1187             ViewAbstractModel::GetInstance()->SetPivot(centerX, centerY, 0.0_vp);
1188             return;
1189         } else {
1190             SetDefaultScale();
1191         }
1192     }
1193     double scale = 0.0;
1194     if (ParseJsDouble(info[0], scale)) {
1195         ViewAbstractModel::GetInstance()->SetScale(scale, scale, 1.0f);
1196     }
1197 }
1198 
SetDefaultScale()1199 void JSViewAbstract::SetDefaultScale()
1200 {
1201     ViewAbstractModel::GetInstance()->SetScale(1.0f, 1.0f, 1.0f);
1202     ViewAbstractModel::GetInstance()->SetPivot(0.5_pct, 0.5_pct, 0.0_vp);
1203 }
1204 
JsScaleX(const JSCallbackInfo & info)1205 void JSViewAbstract::JsScaleX(const JSCallbackInfo& info)
1206 {
1207     double scaleVal = 0.0;
1208     if (!ParseJsDouble(info[0], scaleVal)) {
1209         return;
1210     }
1211     ViewAbstractModel::GetInstance()->SetScale(scaleVal, 1.0f, 1.0f);
1212 }
1213 
JsScaleY(const JSCallbackInfo & info)1214 void JSViewAbstract::JsScaleY(const JSCallbackInfo& info)
1215 {
1216     double scaleVal = 0.0;
1217     if (!ParseJsDouble(info[0], scaleVal)) {
1218         return;
1219     }
1220     ViewAbstractModel::GetInstance()->SetScale(1.0f, scaleVal, 1.0f);
1221 }
1222 
JsOpacity(const JSCallbackInfo & info)1223 void JSViewAbstract::JsOpacity(const JSCallbackInfo& info)
1224 {
1225     double opacity = 0.0;
1226     if (!ParseJsDouble(info[0], opacity)) {
1227         ViewAbstractModel::GetInstance()->SetOpacity(1.0f);
1228         return;
1229     }
1230     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1231         opacity = std::clamp(opacity, 0.0, 1.0);
1232     } else {
1233         if (opacity > 1.0 || LessNotEqual(opacity, 0.0)) {
1234             opacity = 1.0;
1235         }
1236     }
1237     ViewAbstractModel::GetInstance()->SetOpacity(opacity);
1238 }
1239 
JsTranslate(const JSCallbackInfo & info)1240 void JSViewAbstract::JsTranslate(const JSCallbackInfo& info)
1241 {
1242     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
1243         JSCallbackInfoType::OBJECT };
1244     if (!CheckJSCallbackInfo("JsTranslate", info, checkList)) {
1245         SetDefaultTranslate();
1246         return;
1247     }
1248 
1249     if (info[0]->IsObject()) {
1250         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
1251         if (jsObj->HasProperty("x") || jsObj->HasProperty("y") || jsObj->HasProperty("z")) {
1252             // default: x, y, z (0.0, 0.0, 0.0)
1253             auto translateX = CalcDimension(0.0);
1254             auto translateY = CalcDimension(0.0);
1255             auto translateZ = CalcDimension(0.0);
1256             ParseJsTranslate(info[0], translateX, translateY, translateZ);
1257             ViewAbstractModel::GetInstance()->SetTranslate(translateX, translateY, translateZ);
1258             return;
1259         } else {
1260             SetDefaultTranslate();
1261         }
1262     }
1263     CalcDimension value;
1264     if (ParseJsDimensionVp(info[0], value)) {
1265         ViewAbstractModel::GetInstance()->SetTranslate(value, value, value);
1266     }
1267 }
1268 
SetDefaultTranslate()1269 void JSViewAbstract::SetDefaultTranslate()
1270 {
1271     ViewAbstractModel::GetInstance()->SetTranslate(CalcDimension(0.0), CalcDimension(0.0), CalcDimension(0.0));
1272 }
1273 
JsTranslateX(const JSCallbackInfo & info)1274 void JSViewAbstract::JsTranslateX(const JSCallbackInfo& info)
1275 {
1276     CalcDimension value;
1277     if (!ParseJsDimensionVp(info[0], value)) {
1278         return;
1279     }
1280     ViewAbstractModel::GetInstance()->SetTranslate(value, 0.0_px, 0.0_px);
1281 }
1282 
JsTranslateY(const JSCallbackInfo & info)1283 void JSViewAbstract::JsTranslateY(const JSCallbackInfo& info)
1284 {
1285     CalcDimension value;
1286     if (!ParseJsDimensionVp(info[0], value)) {
1287         return;
1288     }
1289     ViewAbstractModel::GetInstance()->SetTranslate(0.0_px, value, 0.0_px);
1290 }
1291 
JsRotate(const JSCallbackInfo & info)1292 void JSViewAbstract::JsRotate(const JSCallbackInfo& info)
1293 {
1294     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
1295     if (!CheckJSCallbackInfo("JsRotate", info, checkList)) {
1296         SetDefaultRotate();
1297         return;
1298     }
1299 
1300     if (info[0]->IsObject()) {
1301         NG::RotateOptions rotate(0.0f, 0.0f, 0.0f, 0.0f, 0.5_pct, 0.5_pct);
1302         std::optional<float> angle;
1303         ParseJsRotate(info[0], rotate, angle);
1304         if (angle) {
1305             ViewAbstractModel::GetInstance()->SetRotate(
1306                 rotate.xDirection, rotate.yDirection, rotate.zDirection, angle.value(), rotate.perspective);
1307             ViewAbstractModel::GetInstance()->SetPivot(rotate.centerX, rotate.centerY, rotate.centerZ);
1308         } else {
1309             SetDefaultRotate();
1310         }
1311         return;
1312     }
1313     double rotateZ;
1314     if (ParseJsDouble(info[0], rotateZ)) {
1315         ViewAbstractModel::GetInstance()->SetRotate(0.0f, 0.0f, 1.0f, rotateZ);
1316     }
1317 }
1318 
SetDefaultRotate()1319 void JSViewAbstract::SetDefaultRotate()
1320 {
1321     NG::RotateOptions rotate(0.0f, 0.0f, 0.0f, 0.0f, 0.5_pct, 0.5_pct, 0.0f, 0.0f);
1322     ViewAbstractModel::GetInstance()->SetRotate(
1323         rotate.xDirection, rotate.yDirection, rotate.zDirection, 0.0f, rotate.perspective);
1324     ViewAbstractModel::GetInstance()->SetPivot(rotate.centerX, rotate.centerY, rotate.centerZ);
1325 }
1326 
JsRotateX(const JSCallbackInfo & info)1327 void JSViewAbstract::JsRotateX(const JSCallbackInfo& info)
1328 {
1329     double rotateVal = 0.0;
1330     if (!ParseJsDouble(info[0], rotateVal)) {
1331         return;
1332     }
1333     ViewAbstractModel::GetInstance()->SetRotate(1.0f, 0.0f, 0.0f, rotateVal);
1334 }
1335 
JsRotateY(const JSCallbackInfo & info)1336 void JSViewAbstract::JsRotateY(const JSCallbackInfo& info)
1337 {
1338     double rotateVal = 0.0;
1339     if (!ParseJsDouble(info[0], rotateVal)) {
1340         return;
1341     }
1342     ViewAbstractModel::GetInstance()->SetRotate(0.0f, 1.0f, 0.0f, rotateVal);
1343 }
1344 
JsTransform(const JSCallbackInfo & info)1345 void JSViewAbstract::JsTransform(const JSCallbackInfo& info)
1346 {
1347     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
1348     if (!CheckJSCallbackInfo("JsTransform", info, checkList)) {
1349         SetDefaultTransform();
1350         return;
1351     }
1352     JSRef<JSVal> array = JSRef<JSObject>::Cast(info[0])->GetProperty("matrix4x4");
1353     const auto matrix4Len = Matrix4::DIMENSION * Matrix4::DIMENSION;
1354     if (!array->IsArray() || JSRef<JSArray>::Cast(array)->Length() != matrix4Len) {
1355         return;
1356     }
1357     JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(array);
1358     std::vector<float> matrix(matrix4Len);
1359     for (int32_t i = 0; i < matrix4Len; i++) {
1360         double value = 0.0;
1361         ParseJsDouble(jsArray->GetValueAt(i), value);
1362         matrix[i] = static_cast<float>(value);
1363     }
1364     ViewAbstractModel::GetInstance()->SetTransformMatrix(matrix);
1365 }
1366 
SetDefaultTransform()1367 void JSViewAbstract::SetDefaultTransform()
1368 {
1369     const auto matrix4Len = Matrix4::DIMENSION * Matrix4::DIMENSION;
1370     std::vector<float> matrix(matrix4Len);
1371     const int32_t initPosition = 5;
1372     for (int32_t i = 0; i < matrix4Len; i = i + initPosition) {
1373         double value = 1.0;
1374         matrix[i] = static_cast<float>(value);
1375     }
1376     ViewAbstractModel::GetInstance()->SetTransformMatrix(matrix);
1377 }
1378 
ParseTransition(std::unique_ptr<JsonValue> & transitionArgs)1379 NG::TransitionOptions JSViewAbstract::ParseTransition(std::unique_ptr<JsonValue>& transitionArgs)
1380 {
1381     bool hasEffect = false;
1382     NG::TransitionOptions transitionOption;
1383     transitionOption.Type = ParseTransitionType(transitionArgs->GetString("type", "All"));
1384     if (transitionArgs->Contains("opacity")) {
1385         double opacity = 1.0;
1386         ParseJsonDouble(transitionArgs->GetValue("opacity"), opacity);
1387         if (opacity > 1.0 || LessNotEqual(opacity, 0.0)) {
1388             opacity = 1.0;
1389         }
1390         transitionOption.UpdateOpacity(static_cast<float>(opacity));
1391         hasEffect = true;
1392     }
1393     if (transitionArgs->Contains("translate")) {
1394         auto translateArgs = transitionArgs->GetObject("translate");
1395         // default: x, y, z (0.0, 0.0, 0.0)
1396         NG::TranslateOptions translate;
1397         ParseJsonTranslate(translateArgs, translate.x, translate.y, translate.z);
1398         transitionOption.UpdateTranslate(translate);
1399         hasEffect = true;
1400     }
1401     if (transitionArgs->Contains("scale")) {
1402         auto scaleArgs = transitionArgs->GetObject("scale");
1403         // default: x, y, z (1.0, 1.0, 1.0), centerX, centerY 50% 50%;
1404         NG::ScaleOptions scale(1.0f, 1.0f, 1.0f, 0.5_pct, 0.5_pct);
1405         ParseJsonScale(scaleArgs, scale.xScale, scale.yScale, scale.zScale, scale.centerX, scale.centerY);
1406         transitionOption.UpdateScale(scale);
1407         hasEffect = true;
1408     }
1409     if (transitionArgs->Contains("rotate")) {
1410         auto rotateArgs = transitionArgs->GetObject("rotate");
1411         // default: dx, dy, dz (0.0, 0.0, 0.0), angle 0, centerX, centerY 50% 50%;
1412         NG::RotateOptions rotate(0.0f, 0.0f, 0.0f, 0.0f, 0.5_pct, 0.5_pct);
1413         std::optional<float> angle;
1414         ParseJsonRotate(rotateArgs, rotate, angle);
1415         if (angle.has_value()) {
1416             rotate.angle = angle.value();
1417             transitionOption.UpdateRotate(rotate);
1418             hasEffect = true;
1419         }
1420     }
1421     if (!hasEffect) {
1422         // default transition
1423         transitionOption = NG::TransitionOptions::GetDefaultTransition(transitionOption.Type);
1424     }
1425     return transitionOption;
1426 }
1427 
ParseJsTransition(const JSRef<JSVal> & transitionArgs)1428 NG::TransitionOptions JSViewAbstract::ParseJsTransition(const JSRef<JSVal>& transitionArgs)
1429 {
1430     NG::TransitionOptions transitionOption;
1431     if (!transitionArgs->IsObject()) {
1432         return transitionOption;
1433     }
1434 
1435     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(transitionArgs);
1436     bool hasEffect = false;
1437     transitionOption.Type = ParseTransitionType(jsObj->GetPropertyValue<std::string>("type", "All"));
1438     if (jsObj->HasProperty("opacity")) {
1439         double opacity = 1.0;
1440         ParseJsDouble(jsObj->GetProperty("opacity"), opacity);
1441         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1442             if (opacity > 1.0 || LessNotEqual(opacity, 0.0)) {
1443                 opacity = 1.0;
1444             }
1445         } else {
1446             opacity = std::clamp(opacity, 0.0, 1.0);
1447         }
1448         transitionOption.UpdateOpacity(static_cast<float>(opacity));
1449         hasEffect = true;
1450     }
1451     if (jsObj->HasProperty("translate")) {
1452         // default: x, y, z (0.0, 0.0, 0.0)
1453         NG::TranslateOptions translate;
1454         ParseJsTranslate(jsObj->GetProperty("translate"), translate.x, translate.y, translate.z);
1455         transitionOption.UpdateTranslate(translate);
1456         hasEffect = true;
1457     }
1458     if (jsObj->HasProperty("scale")) {
1459         // default: x, y, z (1.0, 1.0, 1.0), centerX, centerY 50% 50%;
1460         NG::ScaleOptions scale(1.0f, 1.0f, 1.0f, 0.5_pct, 0.5_pct);
1461         ParseJsScale(jsObj->GetProperty("scale"), scale.xScale, scale.yScale, scale.zScale,
1462             scale.centerX, scale.centerY);
1463         transitionOption.UpdateScale(scale);
1464         hasEffect = true;
1465     }
1466     if (jsObj->HasProperty("rotate")) {
1467         // default: dx, dy, dz (0.0, 0.0, 0.0), angle 0, centerX, centerY 50% 50%;
1468         NG::RotateOptions rotate(0.0f, 0.0f, 0.0f, 0.0f, 0.5_pct, 0.5_pct);
1469         std::optional<float> angle;
1470         ParseJsRotate(jsObj->GetProperty("rotate"), rotate, angle);
1471         if (angle.has_value()) {
1472             rotate.angle = angle.value();
1473             transitionOption.UpdateRotate(rotate);
1474             hasEffect = true;
1475         }
1476     }
1477     if (!hasEffect) {
1478         // default transition
1479         transitionOption = NG::TransitionOptions::GetDefaultTransition(transitionOption.Type);
1480     }
1481     return transitionOption;
1482 }
1483 
JsTransition(const JSCallbackInfo & info)1484 void JSViewAbstract::JsTransition(const JSCallbackInfo& info)
1485 {
1486     if (info.Length() > 1) {
1487         return;
1488     }
1489     if (info.Length() == 0) {
1490         ViewAbstractModel::GetInstance()->SetTransition(
1491             NG::TransitionOptions::GetDefaultTransition(TransitionType::ALL));
1492         return;
1493     }
1494     if (!info[0]->IsObject()) {
1495         return;
1496     }
1497     auto obj = JSRef<JSObject>::Cast(info[0]);
1498     if (!obj->GetProperty("successor_")->IsUndefined()) {
1499         auto chainedEffect = ParseChainedTransition(obj, info.GetExecutionContext());
1500         ViewAbstractModel::GetInstance()->SetChainedTransition(chainedEffect);
1501         return;
1502     }
1503     auto options = ParseJsTransition(info[0]);
1504     ViewAbstractModel::GetInstance()->SetTransition(options);
1505 }
1506 
JsWidth(const JSCallbackInfo & info)1507 void JSViewAbstract::JsWidth(const JSCallbackInfo& info)
1508 {
1509     JsWidth(info[0]);
1510 }
1511 
JsWidth(const JSRef<JSVal> & jsValue)1512 bool JSViewAbstract::JsWidth(const JSRef<JSVal>& jsValue)
1513 {
1514     CalcDimension value;
1515     if (jsValue->IsUndefined()) {
1516         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(true);
1517         return true;
1518     }
1519     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
1520         if (!ParseJsDimensionVpNG(jsValue, value)) {
1521             ViewAbstractModel::GetInstance()->ClearWidthOrHeight(true);
1522             return false;
1523         }
1524     } else if (!ParseJsDimensionVp(jsValue, value)) {
1525         return false;
1526     }
1527 
1528     if (LessNotEqual(value.Value(), 0.0)) {
1529         value.SetValue(0.0);
1530     }
1531 
1532     ViewAbstractModel::GetInstance()->SetWidth(value);
1533     return true;
1534 }
1535 
JsHeight(const JSCallbackInfo & info)1536 void JSViewAbstract::JsHeight(const JSCallbackInfo& info)
1537 {
1538     JsHeight(info[0]);
1539 }
1540 
JsHeight(const JSRef<JSVal> & jsValue)1541 bool JSViewAbstract::JsHeight(const JSRef<JSVal>& jsValue)
1542 {
1543     CalcDimension value;
1544     if (jsValue->IsUndefined()) {
1545         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(false);
1546         return true;
1547     }
1548     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
1549         if (!ParseJsDimensionVpNG(jsValue, value)) {
1550             ViewAbstractModel::GetInstance()->ClearWidthOrHeight(false);
1551             return false;
1552         }
1553     } else if (!ParseJsDimensionVp(jsValue, value)) {
1554         return false;
1555     }
1556 
1557     if (LessNotEqual(value.Value(), 0.0)) {
1558         value.SetValue(0.0);
1559     }
1560 
1561     ViewAbstractModel::GetInstance()->SetHeight(value);
1562     return true;
1563 }
1564 
JsResponseRegion(const JSCallbackInfo & info)1565 void JSViewAbstract::JsResponseRegion(const JSCallbackInfo& info)
1566 {
1567     std::vector<DimensionRect> result;
1568     if (!JSViewAbstract::ParseJsResponseRegionArray(info[0], result)) {
1569         ViewAbstractModel::GetInstance()->SetResponseRegion({});
1570         return;
1571     }
1572 
1573     ViewAbstractModel::GetInstance()->SetResponseRegion(result);
1574 }
1575 
JsMouseResponseRegion(const JSCallbackInfo & info)1576 void JSViewAbstract::JsMouseResponseRegion(const JSCallbackInfo& info)
1577 {
1578     std::vector<DimensionRect> result;
1579     if (!JSViewAbstract::ParseJsResponseRegionArray(info[0], result)) {
1580         ViewAbstractModel::GetInstance()->SetMouseResponseRegion({});
1581         return;
1582     }
1583     ViewAbstractModel::GetInstance()->SetMouseResponseRegion(result);
1584 }
1585 
ParseJsDimensionRect(const JSRef<JSVal> & jsValue,DimensionRect & result)1586 bool JSViewAbstract::ParseJsDimensionRect(const JSRef<JSVal>& jsValue, DimensionRect& result)
1587 {
1588     if (!jsValue->IsObject()) {
1589         return false;
1590     }
1591 
1592     JSRef<JSObject> obj = JSRef<JSObject>::Cast(jsValue);
1593     JSRef<JSVal> x = obj->GetProperty("x");
1594     JSRef<JSVal> y = obj->GetProperty("y");
1595     JSRef<JSVal> width = obj->GetProperty("width");
1596     JSRef<JSVal> height = obj->GetProperty("height");
1597     CalcDimension xDimen = result.GetOffset().GetX();
1598     CalcDimension yDimen = result.GetOffset().GetY();
1599     CalcDimension widthDimen = result.GetWidth();
1600     CalcDimension heightDimen = result.GetHeight();
1601     auto s1 = width->ToString();
1602     auto s2 = height->ToString();
1603     if (s1.find('-') != std::string::npos) {
1604         width = JSRef<JSVal>::Make(ToJSValue("100%"));
1605     }
1606     if (s2.find('-') != std::string::npos) {
1607         height = JSRef<JSVal>::Make(ToJSValue("100%"));
1608     }
1609     if (ParseJsDimensionNG(x, xDimen, DimensionUnit::VP)) {
1610         auto offset = result.GetOffset();
1611         offset.SetX(xDimen);
1612         result.SetOffset(offset);
1613     }
1614     if (ParseJsDimensionNG(y, yDimen, DimensionUnit::VP)) {
1615         auto offset = result.GetOffset();
1616         offset.SetY(yDimen);
1617         result.SetOffset(offset);
1618     }
1619     if (ParseJsDimensionNG(width, widthDimen, DimensionUnit::VP)) {
1620         if (widthDimen.Unit() == DimensionUnit::PERCENT && widthDimen.Value() < 0) {
1621             return true;
1622         }
1623         result.SetWidth(widthDimen);
1624     }
1625     if (ParseJsDimensionNG(height, heightDimen, DimensionUnit::VP)) {
1626         if (heightDimen.Unit() == DimensionUnit::PERCENT && heightDimen.Value() < 0) {
1627             return true;
1628         }
1629         result.SetHeight(heightDimen);
1630     }
1631     return true;
1632 }
1633 
ParseJsResponseRegionArray(const JSRef<JSVal> & jsValue,std::vector<DimensionRect> & result)1634 bool JSViewAbstract::ParseJsResponseRegionArray(const JSRef<JSVal>& jsValue, std::vector<DimensionRect>& result)
1635 {
1636     if (!jsValue->IsArray() && !jsValue->IsObject()) {
1637         return false;
1638     }
1639 
1640     if (jsValue->IsArray()) {
1641         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
1642         for (size_t i = 0; i < array->Length(); i++) {
1643             CalcDimension xDimen = CalcDimension(0.0, DimensionUnit::VP);
1644             CalcDimension yDimen = CalcDimension(0.0, DimensionUnit::VP);
1645             CalcDimension widthDimen = CalcDimension(1, DimensionUnit::PERCENT);
1646             CalcDimension heightDimen = CalcDimension(1, DimensionUnit::PERCENT);
1647             DimensionOffset offsetDimen(xDimen, yDimen);
1648             DimensionRect dimenRect(widthDimen, heightDimen, offsetDimen);
1649             if (ParseJsDimensionRect(array->GetValueAt(i), dimenRect)) {
1650                 result.emplace_back(dimenRect);
1651             } else {
1652                 return false;
1653             }
1654         }
1655         return true;
1656     }
1657 
1658     CalcDimension xDimen = CalcDimension(0.0, DimensionUnit::VP);
1659     CalcDimension yDimen = CalcDimension(0.0, DimensionUnit::VP);
1660     CalcDimension widthDimen = CalcDimension(1, DimensionUnit::PERCENT);
1661     CalcDimension heightDimen = CalcDimension(1, DimensionUnit::PERCENT);
1662     DimensionOffset offsetDimen(xDimen, yDimen);
1663     DimensionRect dimenRect(widthDimen, heightDimen, offsetDimen);
1664     if (ParseJsDimensionRect(jsValue, dimenRect)) {
1665         result.emplace_back(dimenRect);
1666         return true;
1667     } else {
1668         return false;
1669     }
1670 }
1671 
JsSize(const JSCallbackInfo & info)1672 void JSViewAbstract::JsSize(const JSCallbackInfo& info)
1673 {
1674     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
1675     if (!CheckJSCallbackInfo("JsSize", info, checkList)) {
1676         return;
1677     }
1678 
1679     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
1680     JsWidth(sizeObj->GetProperty("width"));
1681     JsHeight(sizeObj->GetProperty("height"));
1682 }
1683 
JsConstraintSize(const JSCallbackInfo & info)1684 void JSViewAbstract::JsConstraintSize(const JSCallbackInfo& info)
1685 {
1686     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
1687     if (!CheckJSCallbackInfo("JsConstraintSize", info, checkList)) {
1688         ViewAbstractModel::GetInstance()->ResetMaxSize(true);
1689         ViewAbstractModel::GetInstance()->ResetMinSize(true);
1690         ViewAbstractModel::GetInstance()->ResetMaxSize(false);
1691         ViewAbstractModel::GetInstance()->ResetMinSize(false);
1692         return;
1693     }
1694 
1695     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
1696 
1697     JSRef<JSVal> minWidthValue = sizeObj->GetProperty("minWidth");
1698     CalcDimension minWidth;
1699     JSRef<JSVal> maxWidthValue = sizeObj->GetProperty("maxWidth");
1700     CalcDimension maxWidth;
1701     JSRef<JSVal> minHeightValue = sizeObj->GetProperty("minHeight");
1702     CalcDimension minHeight;
1703     JSRef<JSVal> maxHeightValue = sizeObj->GetProperty("maxHeight");
1704     CalcDimension maxHeight;
1705     bool version10OrLarger = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN);
1706     if (ParseJsDimensionVp(minWidthValue, minWidth)) {
1707         ViewAbstractModel::GetInstance()->SetMinWidth(minWidth);
1708     } else if (version10OrLarger) {
1709         ViewAbstractModel::GetInstance()->ResetMinSize(true);
1710     }
1711 
1712     if (ParseJsDimensionVp(maxWidthValue, maxWidth)) {
1713         ViewAbstractModel::GetInstance()->SetMaxWidth(maxWidth);
1714     } else if (version10OrLarger) {
1715         ViewAbstractModel::GetInstance()->ResetMaxSize(true);
1716     }
1717 
1718     if (ParseJsDimensionVp(minHeightValue, minHeight)) {
1719         ViewAbstractModel::GetInstance()->SetMinHeight(minHeight);
1720     } else if (version10OrLarger) {
1721         ViewAbstractModel::GetInstance()->ResetMinSize(false);
1722     }
1723 
1724     if (ParseJsDimensionVp(maxHeightValue, maxHeight)) {
1725         ViewAbstractModel::GetInstance()->SetMaxHeight(maxHeight);
1726     } else if (version10OrLarger) {
1727         ViewAbstractModel::GetInstance()->ResetMaxSize(false);
1728     }
1729 }
1730 
JsLayoutPriority(const JSCallbackInfo & info)1731 void JSViewAbstract::JsLayoutPriority(const JSCallbackInfo& info)
1732 {
1733     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER };
1734     if (!CheckJSCallbackInfo("JsLayoutPriority", info, checkList)) {
1735         return;
1736     }
1737 
1738     int32_t priority;
1739     if (info[0]->IsNumber()) {
1740         priority = info[0]->ToNumber<int32_t>();
1741     } else {
1742         priority = static_cast<int32_t>(StringUtils::StringToUint(info[0]->ToString()));
1743     }
1744     ViewAbstractModel::GetInstance()->SetLayoutPriority(priority);
1745 }
1746 
JsPixelRound(const JSCallbackInfo & info)1747 void JSViewAbstract::JsPixelRound(const JSCallbackInfo& info)
1748 {
1749     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
1750     if (!CheckJSCallbackInfo("JsPixelRound", info, checkList)) {
1751         return;
1752     }
1753     uint8_t value = 0;
1754     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
1755     JSRef<JSVal> jsStartValue = object->GetProperty("start");
1756     if (jsStartValue->IsNumber()) {
1757         int32_t startValue = jsStartValue->ToNumber<int32_t>();
1758         if (PixelRoundCalcPolicy::FORCE_CEIL == static_cast<PixelRoundCalcPolicy>(startValue)) {
1759             value |= static_cast<uint8_t>(PixelRoundPolicy::FORCE_CEIL_START);
1760         } else if (PixelRoundCalcPolicy::FORCE_FLOOR == static_cast<PixelRoundCalcPolicy>(startValue)) {
1761             value |= static_cast<uint8_t>(PixelRoundPolicy::FORCE_FLOOR_START);
1762         }
1763     }
1764     JSRef<JSVal> jsTopValue = object->GetProperty("top");
1765     if (jsTopValue->IsNumber()) {
1766         int32_t topValue = jsTopValue->ToNumber<int32_t>();
1767         if (PixelRoundCalcPolicy::FORCE_CEIL == static_cast<PixelRoundCalcPolicy>(topValue)) {
1768             value |= static_cast<uint8_t>(PixelRoundPolicy::FORCE_CEIL_TOP);
1769         } else if (PixelRoundCalcPolicy::FORCE_FLOOR == static_cast<PixelRoundCalcPolicy>(topValue)) {
1770             value |= static_cast<uint8_t>(PixelRoundPolicy::FORCE_FLOOR_TOP);
1771         }
1772     }
1773     JSRef<JSVal> jsEndValue = object->GetProperty("end");
1774     if (jsEndValue->IsNumber()) {
1775         int32_t endValue = jsEndValue->ToNumber<int32_t>();
1776         if (PixelRoundCalcPolicy::FORCE_CEIL == static_cast<PixelRoundCalcPolicy>(endValue)) {
1777             value |= static_cast<uint8_t>(PixelRoundPolicy::FORCE_CEIL_END);
1778         } else if (PixelRoundCalcPolicy::FORCE_FLOOR == static_cast<PixelRoundCalcPolicy>(endValue)) {
1779             value |= static_cast<uint8_t>(PixelRoundPolicy::FORCE_FLOOR_END);
1780         }
1781     }
1782     JSRef<JSVal> jsBottomValue = object->GetProperty("bottom");
1783     if (jsBottomValue->IsNumber()) {
1784         int32_t bottomValue = jsBottomValue->ToNumber<int32_t>();
1785         if (PixelRoundCalcPolicy::FORCE_CEIL == static_cast<PixelRoundCalcPolicy>(bottomValue)) {
1786             value |= static_cast<uint8_t>(PixelRoundPolicy::FORCE_CEIL_BOTTOM);
1787         } else if (PixelRoundCalcPolicy::FORCE_FLOOR == static_cast<PixelRoundCalcPolicy>(bottomValue)) {
1788             value |= static_cast<uint8_t>(PixelRoundPolicy::FORCE_FLOOR_BOTTOM);
1789         }
1790     }
1791     ViewAbstractModel::GetInstance()->SetPixelRound(value);
1792 }
1793 
JsLayoutWeight(const JSCallbackInfo & info)1794 void JSViewAbstract::JsLayoutWeight(const JSCallbackInfo& info)
1795 {
1796     float value = 0.0f;
1797     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER };
1798     if (!CheckJSCallbackInfo("JsLayoutWeight", info, checkList)) {
1799         if (!info[0]->IsUndefined()) {
1800             return;
1801         }
1802     }
1803 
1804     if (info[0]->IsNumber()) {
1805         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1806             value = info[0]->ToNumber<float>();
1807         } else {
1808             value = info[0]->ToNumber<int32_t>();
1809         }
1810     } else {
1811         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1812             value = static_cast<float>(StringUtils::StringToUint(info[0]->ToString()));
1813         } else {
1814             value = static_cast<int32_t>(StringUtils::StringToUint(info[0]->ToString()));
1815         }
1816     }
1817 
1818     ViewAbstractModel::GetInstance()->SetLayoutWeight(value);
1819 }
1820 
JsAlign(const JSCallbackInfo & info)1821 void JSViewAbstract::JsAlign(const JSCallbackInfo& info)
1822 {
1823     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
1824     if (!CheckJSCallbackInfo("JsAlign", info, checkList) &&
1825         Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
1826         ViewAbstractModel::GetInstance()->SetAlign(Alignment::CENTER);
1827         return;
1828     }
1829     auto value = info[0]->ToNumber<int32_t>();
1830     Alignment alignment = ParseAlignment(value);
1831     ViewAbstractModel::GetInstance()->SetAlign(alignment);
1832 }
1833 
JsPosition(const JSCallbackInfo & info)1834 void JSViewAbstract::JsPosition(const JSCallbackInfo& info)
1835 {
1836     CalcDimension x;
1837     CalcDimension y;
1838     if (ParseLocationProps(info, x, y)) {
1839         ViewAbstractModel::GetInstance()->SetPosition(x, y);
1840     } else {
1841         ViewAbstractModel::GetInstance()->SetPosition(0.0_vp, 0.0_vp);
1842     }
1843 }
1844 
JsMarkAnchor(const JSCallbackInfo & info)1845 void JSViewAbstract::JsMarkAnchor(const JSCallbackInfo& info)
1846 {
1847     CalcDimension x;
1848     CalcDimension y;
1849     if (ParseLocationProps(info, x, y)) {
1850         ViewAbstractModel::GetInstance()->MarkAnchor(x, y);
1851     } else {
1852         ViewAbstractModel::GetInstance()->MarkAnchor(0.0_vp, 0.0_vp);
1853     }
1854 }
1855 
JsOffset(const JSCallbackInfo & info)1856 void JSViewAbstract::JsOffset(const JSCallbackInfo& info)
1857 {
1858     CalcDimension x;
1859     CalcDimension y;
1860     if (ParseLocationProps(info, x, y)) {
1861         ViewAbstractModel::GetInstance()->SetOffset(x, y);
1862     } else {
1863         ViewAbstractModel::GetInstance()->SetOffset(0.0_vp, 0.0_vp);
1864     }
1865 }
1866 
JsEnabled(const JSCallbackInfo & info)1867 void JSViewAbstract::JsEnabled(const JSCallbackInfo& info)
1868 {
1869     auto arg = info[0];
1870     if (!arg->IsBoolean()) {
1871         ViewAbstractModel::GetInstance()->SetEnabled(true);
1872     } else {
1873         ViewAbstractModel::GetInstance()->SetEnabled(arg->ToBoolean());
1874     }
1875 }
1876 
JsAspectRatio(const JSCallbackInfo & info)1877 void JSViewAbstract::JsAspectRatio(const JSCallbackInfo& info)
1878 {
1879     double value = 0.0;
1880     if (!ParseJsDouble(info[0], value)) {
1881         // add version protection, undefined use default value
1882         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN) &&
1883             (info[0]->IsNull() || info[0]->IsUndefined())) {
1884             ViewAbstractModel::GetInstance()->ResetAspectRatio();
1885             return;
1886         } else {
1887             return;
1888         }
1889     }
1890 
1891     // negative use default value.
1892     if (LessOrEqual(value, 0.0)) {
1893         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
1894             ViewAbstractModel::GetInstance()->ResetAspectRatio();
1895             return;
1896         } else {
1897             value = 1.0;
1898         }
1899     }
1900 
1901     ViewAbstractModel::GetInstance()->SetAspectRatio(static_cast<float>(value));
1902 }
1903 
JsOverlay(const JSCallbackInfo & info)1904 void JSViewAbstract::JsOverlay(const JSCallbackInfo& info)
1905 {
1906     if (info.Length() > 0 && (info[0]->IsUndefined())) {
1907         ViewAbstractModel::GetInstance()->SetOverlay(
1908             "", nullptr, Alignment::TOP_LEFT, CalcDimension(0), CalcDimension(0));
1909         return;
1910     }
1911 
1912     if (info.Length() <= 0 || (!info[0]->IsString() && !info[0]->IsObject())) {
1913         return;
1914     }
1915     std::optional<Alignment> align;
1916     std::optional<CalcDimension> offsetX;
1917     std::optional<CalcDimension> offsetY;
1918 
1919     if (info[1]->IsObject()) {
1920         JSRef<JSObject> optionObj = JSRef<JSObject>::Cast(info[1]);
1921         JSRef<JSVal> alignVal = optionObj->GetProperty("align");
1922         auto value = alignVal->ToNumber<int32_t>();
1923         Alignment alignment = ParseAlignment(value);
1924         align = alignment;
1925 
1926         JSRef<JSVal> val = optionObj->GetProperty("offset");
1927         if (val->IsObject()) {
1928             JSRef<JSObject> offsetObj = JSRef<JSObject>::Cast(val);
1929             JSRef<JSVal> xVal = offsetObj->GetProperty("x");
1930             CalcDimension x;
1931             if (ParseJsDimensionVp(xVal, x)) {
1932                 offsetX = x;
1933             }
1934             JSRef<JSVal> yVal = offsetObj->GetProperty("y");
1935             CalcDimension y;
1936             if (ParseJsDimensionVp(yVal, y)) {
1937                 offsetY = y;
1938             }
1939         }
1940     }
1941 
1942     if (info[0]->IsString()) {
1943         std::string text = info[0]->ToString();
1944         ViewAbstractModel::GetInstance()->SetOverlay(text, nullptr, align, offsetX, offsetY);
1945     } else if (info[0]->IsObject()) {
1946         JSRef<JSObject> menuObj = JSRef<JSObject>::Cast(info[0]);
1947         auto builder = menuObj->GetProperty("builder");
1948         if (!builder->IsFunction()) {
1949             return;
1950         }
1951         auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
1952         CHECK_NULL_VOID(builderFunc);
1953         WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
1954         auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = targetNode]() {
1955             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1956             ACE_SCORING_EVENT("Overlay");
1957             PipelineContext::SetCallBackNode(node);
1958             func->Execute();
1959         };
1960         ViewAbstractModel::GetInstance()->SetOverlay("", std::move(buildFunc), align, offsetX, offsetY);
1961     }
1962 }
1963 
ParseAlignment(int32_t align)1964 Alignment JSViewAbstract::ParseAlignment(int32_t align)
1965 {
1966     Alignment alignment = Alignment::CENTER;
1967     switch (align) {
1968         case 0:
1969             alignment = Alignment::TOP_LEFT;
1970             break;
1971         case 1:
1972             alignment = Alignment::TOP_CENTER;
1973             break;
1974         case 2:
1975             alignment = Alignment::TOP_RIGHT;
1976             break;
1977         case 3:
1978             alignment = Alignment::CENTER_LEFT;
1979             break;
1980         case 4:
1981             alignment = Alignment::CENTER;
1982             break;
1983         case 5:
1984             alignment = Alignment::CENTER_RIGHT;
1985             break;
1986         case 6:
1987             alignment = Alignment::BOTTOM_LEFT;
1988             break;
1989         case 7:
1990             alignment = Alignment::BOTTOM_CENTER;
1991             break;
1992         case 8:
1993             alignment = Alignment::BOTTOM_RIGHT;
1994             break;
1995         default:
1996             break;
1997     }
1998     return alignment;
1999 }
2000 
SetVisibility(const JSCallbackInfo & info)2001 void JSViewAbstract::SetVisibility(const JSCallbackInfo& info)
2002 {
2003     int32_t visible = 0;
2004     if (info[0]->IsNull() || info[0]->IsUndefined()) {
2005         // undefined value use default value.
2006         visible = 0;
2007     } else if (!info[0]->IsNumber()) {
2008         return;
2009     } else {
2010         visible = info[0]->ToNumber<int32_t>();
2011     }
2012 
2013     if (info.Length() > 1 && info[1]->IsFunction()) {
2014         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[1]));
2015         WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
2016         auto onVisibilityChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
2017                                       int32_t visible) {
2018             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
2019             ACE_SCORING_EVENT("onVisibilityChange");
2020             PipelineContext::SetCallBackNode(node);
2021             JSRef<JSVal> newJSVal = JSRef<JSVal>::Make(ToJSValue(visible));
2022             func->ExecuteJS(1, &newJSVal);
2023         };
2024         ViewAbstractModel::GetInstance()->SetVisibility(
2025             static_cast<VisibleType>(visible), std::move(onVisibilityChange));
2026     } else {
2027         ViewAbstractModel::GetInstance()->SetVisibility(static_cast<VisibleType>(visible), [](int32_t visible) {});
2028     }
2029 }
2030 
JsSetFreeze(const JSCallbackInfo & info)2031 void JSViewAbstract::JsSetFreeze(const JSCallbackInfo& info)
2032 {
2033     if (info[0]->IsBoolean()) {
2034         ViewAbstractModel::GetInstance()->SetFreeze(info[0]->ToBoolean());
2035     }
2036 }
2037 
JsFlexBasis(const JSCallbackInfo & info)2038 void JSViewAbstract::JsFlexBasis(const JSCallbackInfo& info)
2039 {
2040     CalcDimension value;
2041     if (!ParseJsDimensionVp(info[0], value)) {
2042         value.SetUnit(DimensionUnit::AUTO);
2043     }
2044     // flexbasis don't support percent case.
2045     if (value.Unit() == DimensionUnit::PERCENT) {
2046         value.SetUnit(DimensionUnit::AUTO);
2047     }
2048     ViewAbstractModel::GetInstance()->SetFlexBasis(value);
2049 }
2050 
JsFlexGrow(const JSCallbackInfo & info)2051 void JSViewAbstract::JsFlexGrow(const JSCallbackInfo& info)
2052 {
2053     double value = 0.0;
2054     if (!ParseJsDouble(info[0], value)) {
2055         if (info[0]->IsNull() || info[0]->IsUndefined()) {
2056             // undefined use default value.
2057             value = 0.0;
2058         } else {
2059             return;
2060         }
2061     }
2062     // negative use default value.
2063     if (value < 0.0) {
2064         value = 0.0;
2065     }
2066     ViewAbstractModel::GetInstance()->SetFlexGrow(static_cast<float>(value));
2067 }
2068 
JsFlexShrink(const JSCallbackInfo & info)2069 void JSViewAbstract::JsFlexShrink(const JSCallbackInfo& info)
2070 {
2071     double value = 0.0;
2072     if (!ParseJsDouble(info[0], value)) {
2073         if (info[0]->IsNull() || info[0]->IsUndefined()) {
2074             // undefined use default value.
2075             ViewAbstractModel::GetInstance()->ResetFlexShrink();
2076             return;
2077         } else {
2078             return;
2079         }
2080     }
2081     // negative use default value.
2082     if (value < 0.0) {
2083         ViewAbstractModel::GetInstance()->ResetFlexShrink();
2084         return;
2085     }
2086     ViewAbstractModel::GetInstance()->SetFlexShrink(static_cast<float>(value));
2087 }
2088 
JsDisplayPriority(const JSCallbackInfo & info)2089 void JSViewAbstract::JsDisplayPriority(const JSCallbackInfo& info)
2090 {
2091     double value = 0.0;
2092     if (!ParseJsDouble(info[0], value)) {
2093         return;
2094     }
2095     ViewAbstractModel::GetInstance()->SetDisplayIndex(static_cast<int32_t>(value));
2096 }
2097 
JsSharedTransition(const JSCallbackInfo & info)2098 void JSViewAbstract::JsSharedTransition(const JSCallbackInfo& info)
2099 {
2100     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING };
2101     if (!CheckJSCallbackInfo("JsSharedTransition", info, checkList)) {
2102         return;
2103     }
2104     // id
2105     auto id = info[0]->ToString();
2106     if (id.empty()) {
2107         return;
2108     }
2109     std::shared_ptr<SharedTransitionOption> sharedOption;
2110 
2111     // options
2112     if (info.Length() > 1 && info[1]->IsObject()) {
2113         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[1]);
2114         sharedOption = std::make_shared<SharedTransitionOption>();
2115         // default: duration: 1000
2116         sharedOption->duration = jsObj->GetPropertyValue<int32_t>("duration", DEFAULT_DURATION);
2117         if (sharedOption->duration < 0) {
2118             sharedOption->duration = DEFAULT_DURATION;
2119         }
2120         // default: delay: 0
2121         sharedOption->delay = jsObj->GetPropertyValue<int32_t>("delay", 0);
2122         if (sharedOption->delay < 0) {
2123             sharedOption->delay = 0;
2124         }
2125         // default: LinearCurve
2126         RefPtr<Curve> curve;
2127         JSRef<JSVal> curveArgs = jsObj->GetProperty("curve");
2128         if (curveArgs->IsString()) {
2129             curve = CreateCurve(jsObj->GetPropertyValue<std::string>("curve", "linear"), false);
2130         } else if (curveArgs->IsObject()) {
2131             JSRef<JSVal> curveString = JSRef<JSObject>::Cast(curveArgs)->GetProperty("__curveString");
2132             if (!curveString->IsString()) {
2133                 return;
2134             }
2135             curve = CreateCurve(curveString->ToString(), false);
2136         }
2137         if (!curve) {
2138             curve = Curves::LINEAR;
2139         }
2140         sharedOption->curve = curve;
2141         // motionPath
2142         if (jsObj->HasProperty("motionPath")) {
2143             MotionPathOption motionPathOption;
2144             if (ParseMotionPath(jsObj->GetProperty("motionPath"), motionPathOption)) {
2145                 sharedOption->motionPathOption = motionPathOption;
2146             }
2147         }
2148         // zIndex
2149         sharedOption->zIndex = jsObj->GetPropertyValue<int32_t>("zIndex", 0);
2150         // type
2151         int32_t type = jsObj->GetPropertyValue<int32_t>("type",
2152             static_cast<int32_t>(SharedTransitionEffectType::SHARED_EFFECT_EXCHANGE));
2153         sharedOption->type = static_cast<SharedTransitionEffectType>(type);
2154     }
2155     ViewAbstractModel::GetInstance()->SetSharedTransition(id, sharedOption);
2156 }
2157 
JsGeometryTransition(const JSCallbackInfo & info)2158 void JSViewAbstract::JsGeometryTransition(const JSCallbackInfo& info)
2159 {
2160     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING };
2161     if (!CheckJSCallbackInfo("JsGeometryTransition", info, checkList)) {
2162         return;
2163     }
2164     // id
2165     auto id = info[0]->ToString();
2166     // follow flag
2167     bool followWithOutTransition = false;
2168     if (info.Length() >= PARAMETER_LENGTH_SECOND) {
2169         if (info[1]->IsBoolean()) {
2170             followWithOutTransition = info[1]->ToBoolean();
2171         } else if (info[1]->IsObject()) {
2172             JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[1]);
2173             ParseJsBool(jsOption->GetProperty("follow"), followWithOutTransition);
2174         }
2175     }
2176     ViewAbstractModel::GetInstance()->SetGeometryTransition(id, followWithOutTransition);
2177 }
2178 
JsAlignSelf(const JSCallbackInfo & info)2179 void JSViewAbstract::JsAlignSelf(const JSCallbackInfo& info)
2180 {
2181     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
2182     if (!CheckJSCallbackInfo("JsAlignSelf", info, checkList)) {
2183         ViewAbstractModel::GetInstance()->SetAlignSelf(FlexAlign::AUTO);
2184         return;
2185     }
2186     auto alignVal = info[0]->ToNumber<int32_t>();
2187 
2188     if (alignVal >= 0 && alignVal <= MAX_ALIGN_VALUE) {
2189         ViewAbstractModel::GetInstance()->SetAlignSelf(static_cast<FlexAlign>(alignVal));
2190     }
2191 }
2192 
JsBackgroundColor(const JSCallbackInfo & info)2193 void JSViewAbstract::JsBackgroundColor(const JSCallbackInfo& info)
2194 {
2195     Color backgroundColor;
2196     if (!ParseJsColor(info[0], backgroundColor)) {
2197         backgroundColor = Color::TRANSPARENT;
2198     }
2199 
2200     ViewAbstractModel::GetInstance()->SetBackgroundColor(backgroundColor);
2201 }
2202 
JsBackgroundImage(const JSCallbackInfo & info)2203 void JSViewAbstract::JsBackgroundImage(const JSCallbackInfo& info)
2204 {
2205     std::string src;
2206     std::string bundle;
2207     std::string module;
2208     RefPtr<PixelMap> pixmap = nullptr;
2209     GetJsMediaBundleInfo(info[0], bundle, module);
2210     if (info[0]->IsString()) {
2211         src = info[0]->ToString();
2212         ViewAbstractModel::GetInstance()->SetBackgroundImage(
2213             ImageSourceInfo { src, bundle, module }, GetThemeConstants());
2214     } else if (ParseJsMedia(info[0], src)) {
2215         ViewAbstractModel::GetInstance()->SetBackgroundImage(ImageSourceInfo { src, bundle, module }, nullptr);
2216     } else {
2217 #if defined(PIXEL_MAP_SUPPORTED)
2218         if (IsDrawable(info[0])) {
2219             pixmap = GetDrawablePixmap(info[0]);
2220         } else {
2221             pixmap = CreatePixelMapFromNapiValue(info[0]);
2222         }
2223 #endif
2224         CHECK_NULL_VOID(pixmap);
2225         ViewAbstractModel::GetInstance()->SetBackgroundImage(ImageSourceInfo { pixmap }, nullptr);
2226     }
2227 
2228     int32_t repeatIndex = 0;
2229     if (info.Length() == 2 && info[1]->IsNumber()) {
2230         repeatIndex = info[1]->ToNumber<int32_t>();
2231     }
2232     auto repeat = static_cast<ImageRepeat>(repeatIndex);
2233     ViewAbstractModel::GetInstance()->SetBackgroundImageRepeat(repeat);
2234 }
2235 
ParseBlurOption(const JSRef<JSObject> & jsBlurOption,BlurOption & blurOption)2236 void JSViewAbstract::ParseBlurOption(const JSRef<JSObject>& jsBlurOption, BlurOption& blurOption)
2237 {
2238     if (jsBlurOption->GetProperty("grayscale")->IsArray()) {
2239         JSRef<JSArray> params = JSRef<JSArray>::Cast(jsBlurOption->GetProperty("grayscale"));
2240         auto grey1 = params->GetValueAt(0)->ToNumber<uint32_t>();
2241         auto grey2 = params->GetValueAt(1)->ToNumber<uint32_t>();
2242         std::vector<float> greyVec(2); // 2 number
2243         greyVec[0] = grey1;
2244         greyVec[1] = grey2;
2245         blurOption.grayscale = greyVec;
2246     }
2247 }
2248 
JsBackgroundBlurStyle(const JSCallbackInfo & info)2249 void JSViewAbstract::JsBackgroundBlurStyle(const JSCallbackInfo& info)
2250 {
2251     if (info.Length() == 0) {
2252         return;
2253     }
2254     BlurStyleOption styleOption;
2255     if (info[0]->IsNumber()) {
2256         auto blurStyle = info[0]->ToNumber<int32_t>();
2257         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
2258             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
2259             styleOption.blurStyle = static_cast<BlurStyle>(blurStyle);
2260         }
2261     }
2262     if (info.Length() > 1 && info[1]->IsObject()) {
2263         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[1]);
2264         auto colorMode = static_cast<int32_t>(ThemeColorMode::SYSTEM);
2265         ParseJsInt32(jsOption->GetProperty("colorMode"), colorMode);
2266         if (colorMode >= static_cast<int32_t>(ThemeColorMode::SYSTEM) &&
2267             colorMode <= static_cast<int32_t>(ThemeColorMode::DARK)) {
2268             styleOption.colorMode = static_cast<ThemeColorMode>(colorMode);
2269         }
2270         auto adaptiveColor = static_cast<int32_t>(AdaptiveColor::DEFAULT);
2271         ParseJsInt32(jsOption->GetProperty("adaptiveColor"), adaptiveColor);
2272         if (adaptiveColor >= static_cast<int32_t>(AdaptiveColor::DEFAULT) &&
2273             adaptiveColor <= static_cast<int32_t>(AdaptiveColor::AVERAGE)) {
2274             styleOption.adaptiveColor = static_cast<AdaptiveColor>(adaptiveColor);
2275         }
2276         if (jsOption->GetProperty("scale")->IsNumber()) {
2277             double scale = jsOption->GetProperty("scale")->ToNumber<double>();
2278             styleOption.scale = std::clamp(scale, 0.0, 1.0);
2279         }
2280 
2281         if (jsOption->GetProperty("blurOptions")->IsObject()) {
2282             JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(jsOption->GetProperty("blurOptions"));
2283             BlurOption blurOption;
2284             ParseBlurOption(jsBlurOption, blurOption);
2285             styleOption.blurOption = blurOption;
2286         }
2287     }
2288     ViewAbstractModel::GetInstance()->SetBackgroundBlurStyle(styleOption);
2289 }
2290 
ParseEffectOption(const JSRef<JSObject> & jsOption,EffectOption & effectOption)2291 void JSViewAbstract::ParseEffectOption(const JSRef<JSObject>& jsOption, EffectOption& effectOption)
2292 {
2293     CalcDimension radius;
2294     if (!ParseJsDimensionVp(jsOption->GetProperty("radius"), radius) || LessNotEqual(radius.Value(), 0.0f)) {
2295         radius.SetValue(0.0f);
2296     }
2297     double saturation = 1.0f;
2298     if (jsOption->GetProperty("saturation")->IsNumber()) {
2299         saturation = jsOption->GetProperty("saturation")->ToNumber<double>();
2300         saturation = (saturation > 0.0f || NearZero(saturation)) ? saturation : 1.0f;
2301     }
2302     double brightness = 1.0f;
2303     if (jsOption->GetProperty("brightness")->IsNumber()) {
2304         brightness = jsOption->GetProperty("brightness")->ToNumber<double>();
2305         brightness = (brightness > 0.0f || NearZero(brightness)) ? brightness : 1.0f;
2306     }
2307     Color color = Color::TRANSPARENT;
2308     if (!ParseJsColor(jsOption->GetProperty("color"), color)) {
2309         color.SetValue(Color::TRANSPARENT.GetValue());
2310     }
2311     auto adaptiveColorValue = static_cast<int32_t>(AdaptiveColor::DEFAULT);
2312     auto adaptiveColor = AdaptiveColor::DEFAULT;
2313     ParseJsInt32(jsOption->GetProperty("adaptiveColor"), adaptiveColorValue);
2314     if (adaptiveColorValue >= static_cast<int32_t>(AdaptiveColor::DEFAULT) &&
2315         adaptiveColorValue <= static_cast<int32_t>(AdaptiveColor::AVERAGE)) {
2316         adaptiveColor = static_cast<AdaptiveColor>(adaptiveColorValue);
2317     }
2318 
2319     BlurOption blurOption;
2320     if (jsOption->GetProperty("blurOptions")->IsObject()) {
2321         JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(jsOption->GetProperty("blurOptions"));
2322         ParseBlurOption(jsBlurOption, blurOption);
2323     }
2324     effectOption = { radius, saturation, brightness, color, adaptiveColor, blurOption };
2325 }
2326 
JsBackgroundEffect(const JSCallbackInfo & info)2327 void JSViewAbstract::JsBackgroundEffect(const JSCallbackInfo& info)
2328 {
2329     if (info.Length() == 0) {
2330         return;
2331     }
2332     EffectOption option;
2333     if (info[0]->IsObject()) {
2334         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[0]);
2335         ParseEffectOption(jsOption, option);
2336     }
2337     ViewAbstractModel::GetInstance()->SetBackgroundEffect(option);
2338 }
2339 
JsForegroundBlurStyle(const JSCallbackInfo & info)2340 void JSViewAbstract::JsForegroundBlurStyle(const JSCallbackInfo& info)
2341 {
2342     if (info.Length() == 0) {
2343         return;
2344     }
2345     BlurStyleOption styleOption;
2346     if (info[0]->IsNumber()) {
2347         auto blurStyle = info[0]->ToNumber<int32_t>();
2348         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
2349             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
2350             styleOption.blurStyle = static_cast<BlurStyle>(blurStyle);
2351         }
2352     }
2353     if (info.Length() > 1 && info[1]->IsObject()) {
2354         JSRef<JSObject> jsOption = JSRef<JSObject>::Cast(info[1]);
2355         auto colorMode = static_cast<int32_t>(ThemeColorMode::SYSTEM);
2356         ParseJsInt32(jsOption->GetProperty("colorMode"), colorMode);
2357         if (colorMode >= static_cast<int32_t>(ThemeColorMode::SYSTEM) &&
2358             colorMode <= static_cast<int32_t>(ThemeColorMode::DARK)) {
2359             styleOption.colorMode = static_cast<ThemeColorMode>(colorMode);
2360         }
2361         auto adaptiveColor = static_cast<int32_t>(AdaptiveColor::DEFAULT);
2362         ParseJsInt32(jsOption->GetProperty("adaptiveColor"), adaptiveColor);
2363         if (adaptiveColor >= static_cast<int32_t>(AdaptiveColor::DEFAULT) &&
2364             adaptiveColor <= static_cast<int32_t>(AdaptiveColor::AVERAGE)) {
2365             styleOption.adaptiveColor = static_cast<AdaptiveColor>(adaptiveColor);
2366         }
2367         if (jsOption->GetProperty("scale")->IsNumber()) {
2368             double scale = jsOption->GetProperty("scale")->ToNumber<double>();
2369             styleOption.scale = std::clamp(scale, 0.0, 1.0);
2370         }
2371 
2372         if (jsOption->GetProperty("blurOptions")->IsObject()) {
2373             JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(jsOption->GetProperty("blurOptions"));
2374             BlurOption blurOption;
2375             ParseBlurOption(jsBlurOption, blurOption);
2376             styleOption.blurOption = blurOption;
2377         }
2378     }
2379     ViewAbstractModel::GetInstance()->SetForegroundBlurStyle(styleOption);
2380 }
2381 
JsSphericalEffect(const JSCallbackInfo & info)2382 void JSViewAbstract::JsSphericalEffect(const JSCallbackInfo& info)
2383 {
2384     auto radio = 0.0;
2385     if (info[0]->IsNumber()) {
2386         radio = info[0]->ToNumber<double>();
2387     }
2388     ViewAbstractModel::GetInstance()->SetSphericalEffect(std::clamp(radio, 0.0, 1.0));
2389 }
2390 
JsPixelStretchEffect(const JSCallbackInfo & info)2391 void JSViewAbstract::JsPixelStretchEffect(const JSCallbackInfo& info)
2392 {
2393     if (!info[0]->IsObject()) {
2394         PixStretchEffectOption option;
2395         option.ResetValue();
2396         ViewAbstractModel::GetInstance()->SetPixelStretchEffect(option);
2397         return;
2398     }
2399     auto jsObject = JSRef<JSObject>::Cast(info[0]);
2400     CalcDimension left;
2401     ParseJsDimensionVp(jsObject->GetProperty("left"), left);
2402     CalcDimension right;
2403     ParseJsDimensionVp(jsObject->GetProperty("right"), right);
2404     CalcDimension top;
2405     ParseJsDimensionVp(jsObject->GetProperty("top"), top);
2406     CalcDimension bottom;
2407     ParseJsDimensionVp(jsObject->GetProperty("bottom"), bottom);
2408 
2409     PixStretchEffectOption option;
2410     bool illegalInput = false;
2411     if (left.Unit() == DimensionUnit::PERCENT || right.Unit() == DimensionUnit::PERCENT ||
2412         top.Unit() == DimensionUnit::PERCENT || bottom.Unit() == DimensionUnit::PERCENT) {
2413         if ((NearEqual(left.Value(), 0.0) || left.Unit() == DimensionUnit::PERCENT) &&
2414             (NearEqual(top.Value(), 0.0) || top.Unit() == DimensionUnit::PERCENT) &&
2415             (NearEqual(right.Value(), 0.0) || right.Unit() == DimensionUnit::PERCENT) &&
2416             (NearEqual(bottom.Value(), 0.0) || bottom.Unit() == DimensionUnit::PERCENT)) {
2417             left.SetUnit(DimensionUnit::PERCENT);
2418             top.SetUnit(DimensionUnit::PERCENT);
2419             right.SetUnit(DimensionUnit::PERCENT);
2420             bottom.SetUnit(DimensionUnit::PERCENT);
2421         } else {
2422             illegalInput = true;
2423         }
2424     }
2425     if ((left.IsNonNegative() && top.IsNonNegative() && right.IsNonNegative() && bottom.IsNonNegative()) ||
2426         (left.IsNonPositive() && top.IsNonPositive() && right.IsNonPositive() && bottom.IsNonPositive())) {
2427         option.left = left;
2428         option.top = top;
2429         option.right = right;
2430         option.bottom = bottom;
2431     } else {
2432         illegalInput = true;
2433     }
2434     if (illegalInput) {
2435         option.ResetValue();
2436     }
2437     ViewAbstractModel::GetInstance()->SetPixelStretchEffect(option);
2438 }
2439 
JsLightUpEffect(const JSCallbackInfo & info)2440 void JSViewAbstract::JsLightUpEffect(const JSCallbackInfo& info)
2441 {
2442     auto radio = 1.0;
2443     if (info[0]->IsNumber()) {
2444         radio = info[0]->ToNumber<double>();
2445     }
2446     ViewAbstractModel::GetInstance()->SetLightUpEffect(std::clamp(radio, 0.0, 1.0));
2447 }
2448 
JsBackgroundImageSize(const JSCallbackInfo & info)2449 void JSViewAbstract::JsBackgroundImageSize(const JSCallbackInfo& info)
2450 {
2451     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
2452     BackgroundImageSize bgImgSize;
2453     if (!CheckJSCallbackInfo("JsBackgroundImageSize", info, checkList)) {
2454         bgImgSize.SetSizeTypeX(BackgroundImageSizeType::AUTO);
2455         bgImgSize.SetSizeTypeY(BackgroundImageSizeType::AUTO);
2456         ViewAbstractModel::GetInstance()->SetBackgroundImageSize(bgImgSize);
2457         return;
2458     }
2459     if (info[0]->IsNumber()) {
2460         auto sizeType = static_cast<BackgroundImageSizeType>(info[0]->ToNumber<int32_t>());
2461         bgImgSize.SetSizeTypeX(sizeType);
2462         bgImgSize.SetSizeTypeY(sizeType);
2463     } else {
2464         CalcDimension width;
2465         CalcDimension height;
2466         JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
2467         ParseJsDimensionVp(object->GetProperty("width"), width);
2468         ParseJsDimensionVp(object->GetProperty("height"), height);
2469         double valueWidth = width.ConvertToPx();
2470         double valueHeight = height.ConvertToPx();
2471         BackgroundImageSizeType typeWidth = BackgroundImageSizeType::LENGTH;
2472         BackgroundImageSizeType typeHeight = BackgroundImageSizeType::LENGTH;
2473         if (width.Unit() == DimensionUnit::PERCENT) {
2474             typeWidth = BackgroundImageSizeType::PERCENT;
2475             valueWidth = width.Value() * FULL_DIMENSION;
2476         }
2477         if (height.Unit() == DimensionUnit::PERCENT) {
2478             typeHeight = BackgroundImageSizeType::PERCENT;
2479             valueHeight = height.Value() * FULL_DIMENSION;
2480         }
2481         bgImgSize.SetSizeTypeX(typeWidth);
2482         bgImgSize.SetSizeValueX(valueWidth);
2483         bgImgSize.SetSizeTypeY(typeHeight);
2484         bgImgSize.SetSizeValueY(valueHeight);
2485     }
2486 
2487     ViewAbstractModel::GetInstance()->SetBackgroundImageSize(bgImgSize);
2488 }
2489 
JsBackgroundImagePosition(const JSCallbackInfo & info)2490 void JSViewAbstract::JsBackgroundImagePosition(const JSCallbackInfo& info)
2491 {
2492     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
2493     BackgroundImagePosition bgImgPosition;
2494     if (!CheckJSCallbackInfo("JsBackgroundImagePosition", info, checkList)) {
2495         SetBgImgPosition(DimensionUnit::PX, DimensionUnit::PX, 0.0, 0.0, bgImgPosition);
2496         ViewAbstractModel::GetInstance()->SetBackgroundImagePosition(bgImgPosition);
2497         return;
2498     }
2499     if (info[0]->IsNumber()) {
2500         int32_t align = info[0]->ToNumber<int32_t>();
2501         bgImgPosition.SetIsAlign(true);
2502         switch (align) {
2503             case 0:
2504                 SetBgImgPosition(DimensionUnit::PERCENT, DimensionUnit::PERCENT, 0.0, 0.0, bgImgPosition);
2505                 break;
2506             case 1:
2507                 SetBgImgPosition(DimensionUnit::PERCENT, DimensionUnit::PERCENT, HALF_DIMENSION, 0.0, bgImgPosition);
2508                 break;
2509             case 2:
2510                 SetBgImgPosition(DimensionUnit::PERCENT, DimensionUnit::PERCENT, FULL_DIMENSION, 0.0, bgImgPosition);
2511                 break;
2512             case 3:
2513                 SetBgImgPosition(DimensionUnit::PERCENT, DimensionUnit::PERCENT, 0.0, HALF_DIMENSION, bgImgPosition);
2514                 break;
2515             case 4:
2516                 SetBgImgPosition(
2517                     DimensionUnit::PERCENT, DimensionUnit::PERCENT, HALF_DIMENSION, HALF_DIMENSION, bgImgPosition);
2518                 break;
2519             case 5:
2520                 SetBgImgPosition(
2521                     DimensionUnit::PERCENT, DimensionUnit::PERCENT, FULL_DIMENSION, HALF_DIMENSION, bgImgPosition);
2522                 break;
2523             case 6:
2524                 SetBgImgPosition(DimensionUnit::PERCENT, DimensionUnit::PERCENT, 0.0, FULL_DIMENSION, bgImgPosition);
2525                 break;
2526             case 7:
2527                 SetBgImgPosition(
2528                     DimensionUnit::PERCENT, DimensionUnit::PERCENT, HALF_DIMENSION, FULL_DIMENSION, bgImgPosition);
2529                 break;
2530             case 8:
2531                 SetBgImgPosition(
2532                     DimensionUnit::PERCENT, DimensionUnit::PERCENT, FULL_DIMENSION, FULL_DIMENSION, bgImgPosition);
2533                 break;
2534             default:
2535                 break;
2536         }
2537     } else {
2538         CalcDimension x;
2539         CalcDimension y;
2540         JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
2541         ParseJsDimensionVp(object->GetProperty("x"), x);
2542         ParseJsDimensionVp(object->GetProperty("y"), y);
2543         double valueX = x.Value();
2544         double valueY = y.Value();
2545         DimensionUnit typeX = DimensionUnit::PX;
2546         DimensionUnit typeY = DimensionUnit::PX;
2547         if (x.Unit() == DimensionUnit::PERCENT) {
2548             valueX = x.Value();
2549             typeX = DimensionUnit::PERCENT;
2550         }
2551         if (y.Unit() == DimensionUnit::PERCENT) {
2552             valueY = y.Value();
2553             typeY = DimensionUnit::PERCENT;
2554         }
2555         SetBgImgPosition(typeX, typeY, valueX, valueY, bgImgPosition);
2556     }
2557 
2558     ViewAbstractModel::GetInstance()->SetBackgroundImagePosition(bgImgPosition);
2559 }
2560 
ParseBindOptionParam(const JSCallbackInfo & info,size_t optionIndex)2561 std::vector<NG::OptionParam> ParseBindOptionParam(const JSCallbackInfo& info, size_t optionIndex)
2562 {
2563     auto paramArray = JSRef<JSArray>::Cast(info[optionIndex]);
2564     std::vector<NG::OptionParam> params(paramArray->Length());
2565     // parse paramArray
2566     for (size_t i = 0; i < paramArray->Length(); ++i) {
2567         auto indexObject = JSRef<JSObject>::Cast(paramArray->GetValueAt(i));
2568         JSViewAbstract::ParseJsString(indexObject->GetProperty("value"), params[i].value);
2569         auto actionFunc = indexObject->GetProperty("action");
2570         if (!actionFunc->IsFunction()) {
2571             return params;
2572         }
2573         auto action = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(actionFunc));
2574         WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
2575         // set onClick function
2576         params[i].action = [func = std::move(action), context = info.GetExecutionContext(), node = targetNode]() {
2577             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context);
2578             ACE_SCORING_EVENT("menu.action");
2579             PipelineContext::SetCallBackNode(node);
2580             if (func) {
2581                 func->Execute();
2582             }
2583         };
2584         std::string iconPath;
2585         if (JSViewAbstract::ParseJsMedia(indexObject->GetProperty("icon"), iconPath)) {
2586             params[i].icon = iconPath;
2587         }
2588         auto enabled = indexObject->GetProperty("enabled");
2589         if (enabled->IsBoolean()) {
2590             params[i].enabled = enabled->ToBoolean();
2591         }
2592     }
2593     return params;
2594 }
2595 
ParseMenuArrowParam(const JSRef<JSObject> & menuOptions,NG::MenuParam & menuParam)2596 void ParseMenuArrowParam(const JSRef<JSObject>& menuOptions, NG::MenuParam& menuParam)
2597 {
2598     auto enableArrowValue = menuOptions->GetProperty("enableArrow");
2599     if (enableArrowValue->IsBoolean()) {
2600         menuParam.enableArrow = enableArrowValue->ToBoolean();
2601     }
2602 
2603     auto arrowOffset = menuOptions->GetProperty("arrowOffset");
2604     CalcDimension offset;
2605     if (JSViewAbstract::ParseJsDimensionVp(arrowOffset, offset)) {
2606         menuParam.arrowOffset = offset;
2607     }
2608 
2609     // if enableArrow is true and placement not set, set placement default value to top.
2610     if (menuParam.enableArrow.has_value() && !menuParam.placement.has_value() && menuParam.enableArrow.value()) {
2611         menuParam.placement = Placement::TOP;
2612     }
2613 }
2614 
GetMenuShowInSubwindow(NG::MenuParam & menuParam)2615 void GetMenuShowInSubwindow(NG::MenuParam& menuParam)
2616 {
2617     menuParam.isShowInSubWindow = false;
2618     auto pipeline = PipelineBase::GetCurrentContext();
2619     CHECK_NULL_VOID(pipeline);
2620     auto theme = pipeline->GetTheme<SelectTheme>();
2621     CHECK_NULL_VOID(theme);
2622     menuParam.isShowInSubWindow = theme->GetExpandDisplay();
2623 }
2624 
ParseMenuParam(const JSCallbackInfo & info,const JSRef<JSObject> & menuOptions,NG::MenuParam & menuParam)2625 void ParseMenuParam(const JSCallbackInfo& info, const JSRef<JSObject>& menuOptions, NG::MenuParam& menuParam)
2626 {
2627     auto offsetVal = menuOptions->GetProperty("offset");
2628     if (offsetVal->IsObject()) {
2629         auto offsetObj = JSRef<JSObject>::Cast(offsetVal);
2630         JSRef<JSVal> xVal = offsetObj->GetProperty("x");
2631         JSRef<JSVal> yVal = offsetObj->GetProperty("y");
2632         CalcDimension dx;
2633         CalcDimension dy;
2634         if (JSViewAbstract::ParseJsDimensionVp(xVal, dx)) {
2635             menuParam.positionOffset.SetX(dx.ConvertToPx());
2636         }
2637         if (JSViewAbstract::ParseJsDimensionVp(yVal, dy)) {
2638             menuParam.positionOffset.SetY(dy.ConvertToPx());
2639         }
2640     }
2641 
2642     auto placementValue = menuOptions->GetProperty("placement");
2643     if (placementValue->IsNumber()) {
2644         auto placement = placementValue->ToNumber<int32_t>();
2645         if (placement >= 0 && placement < static_cast<int32_t>(PLACEMENT.size())) {
2646             menuParam.placement = PLACEMENT[placement];
2647         }
2648     }
2649 
2650     auto backgroundColorValue = menuOptions->GetProperty("backgroundColor");
2651     Color backgroundColor;
2652     if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
2653         menuParam.backgroundColor = backgroundColor;
2654     }
2655 
2656     auto backgroundBlurStyle = menuOptions->GetProperty("backgroundBlurStyle");
2657     BlurStyleOption styleOption;
2658     if (backgroundBlurStyle->IsNumber()) {
2659         auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
2660         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
2661             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
2662             menuParam.backgroundBlurStyle = blurStyle;
2663         }
2664     }
2665     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
2666     auto onAppearValue = menuOptions->GetProperty("onAppear");
2667     if (onAppearValue->IsFunction()) {
2668         RefPtr<JsFunction> jsOnAppearFunc =
2669             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAppearValue));
2670         auto onAppear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAppearFunc), node = frameNode]() {
2671             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
2672             ACE_SCORING_EVENT("onAppear");
2673             PipelineContext::SetCallBackNode(node);
2674             func->Execute();
2675         };
2676         menuParam.onAppear = std::move(onAppear);
2677     }
2678 
2679     auto onDisappearValue = menuOptions->GetProperty("onDisappear");
2680     if (onDisappearValue->IsFunction()) {
2681         RefPtr<JsFunction> jsOnDisAppearFunc =
2682             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDisappearValue));
2683         auto onDisappear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDisAppearFunc),
2684                                node = frameNode]() {
2685             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
2686             ACE_SCORING_EVENT("onDisappear");
2687             PipelineContext::SetCallBackNode(node);
2688             func->Execute();
2689         };
2690         menuParam.onDisappear = std::move(onDisappear);
2691     }
2692     auto aboutToAppearValue = menuOptions->GetProperty("aboutToAppear");
2693     if (aboutToAppearValue->IsFunction()) {
2694         RefPtr<JsFunction> jsAboutToAppearFunc =
2695             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(aboutToAppearValue));
2696         auto aboutToAppear = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToAppearFunc),
2697                             node = frameNode]() {
2698             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
2699             ACE_SCORING_EVENT("aboutToAppear");
2700             PipelineContext::SetCallBackNode(node);
2701             func->Execute();
2702         };
2703         menuParam.aboutToAppear = std::move(aboutToAppear);
2704     }
2705 
2706     auto aboutToDisAppearValue = menuOptions->GetProperty("aboutToDisappear");
2707     if (aboutToDisAppearValue->IsFunction()) {
2708         RefPtr<JsFunction> jsAboutToDisAppearFunc =
2709             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(aboutToDisAppearValue));
2710         auto aboutToDisappear = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToDisAppearFunc),
2711                                node = frameNode]() {
2712             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
2713             ACE_SCORING_EVENT("aboutToDisappear");
2714             PipelineContext::SetCallBackNode(node);
2715             func->Execute();
2716         };
2717         menuParam.aboutToDisappear = std::move(aboutToDisappear);
2718     }
2719 
2720     JSRef<JSVal> showInSubWindowValue = menuOptions->GetProperty("showInSubWindow");
2721     GetMenuShowInSubwindow(menuParam);
2722     if (menuParam.isShowInSubWindow) {
2723         if (showInSubWindowValue->IsBoolean()) {
2724             menuParam.isShowInSubWindow = showInSubWindowValue->ToBoolean();
2725         }
2726     }
2727     ParseMenuArrowParam(menuOptions, menuParam);
2728 }
2729 
ParseBindOptionParam(const JSCallbackInfo & info,NG::MenuParam & menuParam,size_t optionIndex)2730 void ParseBindOptionParam(const JSCallbackInfo& info, NG::MenuParam& menuParam, size_t optionIndex)
2731 {
2732     auto menuOptions = JSRef<JSObject>::Cast(info[optionIndex]);
2733     JSViewAbstract::ParseJsString(menuOptions->GetProperty("title"), menuParam.title);
2734     ParseMenuParam(info, menuOptions, menuParam);
2735 }
2736 
ParseAnimationScaleArray(const JSRef<JSArray> & scaleArray,NG::MenuParam & menuParam)2737 void ParseAnimationScaleArray(const JSRef<JSArray>& scaleArray, NG::MenuParam& menuParam)
2738 {
2739     constexpr int scaleArraySize = 2;
2740     if (scaleArray->Length() == scaleArraySize) {
2741         auto scalePropertyFrom = scaleArray->GetValueAt(0);
2742         if (scalePropertyFrom->IsNumber()) {
2743             auto scaleFrom = scalePropertyFrom->ToNumber<float>();
2744             menuParam.previewAnimationOptions.scaleFrom = LessOrEqual(scaleFrom, 0.0) ? -1.0f : scaleFrom;
2745         }
2746         auto scalePropertyTo = scaleArray->GetValueAt(1);
2747         if (scalePropertyTo->IsNumber()) {
2748             auto scaleTo = scalePropertyTo->ToNumber<float>();
2749             menuParam.previewAnimationOptions.scaleTo = LessOrEqual(scaleTo, 0.0) ? -1.0f : scaleTo;
2750         }
2751     }
2752 }
2753 
ParseContentPreviewAnimationOptionsParam(const JSRef<JSObject> & menuContentOptions,NG::MenuParam & menuParam)2754 void ParseContentPreviewAnimationOptionsParam(const JSRef<JSObject>& menuContentOptions, NG::MenuParam& menuParam)
2755 {
2756     menuParam.previewAnimationOptions.scaleFrom = -1.0f;
2757     menuParam.previewAnimationOptions.scaleTo = -1.0f;
2758 
2759     auto animationOptions = menuContentOptions->GetProperty("previewAnimationOptions");
2760     if (!animationOptions->IsEmpty() && animationOptions->IsObject()) {
2761         auto animationOptionsObj = JSRef<JSObject>::Cast(animationOptions);
2762         auto scaleProperty = animationOptionsObj->GetProperty("scale");
2763         if (!scaleProperty->IsEmpty() && scaleProperty->IsArray()) {
2764             JSRef<JSArray> scaleArray = JSRef<JSArray>::Cast(scaleProperty);
2765             ParseAnimationScaleArray(scaleArray, menuParam);
2766         }
2767     }
2768 }
2769 
ParseBindContentOptionParam(const JSCallbackInfo & info,const JSRef<JSVal> & args,NG::MenuParam & menuParam,std::function<void ()> & previewBuildFunc)2770 void ParseBindContentOptionParam(const JSCallbackInfo& info, const JSRef<JSVal>& args, NG::MenuParam& menuParam,
2771     std::function<void()>& previewBuildFunc)
2772 {
2773     auto menuContentOptions = JSRef<JSObject>::Cast(args);
2774     ParseMenuParam(info, menuContentOptions, menuParam);
2775     RefPtr<JsFunction> previewBuilderFunc;
2776     auto preview = menuContentOptions->GetProperty("preview");
2777     if (!preview->IsFunction() && !preview->IsNumber()) {
2778         return;
2779     }
2780 
2781     if (preview->IsNumber()) {
2782         if (preview->ToNumber<int32_t>() == 1) {
2783             menuParam.previewMode = MenuPreviewMode::IMAGE;
2784             ParseContentPreviewAnimationOptionsParam(menuContentOptions, menuParam);
2785         }
2786     } else {
2787         previewBuilderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(preview));
2788         CHECK_NULL_VOID(previewBuilderFunc);
2789         WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
2790         previewBuildFunc = [execCtx = info.GetExecutionContext(), func = std::move(previewBuilderFunc),
2791                                node = frameNode]() {
2792             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
2793             ACE_SCORING_EVENT("BuildContextMenuPreviwer");
2794             PipelineContext::SetCallBackNode(node);
2795             func->Execute();
2796         };
2797         menuParam.previewMode = MenuPreviewMode::CUSTOM;
2798         ParseContentPreviewAnimationOptionsParam(menuContentOptions, menuParam);
2799     }
2800 }
2801 
JsBindMenu(const JSCallbackInfo & info)2802 void JSViewAbstract::JsBindMenu(const JSCallbackInfo& info)
2803 {
2804     NG::MenuParam menuParam;
2805     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
2806         menuParam.placement = Placement::BOTTOM_LEFT;
2807     }
2808     size_t builderIndex = 0;
2809     GetMenuShowInSubwindow(menuParam);
2810     if (info.Length() > PARAMETER_LENGTH_FIRST) {
2811         if (info[0]->IsBoolean()) {
2812             menuParam.isShow = info[0]->ToBoolean();
2813             menuParam.setShow = true;
2814             builderIndex = 1;
2815             if (info.Length() > PARAMETER_LENGTH_SECOND) {
2816                 ParseBindOptionParam(info, menuParam, builderIndex + 1);
2817             }
2818         } else if (info[0]->IsUndefined()) {
2819             menuParam.setShow = true;
2820             menuParam.isShow = false;
2821             builderIndex = 1;
2822             if (info.Length() > PARAMETER_LENGTH_SECOND) {
2823                 ParseBindOptionParam(info, menuParam, builderIndex + 1);
2824             }
2825         } else {
2826             JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(info[0]);
2827             menuParam.onStateChange = ParseDoubleBindCallback(info, callbackObj);
2828             auto isShowObj = callbackObj->GetProperty("value");
2829             if (isShowObj->IsBoolean()) {
2830                 menuParam.isShow = isShowObj->ToBoolean();
2831                 menuParam.setShow = true;
2832                 builderIndex = 1;
2833                 if (info.Length() > PARAMETER_LENGTH_SECOND) {
2834                     ParseBindOptionParam(info, menuParam, builderIndex + 1);
2835                 }
2836             } else {
2837                 builderIndex = 0;
2838                 ParseBindOptionParam(info, menuParam, builderIndex + 1);
2839             }
2840         }
2841     }
2842     if (info[builderIndex]->IsArray()) {
2843         std::vector<NG::OptionParam> optionsParam = ParseBindOptionParam(info, builderIndex);
2844         ViewAbstractModel::GetInstance()->BindMenu(std::move(optionsParam), nullptr, menuParam);
2845     } else if (info[builderIndex]->IsObject()) {
2846         // CustomBuilder
2847         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[builderIndex]);
2848         auto builder = obj->GetProperty("builder");
2849         if (!builder->IsFunction()) {
2850             return;
2851         }
2852         auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
2853 
2854         WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
2855         CHECK_NULL_VOID(builderFunc);
2856         auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = frameNode]() {
2857             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
2858             ACE_SCORING_EVENT("BuildMenu");
2859             WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
2860             func->Execute();
2861         };
2862         ViewAbstractModel::GetInstance()->BindMenu({}, std::move(buildFunc), menuParam);
2863     }
2864 }
2865 
JsPadding(const JSCallbackInfo & info)2866 void JSViewAbstract::JsPadding(const JSCallbackInfo& info)
2867 {
2868     ParseMarginOrPadding(info, false);
2869 }
2870 
JsMargin(const JSCallbackInfo & info)2871 void JSViewAbstract::JsMargin(const JSCallbackInfo& info)
2872 {
2873     ParseMarginOrPadding(info, true);
2874 }
2875 
ParseMarginOrPadding(const JSCallbackInfo & info,bool isMargin)2876 void JSViewAbstract::ParseMarginOrPadding(const JSCallbackInfo& info, bool isMargin)
2877 {
2878     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT, JSCallbackInfoType::STRING,
2879         JSCallbackInfoType::NUMBER };
2880     if (!CheckJSCallbackInfo("MarginOrPadding", info, checkList)) {
2881         auto resetDimension = CalcDimension(0.0);
2882         if (isMargin) {
2883             ViewAbstractModel::GetInstance()->SetMargin(resetDimension);
2884         } else {
2885             ViewAbstractModel::GetInstance()->SetPadding(resetDimension);
2886         }
2887         return;
2888     }
2889     auto tmpInfo = info[0];
2890     if (tmpInfo->IsObject()) {
2891         std::optional<CalcDimension> left;
2892         std::optional<CalcDimension> right;
2893         std::optional<CalcDimension> top;
2894         std::optional<CalcDimension> bottom;
2895         JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(tmpInfo);
2896         ParseMarginOrPaddingCorner(paddingObj, top, bottom, left, right);
2897         if (left.has_value() || right.has_value() || top.has_value() || bottom.has_value()) {
2898             if (isMargin) {
2899                 ViewAbstractModel::GetInstance()->SetMargins(top, bottom, left, right);
2900             } else {
2901                 ViewAbstractModel::GetInstance()->SetPaddings(top, bottom, left, right);
2902             }
2903             return;
2904         }
2905     }
2906 
2907     CalcDimension length;
2908     if (!ParseJsDimensionVp(tmpInfo, length)) {
2909         // use default value.
2910         length.Reset();
2911     }
2912     if (isMargin) {
2913         ViewAbstractModel::GetInstance()->SetMargin(length);
2914     } else {
2915         ViewAbstractModel::GetInstance()->SetPadding(length);
2916     }
2917 }
2918 
ParseMarginOrPaddingCorner(JSRef<JSObject> obj,std::optional<CalcDimension> & top,std::optional<CalcDimension> & bottom,std::optional<CalcDimension> & left,std::optional<CalcDimension> & right)2919 void JSViewAbstract::ParseMarginOrPaddingCorner(JSRef<JSObject> obj, std::optional<CalcDimension>& top,
2920     std::optional<CalcDimension>& bottom, std::optional<CalcDimension>& left, std::optional<CalcDimension>& right)
2921 {
2922     CalcDimension leftDimen;
2923     if (ParseJsDimensionVp(obj->GetProperty("left"), leftDimen)) {
2924         left = leftDimen;
2925     }
2926     CalcDimension rightDimen;
2927     if (ParseJsDimensionVp(obj->GetProperty("right"), rightDimen)) {
2928         right = rightDimen;
2929     }
2930     CalcDimension topDimen;
2931     if (ParseJsDimensionVp(obj->GetProperty("top"), topDimen)) {
2932         top = topDimen;
2933     }
2934     CalcDimension bottomDimen;
2935     if (ParseJsDimensionVp(obj->GetProperty("bottom"), bottomDimen)) {
2936         bottom = bottomDimen;
2937     }
2938 }
2939 
JsOutline(const JSCallbackInfo & info)2940 void JSViewAbstract::JsOutline(const JSCallbackInfo& info)
2941 {
2942     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
2943     if (!CheckJSCallbackInfo("JsOutline", info, checkList)) {
2944         CalcDimension borderWidth;
2945         ViewAbstractModel::GetInstance()->SetOuterBorderWidth(borderWidth);
2946         ViewAbstractModel::GetInstance()->SetOuterBorderColor(Color::BLACK);
2947         ViewAbstractModel::GetInstance()->SetOuterBorderRadius(borderWidth);
2948         ViewAbstractModel::GetInstance()->SetOuterBorderStyle(BorderStyle::SOLID);
2949         return;
2950     }
2951     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
2952     auto valueOuterWidth = object->GetProperty("width");
2953     if (!valueOuterWidth->IsUndefined()) {
2954         ParseOuterBorderWidth(valueOuterWidth);
2955     }
2956 
2957     // use default value when undefined.
2958     ParseOuterBorderColor(object->GetProperty("color"));
2959 
2960     auto valueOuterRadius = object->GetProperty("radius");
2961     if (!valueOuterRadius->IsUndefined()) {
2962         ParseOuterBorderRadius(valueOuterRadius);
2963     }
2964     // use default value when undefined.
2965     ParseOuterBorderStyle(object->GetProperty("style"));
2966     info.ReturnSelf();
2967 }
2968 
JsOutlineWidth(const JSCallbackInfo & info)2969 void JSViewAbstract::JsOutlineWidth(const JSCallbackInfo& info)
2970 {
2971     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
2972         JSCallbackInfoType::OBJECT };
2973     if (!CheckJSCallbackInfo("JsOutlineWidth", info, checkList)) {
2974         ViewAbstractModel::GetInstance()->SetOuterBorderWidth({});
2975         return;
2976     }
2977     ParseOuterBorderWidth(info[0]);
2978 }
2979 
JsOutlineColor(const JSCallbackInfo & info)2980 void JSViewAbstract::JsOutlineColor(const JSCallbackInfo& info)
2981 {
2982     ParseOuterBorderColor(info[0]);
2983 }
2984 
JsOutlineRadius(const JSCallbackInfo & info)2985 void JSViewAbstract::JsOutlineRadius(const JSCallbackInfo& info)
2986 {
2987     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
2988         JSCallbackInfoType::OBJECT };
2989     if (!CheckJSCallbackInfo("JsOutlineRadius", info, checkList)) {
2990         ViewAbstractModel::GetInstance()->SetOuterBorderRadius({});
2991         return;
2992     }
2993     ParseOuterBorderRadius(info[0]);
2994 }
2995 
JsOutlineStyle(const JSCallbackInfo & info)2996 void JSViewAbstract::JsOutlineStyle(const JSCallbackInfo& info)
2997 {
2998     ParseOuterBorderStyle(info[0]);
2999 }
3000 
JsBorder(const JSCallbackInfo & info)3001 void JSViewAbstract::JsBorder(const JSCallbackInfo& info)
3002 {
3003     if (!info[0]->IsObject()) {
3004         CalcDimension borderWidth;
3005         ViewAbstractModel::GetInstance()->SetBorderWidth(borderWidth);
3006         ViewAbstractModel::GetInstance()->SetBorderColor(Color::BLACK);
3007         ViewAbstractModel::GetInstance()->SetBorderRadius(borderWidth);
3008         ViewAbstractModel::GetInstance()->SetBorderStyle(BorderStyle::SOLID);
3009         return;
3010     }
3011     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
3012 
3013     auto valueWidth = object->GetProperty("width");
3014     if (!valueWidth->IsUndefined()) {
3015         ParseBorderWidth(valueWidth);
3016     }
3017 
3018     // use default value when undefined.
3019     ParseBorderColor(object->GetProperty("color"));
3020 
3021     auto valueRadius = object->GetProperty("radius");
3022     if (!valueRadius->IsUndefined()) {
3023         ParseBorderRadius(valueRadius);
3024     }
3025     // use default value when undefined.
3026     ParseBorderStyle(object->GetProperty("style"));
3027 
3028     info.ReturnSelf();
3029 }
3030 
JsBorderWidth(const JSCallbackInfo & info)3031 void JSViewAbstract::JsBorderWidth(const JSCallbackInfo& info)
3032 {
3033     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
3034         JSCallbackInfoType::OBJECT };
3035     if (!CheckJSCallbackInfo("JsBorderWidth", info, checkList)) {
3036         ViewAbstractModel::GetInstance()->SetBorderWidth({});
3037         return;
3038     }
3039     ParseBorderWidth(info[0]);
3040 }
3041 
ParseBorderWidth(const JSRef<JSVal> & args)3042 void JSViewAbstract::ParseBorderWidth(const JSRef<JSVal>& args)
3043 {
3044     CalcDimension borderWidth;
3045     if (ParseJsDimensionVp(args, borderWidth)) {
3046         if (borderWidth.IsNegative()) {
3047             borderWidth.Reset();
3048         }
3049         if (borderWidth.Unit() == DimensionUnit::PERCENT) {
3050             borderWidth.Reset();
3051         }
3052         ViewAbstractModel::GetInstance()->SetBorderWidth(borderWidth);
3053     } else if (args->IsObject()) {
3054         std::optional<CalcDimension> leftDimen;
3055         std::optional<CalcDimension> rightDimen;
3056         std::optional<CalcDimension> topDimen;
3057         std::optional<CalcDimension> bottomDimen;
3058         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3059         CalcDimension left;
3060         if (ParseJsDimensionVp(object->GetProperty("left"), left)) {
3061             if (left.Unit() == DimensionUnit::PERCENT || left.IsNegative()) {
3062                 left.Reset();
3063             }
3064             leftDimen = left;
3065         }
3066         CalcDimension right;
3067         if (ParseJsDimensionVp(object->GetProperty("right"), right)) {
3068             if (right.Unit() == DimensionUnit::PERCENT || right.IsNegative()) {
3069                 right.Reset();
3070             }
3071             rightDimen = right;
3072         }
3073         CalcDimension top;
3074         if (ParseJsDimensionVp(object->GetProperty("top"), top)) {
3075             if (top.Unit() == DimensionUnit::PERCENT || top.IsNegative()) {
3076                 top.Reset();
3077             }
3078             topDimen = top;
3079         }
3080         CalcDimension bottom;
3081         if (ParseJsDimensionVp(object->GetProperty("bottom"), bottom)) {
3082             if (bottom.Unit() == DimensionUnit::PERCENT || bottom.IsNegative()) {
3083                 bottom.Reset();
3084             }
3085             bottomDimen = bottom;
3086         }
3087         ViewAbstractModel::GetInstance()->SetBorderWidth(leftDimen, rightDimen, topDimen, bottomDimen);
3088     } else {
3089         return;
3090     }
3091 }
3092 
ParseOuterBorderWidth(const JSRef<JSVal> & args)3093 void JSViewAbstract::ParseOuterBorderWidth(const JSRef<JSVal>& args)
3094 {
3095     CalcDimension borderWidth;
3096     if (ParseJsDimensionVp(args, borderWidth)) {
3097         if (borderWidth.IsNegative() || borderWidth.Unit() == DimensionUnit::PERCENT) {
3098             borderWidth.Reset();
3099         }
3100         ViewAbstractModel::GetInstance()->SetOuterBorderWidth(borderWidth);
3101     } else if (args->IsObject()) {
3102         std::optional<CalcDimension> leftDimen;
3103         std::optional<CalcDimension> rightDimen;
3104         std::optional<CalcDimension> topDimen;
3105         std::optional<CalcDimension> bottomDimen;
3106         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3107         CalcDimension left;
3108         if (ParseJsDimensionVp(object->GetProperty("left"), left) && left.IsNonNegative()) {
3109             if (left.Unit() == DimensionUnit::PERCENT) {
3110                 left.Reset();
3111             }
3112             leftDimen = left;
3113         }
3114         CalcDimension right;
3115         if (ParseJsDimensionVp(object->GetProperty("right"), right) && right.IsNonNegative()) {
3116             if (right.Unit() == DimensionUnit::PERCENT) {
3117                 right.Reset();
3118             }
3119             rightDimen = right;
3120         }
3121         CalcDimension top;
3122         if (ParseJsDimensionVp(object->GetProperty("top"), top) && top.IsNonNegative()) {
3123             if (top.Unit() == DimensionUnit::PERCENT) {
3124                 top.Reset();
3125             }
3126             topDimen = top;
3127         }
3128         CalcDimension bottom;
3129         if (ParseJsDimensionVp(object->GetProperty("bottom"), bottom) && bottom.IsNonNegative()) {
3130             if (bottom.Unit() == DimensionUnit::PERCENT) {
3131                 bottom.Reset();
3132             }
3133             bottomDimen = bottom;
3134         }
3135         ViewAbstractModel::GetInstance()->SetOuterBorderWidth(leftDimen, rightDimen, topDimen, bottomDimen);
3136     } else {
3137         return;
3138     }
3139 }
3140 
ParseMenuOptions(const JSCallbackInfo & info,const JSRef<JSArray> & jsArray,std::vector<NG::MenuOptionsParam> & items)3141 void JSViewAbstract::ParseMenuOptions(
3142     const JSCallbackInfo& info, const JSRef<JSArray>& jsArray, std::vector<NG::MenuOptionsParam>& items)
3143 {
3144     auto length = jsArray->Length();
3145     for (size_t i = 0; i < length; i++) {
3146         auto item = jsArray->GetValueAt(i);
3147         if (!item->IsObject()) {
3148             continue;
3149         }
3150         auto itemObject = JSRef<JSObject>::Cast(item);
3151         NG::MenuOptionsParam menuOptionItem;
3152         std::string value;
3153         std::string icon;
3154         auto menuOptionsValue = itemObject->GetProperty("content");
3155         auto menuOptionsIcon = itemObject->GetProperty("icon");
3156 
3157         if (!ParseJsString(menuOptionsValue, value)) {
3158             return;
3159         }
3160         ParseJsMedia(menuOptionsIcon, icon);
3161         menuOptionItem.content = value;
3162         menuOptionItem.icon = icon;
3163 
3164         auto itemActionValue = itemObject->GetProperty("action");
3165         if (itemActionValue->IsFunction()) {
3166             JsEventCallback<void(const std::string&)> callback(
3167                 info.GetExecutionContext(), JSRef<JSFunc>::Cast(itemActionValue));
3168             menuOptionItem.action = callback;
3169         }
3170         items.emplace_back(menuOptionItem);
3171     }
3172 }
3173 
JsBorderImage(const JSCallbackInfo & info)3174 void JSViewAbstract::JsBorderImage(const JSCallbackInfo& info)
3175 {
3176     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
3177     if (!CheckJSCallbackInfo("JsBorderImage", info, checkList)) {
3178         RefPtr<BorderImage> borderImage = AceType::MakeRefPtr<BorderImage>();
3179         uint8_t imageBorderBitsets = 0;
3180         ViewAbstractModel::GetInstance()->SetBorderImage(borderImage, imageBorderBitsets);
3181         return;
3182     }
3183     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
3184     if (object->IsEmpty()) {
3185         return;
3186     }
3187 
3188     RefPtr<BorderImage> borderImage = AceType::MakeRefPtr<BorderImage>();
3189     uint8_t imageBorderBitsets = 0;
3190 
3191     auto valueSource = object->GetProperty("source");
3192     if (!valueSource->IsString() && !valueSource->IsObject()) {
3193         return;
3194     }
3195     std::string srcResult;
3196     if (valueSource->IsString()) {
3197         srcResult = valueSource->ToString();
3198         if (!srcResult.empty()) {
3199             borderImage->SetSrc(srcResult);
3200             imageBorderBitsets |= BorderImage::SOURCE_BIT;
3201         }
3202     } else if (valueSource->IsObject()) {
3203         if (ParseJsMedia(valueSource, srcResult)) {
3204             borderImage->SetSrc(srcResult);
3205             imageBorderBitsets |= BorderImage::SOURCE_BIT;
3206         } else {
3207             ParseBorderImageLinearGradient(valueSource, imageBorderBitsets);
3208         }
3209     }
3210     auto valueOutset = object->GetProperty("outset");
3211     if (valueOutset->IsNumber() || valueOutset->IsString() || valueOutset->IsObject()) {
3212         imageBorderBitsets |= BorderImage::OUTSET_BIT;
3213         ParseBorderImageOutset(valueOutset, borderImage);
3214     }
3215     auto valueRepeat = object->GetProperty("repeat");
3216     if (!valueRepeat->IsNull()) {
3217         imageBorderBitsets |= BorderImage::REPEAT_BIT;
3218         ParseBorderImageRepeat(valueRepeat, borderImage);
3219     }
3220     auto valueSlice = object->GetProperty("slice");
3221     if (valueSlice->IsNumber() || valueSlice->IsString() || valueSlice->IsObject()) {
3222         imageBorderBitsets |= BorderImage::SLICE_BIT;
3223         ParseBorderImageSlice(valueSlice, borderImage);
3224     }
3225     auto valueWidth = object->GetProperty("width");
3226     if (valueWidth->IsNumber() || valueWidth->IsString() || valueWidth->IsObject()) {
3227         imageBorderBitsets |= BorderImage::WIDTH_BIT;
3228         ParseBorderImageWidth(valueWidth, borderImage);
3229     }
3230     auto needFill = object->GetProperty("fill");
3231     if (needFill->IsBoolean()) {
3232         borderImage->SetNeedFillCenter(needFill->ToBoolean());
3233     }
3234     ViewAbstractModel::GetInstance()->SetBorderImage(borderImage, imageBorderBitsets);
3235     info.ReturnSelf();
3236 }
3237 
ParseBorderImageDimension(const JSRef<JSVal> & args,BorderImage::BorderImageOption & borderImageDimension)3238 void JSViewAbstract::ParseBorderImageDimension(
3239     const JSRef<JSVal>& args, BorderImage::BorderImageOption& borderImageDimension)
3240 {
3241     JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3242     static std::array<std::string, 4> keys = { "left", "right", "top", "bottom" };
3243     for (uint32_t i = 0; i < keys.size(); i++) {
3244         CalcDimension currentDimension;
3245         auto dimensionValue = object->GetProperty(keys.at(i).c_str());
3246         if (ParseJsDimensionVp(dimensionValue, currentDimension)) {
3247             auto direction = static_cast<BorderImageDirection>(i);
3248             switch (direction) {
3249                 case BorderImageDirection::LEFT:
3250                     borderImageDimension.leftDimension = currentDimension;
3251                     break;
3252                 case BorderImageDirection::RIGHT:
3253                     borderImageDimension.rightDimension = currentDimension;
3254                     break;
3255                 case BorderImageDirection::TOP:
3256                     borderImageDimension.topDimension = currentDimension;
3257                     break;
3258                 case BorderImageDirection::BOTTOM:
3259                     borderImageDimension.bottomDimension = currentDimension;
3260                     break;
3261                 default:
3262                     break;
3263             }
3264         }
3265     }
3266 }
3267 
ParseBorderImageLinearGradient(const JSRef<JSVal> & args,uint8_t & bitset)3268 void JSViewAbstract::ParseBorderImageLinearGradient(const JSRef<JSVal>& args, uint8_t& bitset)
3269 {
3270     if (!args->IsObject()) {
3271         return;
3272     }
3273     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(args);
3274     NG::Gradient lineGradient;
3275     lineGradient.CreateGradientWithType(NG::GradientType::LINEAR);
3276     // angle
3277     std::optional<float> degree;
3278     GetJsAngle("angle", jsObj, degree);
3279     if (degree) {
3280         lineGradient.GetLinearGradient()->angle = CalcDimension(degree.value(), DimensionUnit::PX);
3281         degree.reset();
3282     }
3283     // direction
3284     auto direction = static_cast<NG::GradientDirection>(
3285         jsObj->GetPropertyValue<int32_t>("direction", static_cast<int32_t>(NG::GradientDirection::NONE)));
3286     switch (direction) {
3287         case NG::GradientDirection::LEFT:
3288             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
3289             break;
3290         case NG::GradientDirection::RIGHT:
3291             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
3292             break;
3293         case NG::GradientDirection::TOP:
3294             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
3295             break;
3296         case NG::GradientDirection::BOTTOM:
3297             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
3298             break;
3299         case NG::GradientDirection::LEFT_TOP:
3300             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
3301             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
3302             break;
3303         case NG::GradientDirection::LEFT_BOTTOM:
3304             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
3305             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
3306             break;
3307         case NG::GradientDirection::RIGHT_TOP:
3308             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
3309             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
3310             break;
3311         case NG::GradientDirection::RIGHT_BOTTOM:
3312             lineGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
3313             lineGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
3314             break;
3315         case NG::GradientDirection::NONE:
3316         case NG::GradientDirection::START_TO_END:
3317         case NG::GradientDirection::END_TO_START:
3318         default:
3319             break;
3320     }
3321     auto repeating = jsObj->GetPropertyValue<bool>("repeating", false);
3322     lineGradient.SetRepeat(repeating);
3323     NewGetJsGradientColorStops(lineGradient, jsObj->GetProperty("colors"));
3324     ViewAbstractModel::GetInstance()->SetBorderImageGradient(lineGradient);
3325     bitset |= BorderImage::GRADIENT_BIT;
3326 }
3327 
ParseBorderImageRepeat(const JSRef<JSVal> & args,RefPtr<BorderImage> & borderImage)3328 void JSViewAbstract::ParseBorderImageRepeat(const JSRef<JSVal>& args, RefPtr<BorderImage>& borderImage)
3329 {
3330     auto repeatString = args->ToString();
3331     if (repeatString == "Repeat") {
3332         borderImage->SetRepeatMode(BorderImageRepeat::REPEAT);
3333     } else if (repeatString == "Round") {
3334         borderImage->SetRepeatMode(BorderImageRepeat::ROUND);
3335     } else if (repeatString == "Space") {
3336         borderImage->SetRepeatMode(BorderImageRepeat::SPACE);
3337     } else {
3338         borderImage->SetRepeatMode(BorderImageRepeat::STRETCH);
3339     }
3340 }
3341 
ParseBorderImageOutset(const JSRef<JSVal> & args,RefPtr<BorderImage> & borderImage)3342 void JSViewAbstract::ParseBorderImageOutset(const JSRef<JSVal>& args, RefPtr<BorderImage>& borderImage)
3343 {
3344     CalcDimension outsetDimension;
3345     if (ParseJsDimensionVp(args, outsetDimension)) {
3346         borderImage->SetEdgeOutset(BorderImageDirection::LEFT, outsetDimension);
3347         borderImage->SetEdgeOutset(BorderImageDirection::RIGHT, outsetDimension);
3348         borderImage->SetEdgeOutset(BorderImageDirection::TOP, outsetDimension);
3349         borderImage->SetEdgeOutset(BorderImageDirection::BOTTOM, outsetDimension);
3350         return;
3351     }
3352     BorderImage::BorderImageOption option;
3353     ParseBorderImageDimension(args, option);
3354     if (option.leftDimension.has_value()) {
3355         borderImage->SetEdgeOutset(BorderImageDirection::LEFT, option.leftDimension.value());
3356     }
3357     if (option.rightDimension.has_value()) {
3358         borderImage->SetEdgeOutset(BorderImageDirection::RIGHT, option.rightDimension.value());
3359     }
3360     if (option.topDimension.has_value()) {
3361         borderImage->SetEdgeOutset(BorderImageDirection::TOP, option.topDimension.value());
3362     }
3363     if (option.bottomDimension.has_value()) {
3364         borderImage->SetEdgeOutset(BorderImageDirection::BOTTOM, option.bottomDimension.value());
3365     }
3366 }
3367 
ParseBorderImageSlice(const JSRef<JSVal> & args,RefPtr<BorderImage> & borderImage)3368 void JSViewAbstract::ParseBorderImageSlice(const JSRef<JSVal>& args, RefPtr<BorderImage>& borderImage)
3369 {
3370     CalcDimension sliceDimension;
3371     if (ParseJsDimensionVp(args, sliceDimension)) {
3372         borderImage->SetEdgeSlice(BorderImageDirection::LEFT, sliceDimension);
3373         borderImage->SetEdgeSlice(BorderImageDirection::RIGHT, sliceDimension);
3374         borderImage->SetEdgeSlice(BorderImageDirection::TOP, sliceDimension);
3375         borderImage->SetEdgeSlice(BorderImageDirection::BOTTOM, sliceDimension);
3376         return;
3377     }
3378 
3379     JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3380     static std::array<std::string, 4> keys = { "left", "right", "top", "bottom" };
3381     for (uint32_t i = 0; i < keys.size(); i++) {
3382         auto dimensionValue = object->GetProperty(keys.at(i).c_str());
3383         if (ParseJsDimensionVp(dimensionValue, sliceDimension)) {
3384             borderImage->SetEdgeSlice(static_cast<BorderImageDirection>(i), sliceDimension);
3385         }
3386     }
3387 }
3388 
ParseBorderImageWidth(const JSRef<JSVal> & args,RefPtr<BorderImage> & borderImage)3389 void JSViewAbstract::ParseBorderImageWidth(const JSRef<JSVal>& args, RefPtr<BorderImage>& borderImage)
3390 {
3391     CalcDimension widthDimension;
3392     if (ParseJsDimensionVp(args, widthDimension)) {
3393         borderImage->SetEdgeWidth(BorderImageDirection::LEFT, widthDimension);
3394         borderImage->SetEdgeWidth(BorderImageDirection::RIGHT, widthDimension);
3395         borderImage->SetEdgeWidth(BorderImageDirection::TOP, widthDimension);
3396         borderImage->SetEdgeWidth(BorderImageDirection::BOTTOM, widthDimension);
3397         return;
3398     }
3399 
3400     BorderImage::BorderImageOption option;
3401     ParseBorderImageDimension(args, option);
3402     if (option.leftDimension.has_value()) {
3403         borderImage->SetEdgeWidth(BorderImageDirection::LEFT, option.leftDimension.value());
3404     }
3405     if (option.rightDimension.has_value()) {
3406         borderImage->SetEdgeWidth(BorderImageDirection::RIGHT, option.rightDimension.value());
3407     }
3408     if (option.topDimension.has_value()) {
3409         borderImage->SetEdgeWidth(BorderImageDirection::TOP, option.topDimension.value());
3410     }
3411     if (option.bottomDimension.has_value()) {
3412         borderImage->SetEdgeWidth(BorderImageDirection::BOTTOM, option.bottomDimension.value());
3413     }
3414 }
3415 
JsBorderColor(const JSCallbackInfo & info)3416 void JSViewAbstract::JsBorderColor(const JSCallbackInfo& info)
3417 {
3418     ParseBorderColor(info[0]);
3419 }
3420 
ParseBorderColor(const JSRef<JSVal> & args)3421 void JSViewAbstract::ParseBorderColor(const JSRef<JSVal>& args)
3422 {
3423     Color borderColor;
3424     if (ParseJsColor(args, borderColor)) {
3425         ViewAbstractModel::GetInstance()->SetBorderColor(borderColor);
3426     } else if (args->IsObject()) {
3427         std::optional<Color> leftColor;
3428         std::optional<Color> rightColor;
3429         std::optional<Color> topColor;
3430         std::optional<Color> bottomColor;
3431         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3432         Color left;
3433         if (ParseJsColor(object->GetProperty("left"), left)) {
3434             leftColor = left;
3435         }
3436         Color right;
3437         if (ParseJsColor(object->GetProperty("right"), right)) {
3438             rightColor = right;
3439         }
3440         Color top;
3441         if (ParseJsColor(object->GetProperty("top"), top)) {
3442             topColor = top;
3443         }
3444         Color bottom;
3445         if (ParseJsColor(object->GetProperty("bottom"), bottom)) {
3446             bottomColor = bottom;
3447         }
3448 
3449         ViewAbstractModel::GetInstance()->SetBorderColor(leftColor, rightColor, topColor, bottomColor);
3450     } else {
3451         ViewAbstractModel::GetInstance()->SetBorderColor(Color::BLACK);
3452     }
3453 }
3454 
ParseOuterBorderColor(const JSRef<JSVal> & args)3455 void JSViewAbstract::ParseOuterBorderColor(const JSRef<JSVal>& args)
3456 {
3457     Color borderColor;
3458     if (ParseJsColor(args, borderColor)) {
3459         ViewAbstractModel::GetInstance()->SetOuterBorderColor(borderColor);
3460     } else if (args->IsObject()) {
3461         std::optional<Color> leftColor;
3462         std::optional<Color> rightColor;
3463         std::optional<Color> topColor;
3464         std::optional<Color> bottomColor;
3465         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3466         Color left;
3467         if (ParseJsColor(object->GetProperty("left"), left)) {
3468             leftColor = left;
3469         }
3470         Color right;
3471         if (ParseJsColor(object->GetProperty("right"), right)) {
3472             rightColor = right;
3473         }
3474         Color top;
3475         if (ParseJsColor(object->GetProperty("top"), top)) {
3476             topColor = top;
3477         }
3478         Color bottom;
3479         if (ParseJsColor(object->GetProperty("bottom"), bottom)) {
3480             bottomColor = bottom;
3481         }
3482 
3483         ViewAbstractModel::GetInstance()->SetOuterBorderColor(leftColor, rightColor, topColor, bottomColor);
3484     } else {
3485         ViewAbstractModel::GetInstance()->SetOuterBorderColor(Color::BLACK);
3486     }
3487 }
3488 
JsBorderRadius(const JSCallbackInfo & info)3489 void JSViewAbstract::JsBorderRadius(const JSCallbackInfo& info)
3490 {
3491     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING, JSCallbackInfoType::NUMBER,
3492         JSCallbackInfoType::OBJECT };
3493     if (!CheckJSCallbackInfo("JsBorderRadius", info, checkList)) {
3494         ViewAbstractModel::GetInstance()->SetBorderRadius({});
3495         return;
3496     }
3497     ParseBorderRadius(info[0]);
3498 }
3499 
ParseBorderRadius(const JSRef<JSVal> & args)3500 void JSViewAbstract::ParseBorderRadius(const JSRef<JSVal>& args)
3501 {
3502     CalcDimension borderRadius;
3503     if (ParseJsDimensionVp(args, borderRadius)) {
3504         if (borderRadius.Unit() == DimensionUnit::PERCENT) {
3505             borderRadius.Reset();
3506         }
3507         ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius);
3508     } else if (args->IsObject()) {
3509         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3510         CalcDimension topLeft;
3511         CalcDimension topRight;
3512         CalcDimension bottomLeft;
3513         CalcDimension bottomRight;
3514         ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight);
3515         ViewAbstractModel::GetInstance()->SetBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
3516     }
3517 }
3518 
ParseOuterBorderRadius(const JSRef<JSVal> & args)3519 void JSViewAbstract::ParseOuterBorderRadius(const JSRef<JSVal>& args)
3520 {
3521     if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
3522         return;
3523     }
3524     CalcDimension borderRadius;
3525     if (ParseJsDimensionVp(args, borderRadius)) {
3526         if (borderRadius.Unit() == DimensionUnit::PERCENT) {
3527             borderRadius.Reset();
3528         }
3529         ViewAbstractModel::GetInstance()->SetOuterBorderRadius(borderRadius);
3530     } else if (args->IsObject()) {
3531         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3532         CalcDimension topLeft;
3533         CalcDimension topRight;
3534         CalcDimension bottomLeft;
3535         CalcDimension bottomRight;
3536         ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight);
3537         ViewAbstractModel::GetInstance()->SetOuterBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
3538     }
3539 }
3540 
GetBorderRadius(const char * key,JSRef<JSObject> & object,CalcDimension & radius)3541 void JSViewAbstract::GetBorderRadius(const char* key, JSRef<JSObject>& object, CalcDimension& radius)
3542 {
3543     if (ParseJsDimensionVp(object->GetProperty(key), radius)) {
3544         if ((radius.Unit() == DimensionUnit::PERCENT)) {
3545             radius.Reset();
3546         }
3547     }
3548 }
3549 
ParseAllBorderRadiuses(JSRef<JSObject> & object,CalcDimension & topLeft,CalcDimension & topRight,CalcDimension & bottomLeft,CalcDimension & bottomRight)3550 void JSViewAbstract::ParseAllBorderRadiuses(JSRef<JSObject>& object, CalcDimension& topLeft, CalcDimension& topRight,
3551     CalcDimension& bottomLeft, CalcDimension& bottomRight)
3552 {
3553     GetBorderRadius("topLeft", object, topLeft);
3554     GetBorderRadius("topRight", object, topRight);
3555     GetBorderRadius("bottomLeft", object, bottomLeft);
3556     GetBorderRadius("bottomRight", object, bottomRight);
3557 }
3558 
JsBorderStyle(const JSCallbackInfo & info)3559 void JSViewAbstract::JsBorderStyle(const JSCallbackInfo& info)
3560 {
3561     ParseBorderStyle(info[0]);
3562 }
3563 namespace {
ConvertBorderStyle(int32_t value)3564 BorderStyle ConvertBorderStyle(int32_t value)
3565 {
3566     auto style = static_cast<BorderStyle>(value);
3567     if (style < BorderStyle::SOLID || style > BorderStyle::NONE) {
3568         style = BorderStyle::SOLID;
3569     }
3570     return style;
3571 }
3572 } // namespace
3573 
ParseBorderStyle(const JSRef<JSVal> & args)3574 void JSViewAbstract::ParseBorderStyle(const JSRef<JSVal>& args)
3575 {
3576     if (args->IsObject()) {
3577         std::optional<BorderStyle> styleLeft;
3578         std::optional<BorderStyle> styleRight;
3579         std::optional<BorderStyle> styleTop;
3580         std::optional<BorderStyle> styleBottom;
3581         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3582         auto leftValue = object->GetProperty("left");
3583         if (leftValue->IsNumber()) {
3584             styleLeft = ConvertBorderStyle(leftValue->ToNumber<int32_t>());
3585         }
3586         auto rightValue = object->GetProperty("right");
3587         if (rightValue->IsNumber()) {
3588             styleRight = ConvertBorderStyle(rightValue->ToNumber<int32_t>());
3589         }
3590         auto topValue = object->GetProperty("top");
3591         if (topValue->IsNumber()) {
3592             styleTop = ConvertBorderStyle(topValue->ToNumber<int32_t>());
3593         }
3594         auto bottomValue = object->GetProperty("bottom");
3595         if (bottomValue->IsNumber()) {
3596             styleBottom = ConvertBorderStyle(bottomValue->ToNumber<int32_t>());
3597         }
3598         ViewAbstractModel::GetInstance()->SetBorderStyle(styleLeft, styleRight, styleTop, styleBottom);
3599         return;
3600     }
3601     if (args->IsNumber()) {
3602         auto borderStyle = ConvertBorderStyle(args->ToNumber<int32_t>());
3603         ViewAbstractModel::GetInstance()->SetBorderStyle(borderStyle);
3604         return;
3605     }
3606     ViewAbstractModel::GetInstance()->SetBorderStyle(BorderStyle::SOLID);
3607 }
3608 
ParseOuterBorderStyle(const JSRef<JSVal> & args)3609 void JSViewAbstract::ParseOuterBorderStyle(const JSRef<JSVal>& args)
3610 {
3611     if (!args->IsObject() && !args->IsNumber()) {
3612         ViewAbstractModel::GetInstance()->SetOuterBorderStyle(BorderStyle::SOLID);
3613         return;
3614     }
3615     if (args->IsObject()) {
3616         std::optional<BorderStyle> styleLeft;
3617         std::optional<BorderStyle> styleRight;
3618         std::optional<BorderStyle> styleTop;
3619         std::optional<BorderStyle> styleBottom;
3620         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
3621         auto leftValue = object->GetProperty("left");
3622         if (!leftValue->IsUndefined() && leftValue->IsNumber()) {
3623             styleLeft = ConvertBorderStyle(leftValue->ToNumber<int32_t>());
3624         }
3625         auto rightValue = object->GetProperty("right");
3626         if (!rightValue->IsUndefined() && rightValue->IsNumber()) {
3627             styleRight = ConvertBorderStyle(rightValue->ToNumber<int32_t>());
3628         }
3629         auto topValue = object->GetProperty("top");
3630         if (!topValue->IsUndefined() && topValue->IsNumber()) {
3631             styleTop = ConvertBorderStyle(topValue->ToNumber<int32_t>());
3632         }
3633         auto bottomValue = object->GetProperty("bottom");
3634         if (!bottomValue->IsUndefined() && bottomValue->IsNumber()) {
3635             styleBottom = ConvertBorderStyle(bottomValue->ToNumber<int32_t>());
3636         }
3637         ViewAbstractModel::GetInstance()->SetOuterBorderStyle(styleLeft, styleRight, styleTop, styleBottom);
3638         return;
3639     }
3640     auto borderStyle = ConvertBorderStyle(args->ToNumber<int32_t>());
3641     ViewAbstractModel::GetInstance()->SetOuterBorderStyle(borderStyle);
3642 }
3643 
JsBlur(const JSCallbackInfo & info)3644 void JSViewAbstract::JsBlur(const JSCallbackInfo& info)
3645 {
3646     if (info.Length() == 0) {
3647         return;
3648     }
3649     double blur = 0.0;
3650     if (!ParseJsDouble(info[0], blur)) {
3651         return;
3652     }
3653 
3654     BlurOption blurOption;
3655     if (info.Length() > 1 && info[1]->IsObject()) {
3656         JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(info[1]);
3657         ParseBlurOption(jsBlurOption, blurOption);
3658     }
3659     CalcDimension dimensionRadius(blur, DimensionUnit::PX);
3660     ViewAbstractModel::GetInstance()->SetFrontBlur(dimensionRadius, blurOption);
3661     info.SetReturnValue(info.This());
3662 }
3663 
JsColorBlend(const JSCallbackInfo & info)3664 void JSViewAbstract::JsColorBlend(const JSCallbackInfo& info)
3665 {
3666     Color colorBlend;
3667     if (info[0]->IsUndefined()) {
3668         colorBlend = Color::TRANSPARENT;
3669         SetColorBlend(colorBlend);
3670         return;
3671     }
3672     if (!ParseJsColor(info[0], colorBlend)) {
3673         return;
3674     }
3675     SetColorBlend(colorBlend);
3676     info.SetReturnValue(info.This());
3677 }
3678 
JsUseEffect(const JSCallbackInfo & info)3679 void JSViewAbstract::JsUseEffect(const JSCallbackInfo& info)
3680 {
3681     if (info[0]->IsBoolean()) {
3682         ViewAbstractModel::GetInstance()->SetUseEffect(info[0]->ToBoolean());
3683     }
3684 }
3685 
JsUseShadowBatching(const JSCallbackInfo & info)3686 void JSViewAbstract::JsUseShadowBatching(const JSCallbackInfo& info)
3687 {
3688     if (info[0]->IsBoolean()) {
3689         ViewAbstractModel::GetInstance()->SetUseShadowBatching(info[0]->ToBoolean());
3690     }
3691 }
3692 
JsBackdropBlur(const JSCallbackInfo & info)3693 void JSViewAbstract::JsBackdropBlur(const JSCallbackInfo& info)
3694 {
3695     if (info.Length() == 0) {
3696         return;
3697     }
3698     double blur = 0.0;
3699     if (!ParseJsDouble(info[0], blur)) {
3700         return;
3701     }
3702     BlurOption blurOption;
3703     if (info.Length() > 1 && info[1]->IsObject()) {
3704         JSRef<JSObject> jsBlurOption = JSRef<JSObject>::Cast(info[1]);
3705         ParseBlurOption(jsBlurOption, blurOption);
3706     }
3707     CalcDimension dimensionRadius(blur, DimensionUnit::PX);
3708     ViewAbstractModel::GetInstance()->SetBackdropBlur(dimensionRadius, blurOption);
3709 
3710     info.SetReturnValue(info.This());
3711 }
3712 
GetFractionStops(std::vector<std::pair<float,float>> & fractionStops,const JSRef<JSVal> & array)3713 void JSViewAbstract::GetFractionStops(
3714     std::vector<std::pair<float, float>>& fractionStops, const JSRef<JSVal>& array)
3715 {
3716     if (!array->IsArray() || JSRef<JSArray>::Cast(array)->Length() <= 1) {
3717         return;
3718     }
3719     JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(array);
3720     float tmpPos = -1.0f;
3721     size_t length = jsArray->Length();
3722     for (size_t i = 0; i < length; i++) {
3723         std::pair<float, float> fractionStop;
3724         JSRef<JSVal> item = jsArray->GetValueAt(i);
3725         if (!item->IsArray()) {
3726             continue;
3727         }
3728         JSRef<JSArray> subArray = JSRef<JSArray>::Cast(item);
3729         if (subArray->Length() < 2) {
3730             continue;
3731         }
3732 
3733         double value = 0.0;
3734         if (ParseJsDouble(subArray->GetValueAt(0), value)) {
3735             value = std::clamp(value, 0.0, 1.0);
3736             fractionStop.first = static_cast<float>(value);
3737         }
3738         value = 0.0;
3739         if (ParseJsDouble(subArray->GetValueAt(1), value)) {
3740             value = std::clamp(value, 0.0, 1.0);
3741             fractionStop.second = static_cast<float>(value);
3742         }
3743 
3744         if (fractionStop.second <= tmpPos) {
3745             fractionStops.clear();
3746             return;
3747         }
3748         tmpPos = fractionStop.second;
3749         fractionStops.push_back(fractionStop);
3750     }
3751 }
JsLinearGradientBlur(const JSCallbackInfo & info)3752 void JSViewAbstract::JsLinearGradientBlur(const JSCallbackInfo& info)
3753 {
3754     if (info.Length() < 2) { // 2 represents the least para num;
3755         return;
3756     }
3757     double blurRadius = 0.0;
3758     ParseJsDouble(info[0], blurRadius);
3759 
3760     std::vector<std::pair<float, float>> fractionStops;
3761     auto direction = GradientDirection::BOTTOM;
3762     if (info[1]->IsObject()) {
3763         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[1]);
3764         GetFractionStops(fractionStops, jsObj->GetProperty("fractionStops"));
3765         auto directionValue =
3766             jsObj->GetPropertyValue<int8_t>("direction", static_cast<int8_t>(GradientDirection::BOTTOM));
3767         if (directionValue < static_cast<int8_t>(GradientDirection::LEFT) ||
3768             directionValue >= static_cast<int8_t>(GradientDirection::NONE)) {
3769             directionValue = static_cast<int8_t>(GradientDirection::BOTTOM);
3770         }
3771         direction = static_cast<GradientDirection>(directionValue);
3772     }
3773     if (static_cast<int32_t>(fractionStops.size()) <= 1) {
3774         fractionStops.clear();
3775         fractionStops.push_back(std::pair<float, float>(0.0f, 0.0f));
3776         fractionStops.push_back(std::pair<float, float>(0.0f, 1.0f));
3777     }
3778     // Parse direction
3779     CalcDimension dimensionRadius(static_cast<float>(blurRadius), DimensionUnit::PX);
3780     NG::LinearGradientBlurPara blurPara(dimensionRadius, fractionStops, static_cast<NG::GradientDirection>(direction));
3781     SetLinearGradientBlur(blurPara);
3782 }
3783 
JsBackgroundBrightness(const JSCallbackInfo & info)3784 void JSViewAbstract::JsBackgroundBrightness(const JSCallbackInfo& info)
3785 {
3786     double rate = 0.0;
3787     double lightUpDegree = 0.0;
3788     if (info[0]->IsObject()) {
3789         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
3790         ParseJsDouble(jsObj->GetProperty("rate"), rate);
3791         ParseJsDouble(jsObj->GetProperty("lightUpDegree"), lightUpDegree);
3792     }
3793     SetDynamicLightUp(rate, lightUpDegree);
3794 }
3795 
JsWindowBlur(const JSCallbackInfo & info)3796 void JSViewAbstract::JsWindowBlur(const JSCallbackInfo& info)
3797 {
3798     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
3799     if (!CheckJSCallbackInfo("JsWindowBlur", info, checkList)) {
3800         return;
3801     }
3802 
3803     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
3804     double progress = 0.0;
3805     ParseJsDouble(jsObj->GetProperty("percent"), progress);
3806     auto style = jsObj->GetPropertyValue<int32_t>("style",
3807         static_cast<int32_t>(WindowBlurStyle::STYLE_BACKGROUND_SMALL_LIGHT));
3808 
3809     progress = std::clamp(progress, 0.0, 1.0);
3810     style = std::clamp(style, static_cast<int32_t>(WindowBlurStyle::STYLE_BACKGROUND_SMALL_LIGHT),
3811         static_cast<int32_t>(WindowBlurStyle::STYLE_BACKGROUND_XLARGE_DARK));
3812 
3813     SetWindowBlur(static_cast<float>(progress), static_cast<WindowBlurStyle>(style));
3814     info.SetReturnValue(info.This());
3815 }
3816 
ParseDollarResource(const JSRef<JSVal> & jsValue,ResourceType & resType,std::string & resName)3817 bool JSViewAbstract::ParseDollarResource(const JSRef<JSVal>& jsValue, ResourceType& resType, std::string& resName)
3818 {
3819     if (!jsValue->IsString()) {
3820         return false;
3821     }
3822     std::string resPath = jsValue->ToString();
3823     std::vector<std::string> tokens;
3824     StringUtils::StringSplitter(resPath, '.', tokens);
3825     if (static_cast<int32_t>(tokens.size()) != 3) { // $r format like app.xxx.xxx, has 3 paragraph
3826         return false;
3827     }
3828     if (std::find(RESOURCE_HEADS.begin(), RESOURCE_HEADS.end(), tokens[0]) == RESOURCE_HEADS.end()) {
3829         return false;
3830     }
3831     if (!ConvertResourceType(tokens[1], resType)) {
3832         return false;
3833     }
3834     resName = resPath;
3835     return true;
3836 }
3837 
ConvertResourceType(const std::string & typeName,ResourceType & resType)3838 bool JSViewAbstract::ConvertResourceType(const std::string& typeName, ResourceType& resType)
3839 {
3840     static const std::unordered_map<std::string, ResourceType> resTypeMap {
3841         { "color", ResourceType::COLOR },
3842         { "media", ResourceType::MEDIA },
3843         { "float", ResourceType::FLOAT },
3844         { "string", ResourceType::STRING },
3845         { "plural", ResourceType::PLURAL },
3846         { "pattern", ResourceType::PATTERN },
3847         { "boolean", ResourceType::BOOLEAN },
3848         { "integer", ResourceType::INTEGER },
3849         { "strarray", ResourceType::STRARRAY },
3850         { "intarray", ResourceType::INTARRAY },
3851     };
3852     auto it = resTypeMap.find(typeName);
3853     if (it == resTypeMap.end()) {
3854         return false;
3855     }
3856     resType = it->second;
3857     return true;
3858 }
3859 
CompleteResourceObject(JSRef<JSObject> & jsObj)3860 void JSViewAbstract::CompleteResourceObject(JSRef<JSObject>& jsObj)
3861 {
3862     // dynamic $r raw input format is
3863     // {"id":"app.xxx.xxx", "params":[], "bundleName":"xxx", "moduleName":"xxx"}
3864     JSRef<JSVal> resId = jsObj->GetProperty("id");
3865     ResourceType resType;
3866     std::string resName;
3867     if (!ParseDollarResource(resId, resType, resName)) {
3868         return;
3869     }
3870     JSRef<JSVal> args = jsObj->GetProperty("params");
3871     if (!args->IsArray()) {
3872         return;
3873     }
3874     JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
3875     auto paramCount = params->Length();
3876     JSRef<JSVal> name = JSRef<JSVal>::Make(ToJSValue(resName));
3877     if (resType == ResourceType::PLURAL || resType == ResourceType::STRING) {
3878         std::vector<JSRef<JSVal>> tmpParams;
3879         for (uint32_t i = 0; i < paramCount; i++) {
3880             auto param = params->GetValueAt(i);
3881             tmpParams.insert(tmpParams.end(), param);
3882         }
3883         params->SetValueAt(0, name);
3884         uint32_t paramIndex = 1;
3885         auto firstParam = jsObj->GetProperty("type");
3886         if (!firstParam->IsEmpty()) {
3887             params->SetValueAt(paramIndex, firstParam);
3888             paramIndex++;
3889         }
3890         for (auto tmpParam : tmpParams) {
3891             params->SetValueAt(paramIndex, tmpParam);
3892             paramIndex++;
3893         }
3894     } else {
3895         params->SetValueAt(0, name);
3896     }
3897     jsObj->SetProperty<int32_t>("id", UNKNOWN_RESOURCE_ID);
3898     jsObj->SetProperty<int32_t>("type", static_cast<int32_t>(resType));
3899     if (!jsObj->HasProperty("bundleName")) {
3900         jsObj->SetProperty<std::string>("bundleName", "");
3901     }
3902     if (!jsObj->HasProperty("moduleName")) {
3903         jsObj->SetProperty<std::string>("moduleName", "");
3904     }
3905 }
3906 
ParseJsDimensionNG(const JSRef<JSVal> & jsValue,CalcDimension & result,DimensionUnit defaultUnit,bool isSupportPercent)3907 bool JSViewAbstract::ParseJsDimensionNG(
3908     const JSRef<JSVal> &jsValue, CalcDimension &result, DimensionUnit defaultUnit, bool isSupportPercent)
3909 {
3910     if (jsValue->IsNumber()) {
3911         result = CalcDimension(jsValue->ToNumber<double>(), defaultUnit);
3912         return true;
3913     }
3914     if (jsValue->IsString()) {
3915         auto value = jsValue->ToString();
3916         if (value.back() == '%' && !isSupportPercent) {
3917             return false;
3918         }
3919         return StringUtils::StringToCalcDimensionNG(jsValue->ToString(), result, false, defaultUnit);
3920     }
3921     if (jsValue->IsObject()) {
3922         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
3923         CompleteResourceObject(jsObj);
3924         JSRef<JSVal> resId = jsObj->GetProperty("id");
3925         if (!resId->IsNumber()) {
3926             return false;
3927         }
3928         auto resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
3929         if (resType == UNKNOWN_RESOURCE_TYPE) {
3930             return false;
3931         }
3932 
3933         auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
3934         auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
3935         if (!resourceWrapper) {
3936             return false;
3937         }
3938 
3939         auto resIdNum = resId->ToNumber<int32_t>();
3940         if (resIdNum == -1) {
3941             if (!IsGetResourceByName(jsObj)) {
3942                 return false;
3943             }
3944             JSRef<JSVal> args = jsObj->GetProperty("params");
3945             if (!args->IsArray()) {
3946                 return false;
3947             }
3948             JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
3949             auto param = params->GetValueAt(0);
3950             if (resType == static_cast<int32_t>(ResourceType::STRING)) {
3951                 auto value = resourceWrapper->GetStringByName(param->ToString());
3952                 return StringUtils::StringToCalcDimensionNG(value, result, false, defaultUnit);
3953             }
3954             if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
3955                 auto value = std::to_string(resourceWrapper->GetIntByName(param->ToString()));
3956                 StringUtils::StringToDimensionWithUnitNG(value, result, defaultUnit);
3957                 return true;
3958             }
3959             result = resourceWrapper->GetDimensionByName(param->ToString());
3960             return true;
3961         }
3962 
3963         if (resType == static_cast<int32_t>(ResourceType::STRING)) {
3964             auto value = resourceWrapper->GetString(resId->ToNumber<uint32_t>());
3965             return StringUtils::StringToCalcDimensionNG(value, result, false, defaultUnit);
3966         }
3967         if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
3968             auto value = std::to_string(resourceWrapper->GetInt(resId->ToNumber<uint32_t>()));
3969             StringUtils::StringToDimensionWithUnitNG(value, result, defaultUnit);
3970             return true;
3971         }
3972 
3973         if (resType == static_cast<int32_t>(ResourceType::FLOAT)) {
3974             result = resourceWrapper->GetDimension(resId->ToNumber<uint32_t>()); // float return true pixel value
3975             return true;
3976         }
3977     }
3978 
3979     return false;
3980 }
3981 
ParseJsDimension(const JSRef<JSVal> & jsValue,CalcDimension & result,DimensionUnit defaultUnit)3982 bool JSViewAbstract::ParseJsDimension(const JSRef<JSVal>& jsValue, CalcDimension& result, DimensionUnit defaultUnit)
3983 {
3984     if (jsValue->IsNumber()) {
3985         result = CalcDimension(jsValue->ToNumber<double>(), defaultUnit);
3986         return true;
3987     }
3988     if (jsValue->IsString()) {
3989         result = StringUtils::StringToCalcDimension(jsValue->ToString(), false, defaultUnit);
3990         return true;
3991     }
3992     if (!jsValue->IsObject()) {
3993         return false;
3994     }
3995     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
3996     CompleteResourceObject(jsObj);
3997     JSRef<JSVal> resId = jsObj->GetProperty("id");
3998     if (!resId->IsNumber()) {
3999         return false;
4000     }
4001 
4002     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
4003     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4004     if (!resourceWrapper) {
4005         return false;
4006     }
4007 
4008     auto resIdNum = resId->ToNumber<int32_t>();
4009     int32_t resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
4010     if (resType == UNKNOWN_RESOURCE_TYPE) {
4011         return false;
4012     }
4013 
4014     if (resIdNum == -1) {
4015         if (!IsGetResourceByName(jsObj)) {
4016             return false;
4017         }
4018         JSRef<JSVal> args = jsObj->GetProperty("params");
4019         if (!args->IsArray()) {
4020             return false;
4021         }
4022         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4023         auto param = params->GetValueAt(0);
4024         if (resType == static_cast<int32_t>(ResourceType::STRING)) {
4025             auto value = resourceWrapper->GetStringByName(param->ToString());
4026             result = StringUtils::StringToCalcDimension(value, false, defaultUnit);
4027             return true;
4028         }
4029         if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
4030             auto value = std::to_string(resourceWrapper->GetIntByName(param->ToString()));
4031             result = StringUtils::StringToDimensionWithUnit(value, defaultUnit);
4032             return true;
4033         }
4034         result = resourceWrapper->GetDimensionByName(param->ToString());
4035         return true;
4036     }
4037 
4038     if (resType == static_cast<int32_t>(ResourceType::STRING)) {
4039         auto value = resourceWrapper->GetString(resId->ToNumber<uint32_t>());
4040         result = StringUtils::StringToCalcDimension(value, false, defaultUnit);
4041         return true;
4042     }
4043     if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
4044         auto value = std::to_string(resourceWrapper->GetInt(resId->ToNumber<uint32_t>()));
4045         result = StringUtils::StringToDimensionWithUnit(value, defaultUnit);
4046         return true;
4047     }
4048     result = resourceWrapper->GetDimension(resId->ToNumber<uint32_t>());
4049     return true;
4050 }
4051 
ParseJsDimensionVpNG(const JSRef<JSVal> & jsValue,CalcDimension & result,bool isSupportPercent)4052 bool JSViewAbstract::ParseJsDimensionVpNG(const JSRef<JSVal>& jsValue, CalcDimension& result, bool isSupportPercent)
4053 {
4054     // 'vp' -> the value varies with pixel density of device.
4055     return ParseJsDimensionNG(jsValue, result, DimensionUnit::VP, isSupportPercent);
4056 }
4057 
ParseJsDimensionVp(const JSRef<JSVal> & jsValue,CalcDimension & result)4058 bool JSViewAbstract::ParseJsDimensionVp(const JSRef<JSVal>& jsValue, CalcDimension& result)
4059 {
4060     // 'vp' -> the value varies with pixel density of device.
4061     return ParseJsDimension(jsValue, result, DimensionUnit::VP);
4062 }
4063 
ParseJsDimensionFp(const JSRef<JSVal> & jsValue,CalcDimension & result)4064 bool JSViewAbstract::ParseJsDimensionFp(const JSRef<JSVal>& jsValue, CalcDimension& result)
4065 {
4066     // the 'fp' unit is used for text scenes.
4067     return ParseJsDimension(jsValue, result, DimensionUnit::FP);
4068 }
4069 
ParseJsDimensionFpNG(const JSRef<JSVal> & jsValue,CalcDimension & result,bool isSupportPercent)4070 bool JSViewAbstract::ParseJsDimensionFpNG(const JSRef<JSVal>& jsValue, CalcDimension& result, bool isSupportPercent)
4071 {
4072     // the 'fp' unit is used for text scenes.
4073     return ParseJsDimensionNG(jsValue, result, DimensionUnit::FP, isSupportPercent);
4074 }
4075 
ParseJsDimensionPx(const JSRef<JSVal> & jsValue,CalcDimension & result)4076 bool JSViewAbstract::ParseJsDimensionPx(const JSRef<JSVal>& jsValue, CalcDimension& result)
4077 {
4078     return ParseJsDimension(jsValue, result, DimensionUnit::PX);
4079 }
4080 
ParseResourceToDouble(const JSRef<JSVal> & jsValue,double & result)4081 bool JSViewAbstract::ParseResourceToDouble(const JSRef<JSVal>& jsValue, double& result)
4082 {
4083     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4084     CompleteResourceObject(jsObj);
4085     if (jsObj->IsEmpty()) {
4086         return false;
4087     }
4088     JSRef<JSVal> id = jsObj->GetProperty("id");
4089     if (!id->IsNumber()) {
4090         return false;
4091     }
4092 
4093     auto resId = id->ToNumber<int32_t>();
4094     int32_t resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
4095     if (resType == UNKNOWN_RESOURCE_TYPE) {
4096         return false;
4097     }
4098 
4099     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
4100     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4101     if (!resourceWrapper) {
4102         return false;
4103     }
4104 
4105     if (resId == -1) {
4106         if (!IsGetResourceByName(jsObj)) {
4107             return false;
4108         }
4109         JSRef<JSVal> args = jsObj->GetProperty("params");
4110         if (!args->IsArray()) {
4111             return false;
4112         }
4113         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4114         auto param = params->GetValueAt(0);
4115         if (resType == static_cast<int32_t>(ResourceType::STRING)) {
4116             auto numberString = resourceWrapper->GetStringByName(param->ToString());
4117             return StringUtils::StringToDouble(numberString, result);
4118         }
4119         if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
4120             result = resourceWrapper->GetIntByName(param->ToString());
4121             return true;
4122         }
4123         if (resType == static_cast<int32_t>(ResourceType::FLOAT)) {
4124             result = resourceWrapper->GetDoubleByName(param->ToString());
4125             return true;
4126         }
4127         return false;
4128     }
4129     if (resType == static_cast<int32_t>(ResourceType::STRING)) {
4130         auto numberString = resourceWrapper->GetString(resId);
4131         return StringUtils::StringToDouble(numberString, result);
4132     }
4133     if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
4134         result = resourceWrapper->GetInt(resId);
4135         return true;
4136     }
4137     if (resType == static_cast<int32_t>(ResourceType::FLOAT)) {
4138         result = resourceWrapper->GetDouble(resId);
4139         return true;
4140     }
4141     return false;
4142 }
4143 
ParseJsDouble(const JSRef<JSVal> & jsValue,double & result)4144 bool JSViewAbstract::ParseJsDouble(const JSRef<JSVal>& jsValue, double& result)
4145 {
4146     if (jsValue->IsNumber()) {
4147         result = jsValue->ToNumber<double>();
4148         return true;
4149     }
4150     if (jsValue->IsString()) {
4151         return StringUtils::StringToDouble(jsValue->ToString(), result);
4152     }
4153     if (jsValue->IsObject()) {
4154         return ParseResourceToDouble(jsValue, result);
4155     }
4156     return false;
4157 }
4158 
ParseJsInt32(const JSRef<JSVal> & jsValue,int32_t & result)4159 bool JSViewAbstract::ParseJsInt32(const JSRef<JSVal>& jsValue, int32_t& result)
4160 {
4161     if (!jsValue->IsNumber() && !jsValue->IsString() && !jsValue->IsObject()) {
4162         return false;
4163     }
4164     if (jsValue->IsNumber()) {
4165         result = jsValue->ToNumber<int32_t>();
4166         return true;
4167     }
4168     if (jsValue->IsString()) {
4169         result = StringUtils::StringToInt(jsValue->ToString());
4170         return true;
4171     }
4172     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4173     CompleteResourceObject(jsObj);
4174     JSRef<JSVal> resId = jsObj->GetProperty("id");
4175     if (!resId->IsNumber()) {
4176         return false;
4177     }
4178 
4179     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
4180     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4181     if (!resourceWrapper) {
4182         return false;
4183     }
4184 
4185     auto resIdNum = resId->ToNumber<int32_t>();
4186     if (resIdNum == -1) {
4187         if (!IsGetResourceByName(jsObj)) {
4188             return false;
4189         }
4190         JSRef<JSVal> args = jsObj->GetProperty("params");
4191         if (!args->IsArray()) {
4192             return false;
4193         }
4194         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4195         auto param = params->GetValueAt(0);
4196         result = resourceWrapper->GetIntByName(param->ToString());
4197         return true;
4198     }
4199     result = resourceWrapper->GetInt(resId->ToNumber<uint32_t>());
4200     return true;
4201 }
4202 
ParseJsColorFromResource(const JSRef<JSVal> & jsValue,Color & result)4203 bool JSViewAbstract::ParseJsColorFromResource(const JSRef<JSVal>& jsValue, Color& result)
4204 {
4205     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4206     CompleteResourceObject(jsObj);
4207     JSRef<JSVal> resId = jsObj->GetProperty("id");
4208     if (!resId->IsNumber()) {
4209         return false;
4210     }
4211 
4212     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
4213     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4214     if (!resourceWrapper) {
4215         return false;
4216     }
4217 
4218     auto resIdNum = resId->ToNumber<int32_t>();
4219     if (resIdNum == -1) {
4220         if (!IsGetResourceByName(jsObj)) {
4221             return false;
4222         }
4223         JSRef<JSVal> args = jsObj->GetProperty("params");
4224         if (!args->IsArray()) {
4225             return false;
4226         }
4227         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4228         auto param = params->GetValueAt(0);
4229         result = resourceWrapper->GetColorByName(param->ToString());
4230         return true;
4231     }
4232     auto type = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
4233     if (type == static_cast<int32_t>(ResourceType::STRING)) {
4234         auto value = resourceWrapper->GetString(resId->ToNumber<uint32_t>());
4235         return Color::ParseColorString(value, result);
4236     }
4237     if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
4238         auto value = resourceWrapper->GetInt(resId->ToNumber<uint32_t>());
4239         result = Color(ColorAlphaAdapt(value));
4240         return true;
4241     }
4242     if (type == static_cast<int32_t>(ResourceType::COLOR)) {
4243         result = resourceWrapper->GetColor(resId->ToNumber<uint32_t>());
4244         return true;
4245     }
4246     return false;
4247 }
4248 
ParseJsColor(const JSRef<JSVal> & jsValue,Color & result)4249 bool JSViewAbstract::ParseJsColor(const JSRef<JSVal>& jsValue, Color& result)
4250 {
4251     if (jsValue->IsNumber()) {
4252         result = Color(ColorAlphaAdapt(jsValue->ToNumber<uint32_t>()));
4253         return true;
4254     }
4255     if (jsValue->IsString()) {
4256         return Color::ParseColorString(jsValue->ToString(), result);
4257     }
4258     if (jsValue->IsObject()) {
4259         return ParseJsColorFromResource(jsValue, result);
4260     }
4261     return false;
4262 }
4263 
ParseJsColorStrategy(const JSRef<JSVal> & jsValue,ForegroundColorStrategy & strategy)4264 bool JSViewAbstract::ParseJsColorStrategy(const JSRef<JSVal>& jsValue, ForegroundColorStrategy& strategy)
4265 {
4266     if (jsValue->IsString()) {
4267         std::string colorStr = jsValue->ToString();
4268         if (colorStr.compare("invert") == 0) {
4269             strategy = ForegroundColorStrategy::INVERT;
4270             return true;
4271         }
4272     }
4273     return false;
4274 }
4275 
ParseJsShadowColorStrategy(const JSRef<JSVal> & jsValue,ShadowColorStrategy & strategy)4276 bool JSViewAbstract::ParseJsShadowColorStrategy(const JSRef<JSVal>& jsValue, ShadowColorStrategy& strategy)
4277 {
4278     if (jsValue->IsString()) {
4279         std::string colorStr = jsValue->ToString();
4280         if (colorStr.compare("average") == 0) {
4281             strategy = ShadowColorStrategy::AVERAGE;
4282             return true;
4283         } else if (colorStr.compare("primary") == 0) {
4284             strategy = ShadowColorStrategy::PRIMARY;
4285             return true;
4286         }
4287     }
4288     return false;
4289 }
4290 
ParseJsSymbolId(const JSRef<JSVal> & jsValue,std::uint32_t & symbolId,RefPtr<ResourceObject> & symbolResourceObject)4291 bool JSViewAbstract::ParseJsSymbolId(
4292     const JSRef<JSVal>& jsValue, std::uint32_t& symbolId, RefPtr<ResourceObject>& symbolResourceObject)
4293 {
4294     if (jsValue->IsNull() || jsValue->IsUndefined()) {
4295         symbolId = 0;
4296         return false;
4297     }
4298     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4299     JSRef<JSVal> resId = jsObj->GetProperty("id");
4300     if (resId->IsNull() || !resId->IsNumber()) {
4301         return false;
4302     }
4303     auto resourceObject = GetResourceObject(jsObj);
4304     symbolResourceObject = resourceObject;
4305     if (!resourceObject) {
4306         return false;
4307     }
4308     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4309     if (!resourceWrapper) {
4310         return false;
4311     }
4312     auto symbol = resourceWrapper->GetSymbolById(resId->ToNumber<uint32_t>());
4313     if (!symbol) {
4314         return false;
4315     }
4316     symbolId = symbol;
4317     return true;
4318 }
4319 
ParseJsSymbolColor(const JSRef<JSVal> & jsValue,std::vector<Color> & result)4320 bool JSViewAbstract::ParseJsSymbolColor(const JSRef<JSVal>& jsValue, std::vector<Color>& result)
4321 {
4322     if (!jsValue->IsArray()) {
4323         return false;
4324     }
4325     if (jsValue->IsArray()) {
4326         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
4327         for (size_t i = 0; i < array->Length(); i++) {
4328             JSRef<JSVal> value = array->GetValueAt(i);
4329             if (!value->IsNumber() && !value->IsString() && !value->IsObject()) {
4330                 return false;
4331             }
4332             if (value->IsNumber()) {
4333                 result.emplace_back(Color(ColorAlphaAdapt(value->ToNumber<uint32_t>())));
4334                 continue;
4335             } else if (value->IsString()) {
4336                 Color color;
4337                 Color::ParseColorString(value->ToString(), color);
4338                 result.emplace_back(color);
4339                 continue;
4340             } else {
4341                 Color color;
4342                 ParseJsColorFromResource(value, color);
4343                 result.emplace_back(color);
4344             }
4345         }
4346         return true;
4347     }
4348     return false;
4349 }
4350 
ParseJsFontFamilies(const JSRef<JSVal> & jsValue,std::vector<std::string> & result)4351 bool JSViewAbstract::ParseJsFontFamilies(const JSRef<JSVal>& jsValue, std::vector<std::string>& result)
4352 {
4353     result.clear();
4354     if (!jsValue->IsString() && !jsValue->IsObject()) {
4355         return false;
4356     }
4357     if (jsValue->IsString()) {
4358         result = ConvertStrToFontFamilies(jsValue->ToString());
4359         return true;
4360     }
4361     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4362     CompleteResourceObject(jsObj);
4363     JSRef<JSVal> resId = jsObj->GetProperty("id");
4364     if (!resId->IsNumber()) {
4365         return false;
4366     }
4367 
4368     auto resourceObject = GetResourceObject(jsObj);
4369     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4370     if (!resourceWrapper) {
4371         return false;
4372     }
4373 
4374     auto resIdNum = resId->ToNumber<int32_t>();
4375     if (resIdNum == -1) {
4376         if (!IsGetResourceByName(jsObj)) {
4377             return false;
4378         }
4379         JSRef<JSVal> args = jsObj->GetProperty("params");
4380         if (!args->IsArray()) {
4381             return false;
4382         }
4383         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4384         auto param = params->GetValueAt(0);
4385         result.emplace_back(resourceWrapper->GetStringByName(param->ToString()));
4386         return true;
4387     }
4388     result.emplace_back(resourceWrapper->GetString(resId->ToNumber<uint32_t>()));
4389     return true;
4390 }
4391 
ParseJsString(const JSRef<JSVal> & jsValue,std::string & result)4392 bool JSViewAbstract::ParseJsString(const JSRef<JSVal>& jsValue, std::string& result)
4393 {
4394     if (!jsValue->IsString() && !jsValue->IsObject()) {
4395         return false;
4396     }
4397 
4398     if (jsValue->IsString()) {
4399         result = jsValue->ToString();
4400         return true;
4401     }
4402 
4403     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4404     CompleteResourceObject(jsObj);
4405 
4406     JSRef<JSVal> resId = jsObj->GetProperty("id");
4407     if (!resId->IsNumber()) {
4408         return false;
4409     }
4410     auto type = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
4411     if (type == UNKNOWN_RESOURCE_TYPE) {
4412         return false;
4413     }
4414 
4415     JSRef<JSVal> args = jsObj->GetProperty("params");
4416     if (!args->IsArray()) {
4417         return false;
4418     }
4419 
4420     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
4421     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4422     if (!resourceWrapper) {
4423         return false;
4424     }
4425 
4426     JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4427     auto resIdNum = resId->ToNumber<int32_t>();
4428     if (resIdNum == -1) {
4429         if (!IsGetResourceByName(jsObj)) {
4430             return false;
4431         }
4432         auto param = params->GetValueAt(0);
4433         if (type == static_cast<int32_t>(ResourceType::STRING)) {
4434             auto originStr = resourceWrapper->GetStringByName(param->ToString());
4435             ReplaceHolder(originStr, params, 1);
4436             result = originStr;
4437         } else if (type == static_cast<int32_t>(ResourceType::PLURAL)) {
4438             auto countJsVal = params->GetValueAt(1);
4439             int count = 0;
4440             if (!countJsVal->IsNumber()) {
4441                 return false;
4442             }
4443             count = countJsVal->ToNumber<int>();
4444             auto pluralStr = resourceWrapper->GetPluralStringByName(param->ToString(), count);
4445             ReplaceHolder(pluralStr, params, 2);
4446             result = pluralStr;
4447         } else {
4448             return false;
4449         }
4450         return true;
4451     }
4452     if (type == static_cast<int32_t>(ResourceType::STRING)) {
4453         auto originStr = resourceWrapper->GetString(resId->ToNumber<uint32_t>());
4454         ReplaceHolder(originStr, params, 0);
4455         result = originStr;
4456     } else if (type == static_cast<int32_t>(ResourceType::PLURAL)) {
4457         auto countJsVal = params->GetValueAt(0);
4458         int count = 0;
4459         if (!countJsVal->IsNumber()) {
4460             return false;
4461         }
4462         count = countJsVal->ToNumber<int>();
4463         auto pluralStr = resourceWrapper->GetPluralString(resId->ToNumber<uint32_t>(), count);
4464         ReplaceHolder(pluralStr, params, 1);
4465         result = pluralStr;
4466     } else if (type == static_cast<int32_t>(ResourceType::FLOAT)) {
4467         result = std::to_string(resourceWrapper->GetDouble(resId->ToNumber<uint32_t>()));
4468     } else if (type == static_cast<int32_t>(ResourceType::INTEGER)) {
4469         result = std::to_string(resourceWrapper->GetInt(resId->ToNumber<uint32_t>()));
4470     } else {
4471         return false;
4472     }
4473     return true;
4474 }
4475 
ParseJsMedia(const JSRef<JSVal> & jsValue,std::string & result)4476 bool JSViewAbstract::ParseJsMedia(const JSRef<JSVal>& jsValue, std::string& result)
4477 {
4478     if (!jsValue->IsObject() && !jsValue->IsString()) {
4479         return false;
4480     }
4481     if (jsValue->IsString()) {
4482         result = jsValue->ToString();
4483         return true;
4484     }
4485     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4486     CompleteResourceObject(jsObj);
4487     int32_t type = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
4488     JSRef<JSVal> resId = jsObj->GetProperty("id");
4489     if (!resId->IsNull() && type != UNKNOWN_RESOURCE_TYPE && resId->IsNumber()) {
4490         auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
4491         auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4492         if (!resourceWrapper) {
4493             return false;
4494         }
4495 
4496         if (type == static_cast<int32_t>(ResourceType::RAWFILE)) {
4497             JSRef<JSVal> args = jsObj->GetProperty("params");
4498             if (!args->IsArray()) {
4499                 return false;
4500             }
4501             JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4502             auto fileName = params->GetValueAt(0);
4503             if (!fileName->IsString()) {
4504                 return false;
4505             }
4506             result = resourceWrapper->GetRawfile(fileName->ToString());
4507             return true;
4508         }
4509         auto resIdNum = resId->ToNumber<int32_t>();
4510         if (resIdNum == -1) {
4511             if (!IsGetResourceByName(jsObj)) {
4512                 return false;
4513             }
4514             JSRef<JSVal> args = jsObj->GetProperty("params");
4515             if (!args->IsArray()) {
4516                 return false;
4517             }
4518             JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4519             auto param = params->GetValueAt(0);
4520             if (type == static_cast<int32_t>(ResourceType::MEDIA)) {
4521                 result = resourceWrapper->GetMediaPathByName(param->ToString());
4522                 return true;
4523             }
4524             return false;
4525         }
4526         if (type == static_cast<int32_t>(ResourceType::MEDIA)) {
4527             result = resourceWrapper->GetMediaPath(resId->ToNumber<uint32_t>());
4528             return true;
4529         }
4530         return false;
4531     }
4532     return false;
4533 }
4534 
ParseJsBool(const JSRef<JSVal> & jsValue,bool & result)4535 bool JSViewAbstract::ParseJsBool(const JSRef<JSVal>& jsValue, bool& result)
4536 {
4537     if (!jsValue->IsBoolean() && !jsValue->IsObject()) {
4538         return false;
4539     }
4540 
4541     if (jsValue->IsBoolean()) {
4542         result = jsValue->ToBoolean();
4543         return true;
4544     }
4545 
4546     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4547     CompleteResourceObject(jsObj);
4548     int32_t resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
4549     if (resType == UNKNOWN_RESOURCE_TYPE) {
4550         return false;
4551     }
4552 
4553     JSRef<JSVal> resId = jsObj->GetProperty("id");
4554     if (!resId->IsNumber()) {
4555         return false;
4556     }
4557 
4558     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
4559     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4560     if (!resourceWrapper) {
4561         return false;
4562     }
4563 
4564     auto resIdNum = resId->ToNumber<int32_t>();
4565     if (resIdNum == -1) {
4566         if (!IsGetResourceByName(jsObj)) {
4567             return false;
4568         }
4569         JSRef<JSVal> args = jsObj->GetProperty("params");
4570         if (!args->IsArray()) {
4571             return false;
4572         }
4573         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4574         auto param = params->GetValueAt(0);
4575         if (resType == static_cast<int32_t>(ResourceType::BOOLEAN)) {
4576             result = resourceWrapper->GetBooleanByName(param->ToString());
4577             return true;
4578         }
4579         return false;
4580     }
4581 
4582     if (resType == static_cast<int32_t>(ResourceType::BOOLEAN)) {
4583         result = resourceWrapper->GetBoolean(resId->ToNumber<uint32_t>());
4584         return true;
4585     }
4586     return false;
4587 }
4588 
ParseJsInteger(const JSRef<JSVal> & jsValue,uint32_t & result)4589 bool JSViewAbstract::ParseJsInteger(const JSRef<JSVal>& jsValue, uint32_t& result)
4590 {
4591     return ParseJsInteger<uint32_t>(jsValue, result);
4592 }
4593 
ParseJsInteger(const JSRef<JSVal> & jsValue,int32_t & result)4594 bool JSViewAbstract::ParseJsInteger(const JSRef<JSVal>& jsValue, int32_t& result)
4595 {
4596     return ParseJsInteger<int32_t>(jsValue, result);
4597 }
4598 
ParseJsIntegerArray(const JSRef<JSVal> & jsValue,std::vector<uint32_t> & result)4599 bool JSViewAbstract::ParseJsIntegerArray(const JSRef<JSVal>& jsValue, std::vector<uint32_t>& result)
4600 {
4601     if (!jsValue->IsArray() && !jsValue->IsObject()) {
4602         return false;
4603     }
4604 
4605     if (jsValue->IsArray()) {
4606         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
4607         for (size_t i = 0; i < array->Length(); i++) {
4608             JSRef<JSVal> value = array->GetValueAt(i);
4609             if (value->IsNumber()) {
4610                 result.emplace_back(value->ToNumber<uint32_t>());
4611             } else if (value->IsObject()) {
4612                 uint32_t singleResInt;
4613                 if (ParseJsInteger(value, singleResInt)) {
4614                     result.emplace_back(singleResInt);
4615                 } else {
4616                     return false;
4617                 }
4618             } else {
4619                 return false;
4620             }
4621         }
4622         return true;
4623     }
4624 
4625     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4626     CompleteResourceObject(jsObj);
4627     int32_t resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
4628     if (resType == UNKNOWN_RESOURCE_TYPE) {
4629         return false;
4630     }
4631 
4632     JSRef<JSVal> resId = jsObj->GetProperty("id");
4633     if (!resId->IsNumber()) {
4634         return false;
4635     }
4636 
4637     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
4638     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4639     if (!resourceWrapper) {
4640         return false;
4641     }
4642 
4643     auto resIdNum = resId->ToNumber<int32_t>();
4644     if (resIdNum == -1) {
4645         if (!IsGetResourceByName(jsObj)) {
4646             return false;
4647         }
4648         JSRef<JSVal> args = jsObj->GetProperty("params");
4649         if (!args->IsArray()) {
4650             return false;
4651         }
4652         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4653         auto param = params->GetValueAt(0);
4654         if (resType == static_cast<int32_t>(ResourceType::INTARRAY)) {
4655             result = resourceWrapper->GetIntArrayByName(param->ToString());
4656             return true;
4657         }
4658         return false;
4659     }
4660 
4661     if (resType == static_cast<int32_t>(ResourceType::INTARRAY)) {
4662         result = resourceWrapper->GetIntArray(resId->ToNumber<uint32_t>());
4663         return true;
4664     }
4665     return false;
4666 }
4667 
ParseJsStrArray(const JSRef<JSVal> & jsValue,std::vector<std::string> & result)4668 bool JSViewAbstract::ParseJsStrArray(const JSRef<JSVal>& jsValue, std::vector<std::string>& result)
4669 {
4670     if (!jsValue->IsArray() && !jsValue->IsObject()) {
4671         return false;
4672     }
4673 
4674     if (jsValue->IsArray()) {
4675         JSRef<JSArray> array = JSRef<JSArray>::Cast(jsValue);
4676         for (size_t i = 0; i < array->Length(); i++) {
4677             JSRef<JSVal> value = array->GetValueAt(i);
4678             if (value->IsString()) {
4679                 result.emplace_back(value->ToString());
4680             } else if (value->IsObject()) {
4681                 std::string singleResStr;
4682                 if (ParseJsString(value, singleResStr)) {
4683                     result.emplace_back(singleResStr);
4684                 } else {
4685                     return false;
4686                 }
4687             } else {
4688                 return false;
4689             }
4690         }
4691         return true;
4692     }
4693 
4694     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
4695     CompleteResourceObject(jsObj);
4696     int32_t resType = jsObj->GetPropertyValue<int32_t>("type", UNKNOWN_RESOURCE_TYPE);
4697     if (resType == UNKNOWN_RESOURCE_TYPE) {
4698         return false;
4699     }
4700 
4701     JSRef<JSVal> resId = jsObj->GetProperty("id");
4702     if (!resId->IsNumber()) {
4703         return false;
4704     }
4705 
4706     auto resourceObject = GetResourceObjectByBundleAndModule(jsObj);
4707     auto resourceWrapper = CreateResourceWrapper(jsObj, resourceObject);
4708     if (!resourceWrapper) {
4709         return false;
4710     }
4711 
4712     auto resIdNum = resId->ToNumber<int32_t>();
4713     if (resIdNum == -1) {
4714         if (!IsGetResourceByName(jsObj)) {
4715             return false;
4716         }
4717         JSRef<JSVal> args = jsObj->GetProperty("params");
4718         if (!args->IsArray()) {
4719             return false;
4720         }
4721         JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4722         auto param = params->GetValueAt(0);
4723         if (resType == static_cast<int32_t>(ResourceType::STRARRAY)) {
4724             result = resourceWrapper->GetStringArrayByName(param->ToString());
4725             return true;
4726         }
4727         return false;
4728     }
4729 
4730     if (resType == static_cast<int32_t>(ResourceType::STRARRAY)) {
4731         result = resourceWrapper->GetStringArray(resId->ToNumber<uint32_t>());
4732         return true;
4733     }
4734     return false;
4735 }
4736 
IsGetResourceByName(const JSRef<JSObject> & jsObj)4737 bool JSViewAbstract::IsGetResourceByName(const JSRef<JSObject>& jsObj)
4738 {
4739     JSRef<JSVal> resId = jsObj->GetProperty("id");
4740     if (!resId->IsNumber() || resId->ToNumber<int32_t>() != -1) {
4741         return false;
4742     }
4743     JSRef<JSVal> args = jsObj->GetProperty("params");
4744     if (!args->IsArray()) {
4745         return false;
4746     }
4747     JSRef<JSVal> bundleName = jsObj->GetProperty("bundleName");
4748     JSRef<JSVal> moduleName = jsObj->GetProperty("moduleName");
4749     if (!bundleName->IsString() || !moduleName->IsString()) {
4750         return false;
4751     }
4752     JSRef<JSArray> params = JSRef<JSArray>::Cast(args);
4753     if (params->IsEmpty()) {
4754         return false;
4755     }
4756     return true;
4757 }
4758 
ParseSize(const JSCallbackInfo & info)4759 std::pair<CalcDimension, CalcDimension> JSViewAbstract::ParseSize(const JSCallbackInfo& info)
4760 {
4761     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
4762     if (!CheckJSCallbackInfo("ParseSize", info, checkList)) {
4763         return std::pair<CalcDimension, CalcDimension>();
4764     }
4765     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
4766     CalcDimension width;
4767     CalcDimension height;
4768     if (!ParseJsDimensionVp(jsObj->GetProperty("width"), width) ||
4769         !ParseJsDimensionVp(jsObj->GetProperty("height"), height)) {
4770         return std::pair<CalcDimension, CalcDimension>();
4771     }
4772     return std::pair<CalcDimension, CalcDimension>(width, height);
4773 }
4774 
JsUseAlign(const JSCallbackInfo & info)4775 void JSViewAbstract::JsUseAlign(const JSCallbackInfo& info)
4776 {
4777     if (info.Length() < 2) {
4778         return;
4779     }
4780 
4781     if (!info[0]->IsObject() && !info[1]->IsObject()) {
4782         return;
4783     }
4784 
4785     AlignDeclaration* declaration = JSRef<JSObject>::Cast(info[0])->Unwrap<AlignDeclaration>();
4786     if (declaration == nullptr) {
4787         return;
4788     }
4789 
4790     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
4791     JSRef<JSVal> side = obj->GetProperty("side");
4792     JSRef<JSVal> offset = obj->GetProperty("offset");
4793 
4794     if (!side->IsNumber()) {
4795         return;
4796     }
4797 
4798     auto sideValue = side->ToNumber<int32_t>();
4799 
4800     if (declaration->GetDeclarationType() == AlignDeclaration::DeclarationType::HORIZONTAL) {
4801         if (sideValue < static_cast<int32_t>(AlignDeclaration::Edge::START) ||
4802             sideValue > static_cast<int32_t>(AlignDeclaration::Edge::END)) {
4803             return;
4804         }
4805     } else if (declaration->GetDeclarationType() == AlignDeclaration::DeclarationType::VERTICAL) {
4806         if (sideValue < static_cast<int32_t>(AlignDeclaration::Edge::TOP) ||
4807             sideValue > static_cast<int32_t>(AlignDeclaration::Edge::BASELINE)) {
4808             return;
4809         }
4810     }
4811 
4812     std::optional<CalcDimension> optOffset;
4813     CalcDimension offsetDimension;
4814     if (ParseJsDimensionVp(offset, offsetDimension)) {
4815         optOffset = offsetDimension;
4816     }
4817     ViewAbstractModel::GetInstance()->SetUseAlign(
4818         declaration, static_cast<AlignDeclaration::Edge>(sideValue), optOffset);
4819 }
4820 
JsGridSpan(const JSCallbackInfo & info)4821 void JSViewAbstract::JsGridSpan(const JSCallbackInfo& info)
4822 {
4823     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
4824     if (!CheckJSCallbackInfo("JsGridSpan", info, checkList)) {
4825         return;
4826     }
4827     auto span = info[0]->ToNumber<int32_t>();
4828     ViewAbstractModel::GetInstance()->SetGrid(span, std::nullopt);
4829 }
4830 
JsGridOffset(const JSCallbackInfo & info)4831 void JSViewAbstract::JsGridOffset(const JSCallbackInfo& info)
4832 {
4833     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
4834     if (!CheckJSCallbackInfo("JsGridOffset", info, checkList)) {
4835         return;
4836     }
4837     auto offset = info[0]->ToNumber<int32_t>();
4838     ViewAbstractModel::GetInstance()->SetGrid(std::nullopt, offset);
4839 }
4840 
ParseSpanAndOffset(const JSRef<JSVal> & val,uint32_t & span,int32_t & offset)4841 static bool ParseSpanAndOffset(const JSRef<JSVal>& val, uint32_t& span, int32_t& offset)
4842 {
4843     // {lg: 4}
4844     if (val->IsNumber()) {
4845         span = val->ToNumber<uint32_t>();
4846         return true;
4847     }
4848 
4849     if (!val->IsObject()) {
4850         return false;
4851     }
4852 
4853     // {lg: {span: 1, offset: 2}}
4854     JSRef<JSObject> obj = JSRef<JSObject>::Cast(val);
4855     span = obj->GetProperty("span")->ToNumber<uint32_t>();
4856     offset = obj->GetProperty("offset")->ToNumber<int32_t>();
4857     return true;
4858 }
4859 
JsUseSizeType(const JSCallbackInfo & info)4860 void JSViewAbstract::JsUseSizeType(const JSCallbackInfo& info)
4861 {
4862     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
4863     if (!CheckJSCallbackInfo("JsUseSizeType", info, checkList)) {
4864         return;
4865     }
4866     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
4867     for (auto values : SCREEN_SIZE_VALUES) {
4868         JSRef<JSVal> val = sizeObj->GetProperty(values.second.c_str());
4869         if (val->IsNull() || val->IsEmpty()) {
4870             continue;
4871         }
4872         uint32_t span = 0;
4873         int32_t offset = 0;
4874         if (ParseSpanAndOffset(val, span, offset)) {
4875             ViewAbstractModel::GetInstance()->SetGrid(span, offset, values.first);
4876         }
4877     }
4878 }
4879 
JsZIndex(const JSCallbackInfo & info)4880 void JSViewAbstract::JsZIndex(const JSCallbackInfo& info)
4881 {
4882     int zIndex = 0;
4883     if (info[0]->IsNumber()) {
4884         zIndex = info[0]->ToNumber<int>();
4885     }
4886 
4887     ViewAbstractModel::GetInstance()->SetZIndex(zIndex);
4888 }
4889 
Pop()4890 void JSViewAbstract::Pop()
4891 {
4892     ViewStackModel::GetInstance()->Pop();
4893 }
4894 
JsSetDraggable(bool draggable)4895 void JSViewAbstract::JsSetDraggable(bool draggable)
4896 {
4897     ViewAbstractModel::GetInstance()->SetDraggable(draggable);
4898 }
4899 
JsSetDragPreviewOptions(const JSCallbackInfo & info)4900 void JSViewAbstract::JsSetDragPreviewOptions(const JSCallbackInfo& info)
4901 {
4902     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
4903     if (!CheckJSCallbackInfo("JsSetDragPreviewOptions", info, checkList)) {
4904         return;
4905     }
4906     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
4907     auto mode = obj->GetProperty("mode");
4908     if (!mode->IsNumber()) {
4909         ViewAbstractModel::GetInstance()->SetDragPreviewOptions({NG::DragPreviewMode::AUTO});
4910         return;
4911     }
4912     int32_t dragPreviewMode = mode->ToNumber<int>();
4913     if (!(dragPreviewMode >= static_cast<int32_t>(NG::DragPreviewMode::AUTO) &&
4914             dragPreviewMode <= static_cast<int32_t>(NG::DragPreviewMode::DISABLE_SCALE))) {
4915         dragPreviewMode = static_cast<int32_t>(NG::DragPreviewMode::AUTO);
4916     }
4917     NG::DragPreviewOption option {static_cast<NG::DragPreviewMode>(dragPreviewMode)};
4918     ViewAbstractModel::GetInstance()->SetDragPreviewOptions(option);
4919 }
4920 
JsOnDragStart(const JSCallbackInfo & info)4921 void JSViewAbstract::JsOnDragStart(const JSCallbackInfo& info)
4922 {
4923     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
4924     if (!CheckJSCallbackInfo("JsOnDragStart", info, checkList)) {
4925         return;
4926     }
4927 
4928     RefPtr<JsDragFunction> jsOnDragStartFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
4929 
4930     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
4931     auto onDragStart = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragStartFunc), node = frameNode](
4932                            const RefPtr<DragEvent>& info, const std::string& extraParams) -> NG::DragDropBaseInfo {
4933         NG::DragDropBaseInfo dragDropInfo;
4934         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, dragDropInfo);
4935         PipelineContext::SetCallBackNode(node);
4936         auto ret = func->Execute(info, extraParams);
4937         if (!ret->IsObject()) {
4938             return dragDropInfo;
4939         }
4940 
4941         dragDropInfo.node = ParseDragNode(ret);
4942         auto builderObj = JSRef<JSObject>::Cast(ret);
4943 #if defined(PIXEL_MAP_SUPPORTED)
4944         auto pixmap = builderObj->GetProperty("pixelMap");
4945         dragDropInfo.pixelMap = CreatePixelMapFromNapiValue(pixmap);
4946 #endif
4947         auto extraInfo = builderObj->GetProperty("extraInfo");
4948         ParseJsString(extraInfo, dragDropInfo.extraInfo);
4949         return dragDropInfo;
4950     };
4951     ViewAbstractModel::GetInstance()->SetOnDragStart(std::move(onDragStart));
4952 }
4953 
ParseAndUpdateDragItemInfo(const JSRef<JSVal> & info,NG::DragDropBaseInfo & dragInfo)4954 bool JSViewAbstract::ParseAndUpdateDragItemInfo(const JSRef<JSVal>& info, NG::DragDropBaseInfo& dragInfo)
4955 {
4956     auto node = ParseDragNode(info);
4957     if (!node) {
4958         return false;
4959     }
4960     dragInfo.node = node;
4961     return true;
4962 }
4963 
ParseDragNode(const JSRef<JSVal> & info)4964 RefPtr<AceType> JSViewAbstract::ParseDragNode(const JSRef<JSVal>& info)
4965 {
4966     auto builderFunc = ParseDragStartBuilderFunc(info);
4967     if (!builderFunc) {
4968         return nullptr;
4969     }
4970     // use another VSP instance while executing the builder function
4971     ViewStackModel::GetInstance()->NewScope();
4972     {
4973         ACE_SCORING_EVENT("onDragStart.builder");
4974         builderFunc->Execute();
4975     }
4976 
4977     return ViewStackModel::GetInstance()->Finish();
4978 }
4979 
JsOnDragEnter(const JSCallbackInfo & info)4980 void JSViewAbstract::JsOnDragEnter(const JSCallbackInfo& info)
4981 {
4982     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
4983     if (!CheckJSCallbackInfo("JsOnDragEnter", info, checkList)) {
4984         return;
4985     }
4986     RefPtr<JsDragFunction> jsOnDragEnterFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
4987     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
4988     auto onDragEnter = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEnterFunc), node = frameNode](
4989                            const RefPtr<OHOS::Ace::DragEvent>& info, const std::string& extraParams) {
4990         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
4991         ACE_SCORING_EVENT("onDragEnter");
4992         PipelineContext::SetCallBackNode(node);
4993         func->Execute(info, extraParams);
4994     };
4995 
4996     ViewAbstractModel::GetInstance()->SetOnDragEnter(std::move(onDragEnter));
4997 }
4998 
JsOnDragEnd(const JSCallbackInfo & info)4999 void JSViewAbstract::JsOnDragEnd(const JSCallbackInfo& info)
5000 {
5001     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
5002     if (!CheckJSCallbackInfo("JsOnDragEnd", info, checkList)) {
5003         return;
5004     }
5005     RefPtr<JsDragFunction> jsOnDragEndFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
5006     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5007     auto onDragEnd = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEndFunc), node = frameNode](
5008                          const RefPtr<OHOS::Ace::DragEvent>& info) {
5009         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5010         ACE_SCORING_EVENT("onDragEnd");
5011         auto extraParams = JsonUtil::Create(true);
5012         PipelineContext::SetCallBackNode(node);
5013         func->Execute(info, extraParams->ToString());
5014     };
5015 
5016     ViewAbstractModel::GetInstance()->SetOnDragEnd(std::move(onDragEnd));
5017 }
5018 
JsOnDragMove(const JSCallbackInfo & info)5019 void JSViewAbstract::JsOnDragMove(const JSCallbackInfo& info)
5020 {
5021     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
5022     if (!CheckJSCallbackInfo("JsOnDragMove", info, checkList)) {
5023         return;
5024     }
5025     RefPtr<JsDragFunction> jsOnDragMoveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
5026     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5027     auto onDragMove = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragMoveFunc), node = frameNode](
5028                           const RefPtr<OHOS::Ace::DragEvent>& info, const std::string& extraParams) {
5029         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5030         ACE_SCORING_EVENT("onDragMove");
5031         PipelineContext::SetCallBackNode(node);
5032         func->Execute(info, extraParams);
5033     };
5034 
5035     ViewAbstractModel::GetInstance()->SetOnDragMove(std::move(onDragMove));
5036 }
5037 
JsOnDragLeave(const JSCallbackInfo & info)5038 void JSViewAbstract::JsOnDragLeave(const JSCallbackInfo& info)
5039 {
5040     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
5041     if (!CheckJSCallbackInfo("JsOnDragLeave", info, checkList)) {
5042         return;
5043     }
5044     RefPtr<JsDragFunction> jsOnDragLeaveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
5045     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5046     auto onDragLeave = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragLeaveFunc), node = frameNode](
5047                            const RefPtr<OHOS::Ace::DragEvent>& info, const std::string& extraParams) {
5048         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5049         ACE_SCORING_EVENT("onDragLeave");
5050         PipelineContext::SetCallBackNode(node);
5051         func->Execute(info, extraParams);
5052     };
5053 
5054     ViewAbstractModel::GetInstance()->SetOnDragLeave(std::move(onDragLeave));
5055 }
5056 
JsOnDrop(const JSCallbackInfo & info)5057 void JSViewAbstract::JsOnDrop(const JSCallbackInfo& info)
5058 {
5059     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
5060     if (!CheckJSCallbackInfo("JsOnDrop", info, checkList)) {
5061         return;
5062     }
5063     RefPtr<JsDragFunction> jsOnDropFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(info[0]));
5064     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5065     auto onDrop = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDropFunc), node = frameNode](
5066                       const RefPtr<OHOS::Ace::DragEvent>& info, const std::string& extraParams) {
5067         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5068         ACE_SCORING_EVENT("onDrop");
5069         PipelineContext::SetCallBackNode(node);
5070         func->Execute(info, extraParams);
5071     };
5072 
5073     ViewAbstractModel::GetInstance()->SetOnDrop(std::move(onDrop));
5074 }
5075 
JsOnAreaChange(const JSCallbackInfo & info)5076 void JSViewAbstract::JsOnAreaChange(const JSCallbackInfo& info)
5077 {
5078     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
5079         ViewAbstractModel::GetInstance()->DisableOnAreaChange();
5080         return;
5081     }
5082     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
5083     if (!CheckJSCallbackInfo("JsOnAreaChange", info, checkList)) {
5084         return;
5085     }
5086     auto jsOnAreaChangeFunction = AceType::MakeRefPtr<JsOnAreaChangeFunction>(JSRef<JSFunc>::Cast(info[0]));
5087 
5088     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5089     auto onAreaChanged = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAreaChangeFunction),
5090                              node = frameNode](
5091                              const Rect& oldRect, const Offset& oldOrigin, const Rect& rect, const Offset& origin) {
5092         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5093         ACE_SCORING_EVENT("onAreaChange");
5094         PipelineContext::SetCallBackNode(node);
5095         func->Execute(oldRect, oldOrigin, rect, origin);
5096     };
5097     ViewAbstractModel::GetInstance()->SetOnAreaChanged(std::move(onAreaChanged));
5098 }
5099 
5100 #ifndef WEARABLE_PRODUCT
JsBindPopup(const JSCallbackInfo & info)5101 void JSViewAbstract::JsBindPopup(const JSCallbackInfo& info)
5102 {
5103     if (info.Length() < 2) {
5104         return;
5105     }
5106     if ((!info[0]->IsBoolean() && !info[0]->IsObject()) || !info[1]->IsObject()) {
5107         return;
5108     }
5109     auto popupParam = AceType::MakeRefPtr<PopupParam>();
5110     // Set IsShow to popupParam
5111     if (info[0]->IsBoolean()) {
5112         popupParam->SetIsShow(info[0]->ToBoolean());
5113     } else {
5114         JSRef<JSObject> showObj = JSRef<JSObject>::Cast(info[0]);
5115         auto callback = ParseDoubleBindCallback(info, showObj);
5116         popupParam->SetOnStateChange(std::move(callback));
5117         popupParam->SetIsShow(showObj->GetProperty("value")->ToBoolean());
5118     }
5119     // Set popup to popupParam
5120     auto popupObj = JSRef<JSObject>::Cast(info[1]);
5121     if (popupObj->GetProperty("message")->IsString()) {
5122         ParsePopupParam(info, popupObj, popupParam); // Parse PopupOptions param
5123         ViewAbstractModel::GetInstance()->BindPopup(popupParam, nullptr);
5124     } else if (!popupObj->GetProperty("builder").IsEmpty()) {
5125         ParseCustomPopupParam(info, popupObj, popupParam); // Parse CustomPopupOptions param
5126         auto builderValue = popupObj->GetProperty("builder");
5127         auto builder = builderValue;
5128         if (!builderValue->IsObject()) {
5129             return;
5130         }
5131         if (!builderValue->IsFunction()) {
5132             JSRef<JSObject> builderObj;
5133             builderObj = JSRef<JSObject>::Cast(builderValue);
5134             builder = builderObj->GetProperty("builder");
5135             if (!builder->IsFunction()) {
5136                 return;
5137             }
5138         }
5139         if (popupParam->IsShow()) {
5140             auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
5141             CHECK_NULL_VOID(builderFunc);
5142             ViewStackModel::GetInstance()->NewScope();
5143             builderFunc->Execute();
5144             auto customNode = ViewStackModel::GetInstance()->Finish();
5145             ViewAbstractModel::GetInstance()->BindPopup(popupParam, customNode);
5146         } else {
5147             ViewAbstractModel::GetInstance()->BindPopup(popupParam, nullptr);
5148         }
5149     } else {
5150         return;
5151     }
5152 }
5153 #endif
5154 
JsLinearGradient(const JSCallbackInfo & info)5155 void JSViewAbstract::JsLinearGradient(const JSCallbackInfo& info)
5156 {
5157     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
5158     if (!CheckJSCallbackInfo("LinearGradient", info, checkList)) {
5159         NG::Gradient newGradient;
5160         newGradient.CreateGradientWithType(NG::GradientType::LINEAR);
5161         ViewAbstractModel::GetInstance()->SetLinearGradient(newGradient);
5162         return;
5163     }
5164     NG::Gradient newGradient;
5165     NewJsLinearGradient(info, newGradient);
5166     ViewAbstractModel::GetInstance()->SetLinearGradient(newGradient);
5167 }
5168 
NewJsLinearGradient(const JSCallbackInfo & info,NG::Gradient & newGradient)5169 void JSViewAbstract::NewJsLinearGradient(const JSCallbackInfo& info, NG::Gradient& newGradient)
5170 {
5171     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
5172     newGradient.CreateGradientWithType(NG::GradientType::LINEAR);
5173     // angle
5174     std::optional<float> degree;
5175     GetJsAngle("angle", jsObj, degree);
5176     if (degree) {
5177         newGradient.GetLinearGradient()->angle = CalcDimension(degree.value(), DimensionUnit::PX);
5178         degree.reset();
5179     }
5180     // direction
5181     auto direction = static_cast<GradientDirection>(
5182         jsObj->GetPropertyValue<int32_t>("direction", static_cast<int32_t>(GradientDirection::NONE)));
5183     switch (direction) {
5184         case GradientDirection::LEFT:
5185             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
5186             break;
5187         case GradientDirection::RIGHT:
5188             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
5189             break;
5190         case GradientDirection::TOP:
5191             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
5192             break;
5193         case GradientDirection::BOTTOM:
5194             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
5195             break;
5196         case GradientDirection::LEFT_TOP:
5197             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
5198             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
5199             break;
5200         case GradientDirection::LEFT_BOTTOM:
5201             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::LEFT;
5202             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
5203             break;
5204         case GradientDirection::RIGHT_TOP:
5205             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
5206             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::TOP;
5207             break;
5208         case GradientDirection::RIGHT_BOTTOM:
5209             newGradient.GetLinearGradient()->linearX = NG::GradientDirection::RIGHT;
5210             newGradient.GetLinearGradient()->linearY = NG::GradientDirection::BOTTOM;
5211             break;
5212         case GradientDirection::NONE:
5213         case GradientDirection::START_TO_END:
5214         case GradientDirection::END_TO_START:
5215         default:
5216             break;
5217     }
5218     auto repeating = jsObj->GetPropertyValue<bool>("repeating", false);
5219     newGradient.SetRepeat(repeating);
5220     NewGetJsGradientColorStops(newGradient, jsObj->GetProperty("colors"));
5221 }
5222 
JsRadialGradient(const JSCallbackInfo & info)5223 void JSViewAbstract::JsRadialGradient(const JSCallbackInfo& info)
5224 {
5225     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
5226     if (!CheckJSCallbackInfo("JsRadialGradient", info, checkList)) {
5227         NG::Gradient newGradient;
5228         newGradient.CreateGradientWithType(NG::GradientType::RADIAL);
5229         ViewAbstractModel::GetInstance()->SetRadialGradient(newGradient);
5230         return;
5231     }
5232     NG::Gradient newGradient;
5233     NewJsRadialGradient(info, newGradient);
5234     ViewAbstractModel::GetInstance()->SetRadialGradient(newGradient);
5235 }
5236 
NewJsRadialGradient(const JSCallbackInfo & info,NG::Gradient & newGradient)5237 void JSViewAbstract::NewJsRadialGradient(const JSCallbackInfo& info, NG::Gradient& newGradient)
5238 {
5239     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
5240     newGradient.CreateGradientWithType(NG::GradientType::RADIAL);
5241     // center
5242     JSRef<JSVal> center = jsObj->GetProperty("center");
5243     if (center->IsArray() && JSRef<JSArray>::Cast(center)->Length() == 2) {
5244         CalcDimension value;
5245         JSRef<JSArray> centerArray = JSRef<JSArray>::Cast(center);
5246         if (ParseJsDimensionVp(centerArray->GetValueAt(0), value)) {
5247             newGradient.GetRadialGradient()->radialCenterX = CalcDimension(value);
5248             if (value.Unit() == DimensionUnit::PERCENT) {
5249                 // [0,1] -> [0, 100]
5250                 newGradient.GetRadialGradient()->radialCenterX =
5251                     CalcDimension(value.Value() * 100.0, DimensionUnit::PERCENT);
5252             }
5253         }
5254         if (ParseJsDimensionVp(centerArray->GetValueAt(1), value)) {
5255             newGradient.GetRadialGradient()->radialCenterY = CalcDimension(value);
5256             if (value.Unit() == DimensionUnit::PERCENT) {
5257                 // [0,1] -> [0, 100]
5258                 newGradient.GetRadialGradient()->radialCenterY =
5259                     CalcDimension(value.Value() * 100.0, DimensionUnit::PERCENT);
5260             }
5261         }
5262     }
5263     // radius
5264     CalcDimension radius;
5265     if (ParseJsDimensionVp(jsObj->GetProperty("radius"), radius)) {
5266         newGradient.GetRadialGradient()->radialVerticalSize = CalcDimension(radius);
5267         newGradient.GetRadialGradient()->radialHorizontalSize = CalcDimension(radius);
5268     }
5269     // repeating
5270     auto repeating = jsObj->GetPropertyValue<bool>("repeating", false);
5271     newGradient.SetRepeat(repeating);
5272     // color stops
5273     NewGetJsGradientColorStops(newGradient, jsObj->GetProperty("colors"));
5274 }
5275 
JsSweepGradient(const JSCallbackInfo & info)5276 void JSViewAbstract::JsSweepGradient(const JSCallbackInfo& info)
5277 {
5278     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
5279     if (!CheckJSCallbackInfo("JsSweepGradient", info, checkList)) {
5280         NG::Gradient newGradient;
5281         newGradient.CreateGradientWithType(NG::GradientType::SWEEP);
5282         ViewAbstractModel::GetInstance()->SetSweepGradient(newGradient);
5283         return;
5284     }
5285 
5286     NG::Gradient newGradient;
5287     NewJsSweepGradient(info, newGradient);
5288     ViewAbstractModel::GetInstance()->SetSweepGradient(newGradient);
5289 }
5290 
NewJsSweepGradient(const JSCallbackInfo & info,NG::Gradient & newGradient)5291 void JSViewAbstract::NewJsSweepGradient(const JSCallbackInfo& info, NG::Gradient& newGradient)
5292 {
5293     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
5294     newGradient.CreateGradientWithType(NG::GradientType::SWEEP);
5295     // center
5296     JSRef<JSVal> center = jsObj->GetProperty("center");
5297     if (center->IsArray() && JSRef<JSArray>::Cast(center)->Length() == 2) {
5298         CalcDimension value;
5299         JSRef<JSArray> centerArray = JSRef<JSArray>::Cast(center);
5300         if (ParseJsDimensionVp(centerArray->GetValueAt(0), value)) {
5301             newGradient.GetSweepGradient()->centerX = CalcDimension(value);
5302             if (value.Unit() == DimensionUnit::PERCENT) {
5303                 // [0,1] -> [0, 100]
5304                 newGradient.GetSweepGradient()->centerX = CalcDimension(value.Value() * 100.0, DimensionUnit::PERCENT);
5305             }
5306         }
5307         if (ParseJsDimensionVp(centerArray->GetValueAt(1), value)) {
5308             newGradient.GetSweepGradient()->centerY = CalcDimension(value);
5309             if (value.Unit() == DimensionUnit::PERCENT) {
5310                 // [0,1] -> [0, 100]
5311                 newGradient.GetSweepGradient()->centerY = CalcDimension(value.Value() * 100.0, DimensionUnit::PERCENT);
5312             }
5313         }
5314     }
5315     std::optional<float> degree;
5316     // start
5317     GetJsAngle("start", jsObj, degree);
5318     if (degree) {
5319         CheckAngle(degree);
5320         newGradient.GetSweepGradient()->startAngle = CalcDimension(degree.value(), DimensionUnit::PX);
5321         degree.reset();
5322     }
5323     // end
5324     GetJsAngle("end", jsObj, degree);
5325     if (degree) {
5326         CheckAngle(degree);
5327         newGradient.GetSweepGradient()->endAngle = CalcDimension(degree.value(), DimensionUnit::PX);
5328         degree.reset();
5329     }
5330     // rotation
5331     GetJsAngle("rotation", jsObj, degree);
5332     if (degree) {
5333         CheckAngle(degree);
5334         newGradient.GetSweepGradient()->rotation = CalcDimension(degree.value(), DimensionUnit::PX);
5335         degree.reset();
5336     }
5337     // repeating
5338     auto repeating = jsObj->GetPropertyValue<bool>("repeating", false);
5339     newGradient.SetRepeat(repeating);
5340     // color stops
5341     NewGetJsGradientColorStops(newGradient, jsObj->GetProperty("colors"));
5342 }
5343 
JsMotionPath(const JSCallbackInfo & info)5344 void JSViewAbstract::JsMotionPath(const JSCallbackInfo& info)
5345 {
5346     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT };
5347     if (!CheckJSCallbackInfo("JsMotionPath", info, checkList)) {
5348         ViewAbstractModel::GetInstance()->SetMotionPath(MotionPathOption());
5349         return;
5350     }
5351     MotionPathOption motionPathOption;
5352     if (ParseMotionPath(info[0], motionPathOption)) {
5353         ViewAbstractModel::GetInstance()->SetMotionPath(motionPathOption);
5354     } else {
5355         LOGI("Parse animation motionPath failed. %{public}s", info[0]->ToString().c_str());
5356         ViewAbstractModel::GetInstance()->SetMotionPath(MotionPathOption());
5357     }
5358 }
5359 
JsShadow(const JSCallbackInfo & info)5360 void JSViewAbstract::JsShadow(const JSCallbackInfo& info)
5361 {
5362     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT, JSCallbackInfoType::NUMBER };
5363     if (!CheckJSCallbackInfo("JsShadow", info, checkList)) {
5364         Shadow shadow;
5365         std::vector<Shadow> shadows { shadow };
5366         ViewAbstractModel::GetInstance()->SetBackShadow(shadows);
5367         return;
5368     }
5369     Shadow shadow;
5370     if (!ParseShadowProps(info[0], shadow)) {
5371         info.ReturnSelf();
5372         return;
5373     }
5374     std::vector<Shadow> shadows { shadow };
5375     ViewAbstractModel::GetInstance()->SetBackShadow(shadows);
5376 }
5377 
JsBlendMode(const JSCallbackInfo & info)5378 void JSViewAbstract::JsBlendMode(const JSCallbackInfo& info)
5379 {
5380     if (info.Length() == 0) {
5381         return;
5382     }
5383     BlendMode blendMode = BlendMode::NONE;
5384     BlendApplyType blendApplyType = BlendApplyType::FAST;
5385     // for backward compatible, we temporary add a magic number to trigger offscreen, will remove soon
5386     constexpr int BACKWARD_COMPAT_MAGIC_NUMBER_OFFSCREEN = 1000;
5387     if (info[0]->IsNumber()) {
5388         auto blendModeNum = info[0]->ToNumber<int32_t>();
5389         if (blendModeNum >= static_cast<int>(BlendMode::NONE) &&
5390             blendModeNum <= static_cast<int>(BlendMode::LUMINOSITY)) {
5391             blendMode = static_cast<BlendMode>(blendModeNum);
5392         } else if (blendModeNum == BACKWARD_COMPAT_MAGIC_NUMBER_OFFSCREEN) {
5393             // backward compatibility code, will remove soon
5394             blendMode = BlendMode::SRC_OVER;
5395             blendApplyType = BlendApplyType::OFFSCREEN;
5396         }
5397     }
5398     if (info.Length() >= PARAMETER_LENGTH_SECOND && info[1]->IsNumber()) {
5399         auto blendApplyTypeNum = info[1]->ToNumber<int32_t>();
5400         if (blendApplyTypeNum >= static_cast<int>(BlendApplyType::FAST) &&
5401             blendApplyTypeNum <= static_cast<int>(BlendApplyType::OFFSCREEN)) {
5402             blendApplyType = static_cast<BlendApplyType>(blendApplyTypeNum);
5403         }
5404     }
5405     ViewAbstractModel::GetInstance()->SetBlendMode(blendMode);
5406     ViewAbstractModel::GetInstance()->SetBlendApplyType(blendApplyType);
5407 }
5408 
JsGrayScale(const JSCallbackInfo & info)5409 void JSViewAbstract::JsGrayScale(const JSCallbackInfo& info)
5410 {
5411     CalcDimension value;
5412     if (!ParseJsDimensionVp(info[0], value)) {
5413         value.SetValue(0.0);
5414         ViewAbstractModel::GetInstance()->SetGrayScale(value);
5415         return;
5416     }
5417 
5418     if (LessNotEqual(value.Value(), 0.0)) {
5419         value.SetValue(0.0);
5420     }
5421 
5422     if (GreatNotEqual(value.Value(), 1.0)) {
5423         value.SetValue(1.0);
5424     }
5425 
5426     ViewAbstractModel::GetInstance()->SetGrayScale(value);
5427 }
5428 
JsBrightness(const JSCallbackInfo & info)5429 void JSViewAbstract::JsBrightness(const JSCallbackInfo& info)
5430 {
5431     CalcDimension value;
5432     if (!ParseJsDimensionVp(info[0], value)) {
5433         value.SetValue(1.0);
5434         ViewAbstractModel::GetInstance()->SetBrightness(value);
5435         return;
5436     }
5437 
5438     ViewAbstractModel::GetInstance()->SetBrightness(value);
5439 }
5440 
JsContrast(const JSCallbackInfo & info)5441 void JSViewAbstract::JsContrast(const JSCallbackInfo& info)
5442 {
5443     CalcDimension value;
5444     if (!ParseJsDimensionVp(info[0], value)) {
5445         value.SetValue(1.0);
5446         ViewAbstractModel::GetInstance()->SetContrast(value);
5447         return;
5448     }
5449 
5450     if (LessNotEqual(value.Value(), 0.0)) {
5451         value.SetValue(0.0);
5452     }
5453 
5454     ViewAbstractModel::GetInstance()->SetContrast(value);
5455 }
5456 
JsSaturate(const JSCallbackInfo & info)5457 void JSViewAbstract::JsSaturate(const JSCallbackInfo& info)
5458 {
5459     CalcDimension value;
5460     if (!ParseJsDimensionVp(info[0], value)) {
5461         value.SetValue(1.0);
5462         ViewAbstractModel::GetInstance()->SetSaturate(value);
5463         return;
5464     }
5465 
5466     if (LessNotEqual(value.Value(), 0.0)) {
5467         value.SetValue(0.0);
5468     }
5469 
5470     ViewAbstractModel::GetInstance()->SetSaturate(value);
5471 }
5472 
JsSepia(const JSCallbackInfo & info)5473 void JSViewAbstract::JsSepia(const JSCallbackInfo& info)
5474 {
5475     CalcDimension value;
5476     if (!ParseJsDimensionVp(info[0], value)) {
5477         value.SetValue(0.0);
5478         ViewAbstractModel::GetInstance()->SetSepia(value);
5479         return;
5480     }
5481 
5482     if (LessNotEqual(value.Value(), 0.0)) {
5483         value.SetValue(0.0);
5484     }
5485 
5486     ViewAbstractModel::GetInstance()->SetSepia(value);
5487 }
5488 
ParseInvertProps(const JSRef<JSVal> & jsValue,InvertVariant & invert)5489 bool JSViewAbstract::ParseInvertProps(const JSRef<JSVal>& jsValue, InvertVariant& invert)
5490 {
5491     double invertValue = 0.0;
5492     if (ParseJsDouble(jsValue, invertValue)) {
5493         invert = static_cast<float>(std::clamp(invertValue, 0.0, 1.0));
5494         return true;
5495     }
5496     auto argsPtrItem = JsonUtil::ParseJsonString(jsValue->ToString());
5497     if (!argsPtrItem || argsPtrItem->IsNull()) {
5498         return false;
5499     }
5500     InvertOption option;
5501     double low = 0.0;
5502     if (ParseJsonDouble(argsPtrItem->GetValue("low"), low)) {
5503         option.low_ = std::clamp(low, 0.0, 1.0);
5504     }
5505     double high = 0.0;
5506     if (ParseJsonDouble(argsPtrItem->GetValue("high"), high)) {
5507         option.high_ = std::clamp(high, 0.0, 1.0);
5508     }
5509     double threshold = 0.0;
5510     if (ParseJsonDouble(argsPtrItem->GetValue("threshold"), threshold)) {
5511         option.threshold_ = std::clamp(threshold, 0.0, 1.0);
5512     }
5513     double thresholdRange = 0.0;
5514     if (ParseJsonDouble(argsPtrItem->GetValue("thresholdRange"), thresholdRange)) {
5515         option.thresholdRange_ = std::clamp(thresholdRange, 0.0, 1.0);
5516     }
5517     invert = option;
5518     return true;
5519 }
5520 
JsInvert(const JSCallbackInfo & info)5521 void JSViewAbstract::JsInvert(const JSCallbackInfo& info)
5522 {
5523     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::OBJECT, JSCallbackInfoType::NUMBER };
5524     InvertVariant invert = 0.0f;
5525     if (!CheckJSCallbackInfo("JsInvert", info, checkList)) {
5526         ViewAbstractModel::GetInstance()->SetInvert(invert);
5527         return;
5528     }
5529     if (ParseInvertProps(info[0], invert)) {
5530         ViewAbstractModel::GetInstance()->SetInvert(invert);
5531     }
5532     ViewAbstractModel::GetInstance()->SetInvert(invert);
5533 }
5534 
JsSystemBarEffect(const JSCallbackInfo & info)5535 void JSViewAbstract::JsSystemBarEffect(const JSCallbackInfo& info)
5536 {
5537     ViewAbstractModel::GetInstance()->SetSystemBarEffect(true);
5538 }
5539 
JsHueRotate(const JSCallbackInfo & info)5540 void JSViewAbstract::JsHueRotate(const JSCallbackInfo& info)
5541 {
5542     std::optional<float> degree;
5543     JSRef<JSVal> arg = info[0];
5544     if (arg->IsString()) {
5545         degree = static_cast<float>(StringUtils::StringToDegree(arg->ToString()));
5546     } else if (arg->IsNumber()) {
5547         degree = static_cast<float>(arg->ToNumber<int32_t>());
5548     } else {
5549         ViewAbstractModel::GetInstance()->SetHueRotate(0.0);
5550         return;
5551     }
5552     float deg = 0.0f;
5553     if (degree) {
5554         deg = degree.value();
5555         degree.reset();
5556     }
5557     deg = std::fmod(deg, ROUND_UNIT);
5558     if (deg < 0.0f) {
5559         deg += ROUND_UNIT;
5560     }
5561     ViewAbstractModel::GetInstance()->SetHueRotate(deg);
5562 }
5563 
JsClip(const JSCallbackInfo & info)5564 void JSViewAbstract::JsClip(const JSCallbackInfo& info)
5565 {
5566     JSRef<JSVal> arg = info[0];
5567     if (arg->IsUndefined()) {
5568         ViewAbstractModel::GetInstance()->SetClipEdge(false);
5569         return;
5570     }
5571     if (arg->IsObject()) {
5572         JSShapeAbstract* clipShape = JSRef<JSObject>::Cast(arg)->Unwrap<JSShapeAbstract>();
5573         if (clipShape == nullptr) {
5574             return;
5575         }
5576         ViewAbstractModel::GetInstance()->SetClipShape(clipShape->GetBasicShape());
5577     } else if (arg->IsBoolean()) {
5578         ViewAbstractModel::GetInstance()->SetClipEdge(arg->ToBoolean());
5579     }
5580 }
5581 
JsMask(const JSCallbackInfo & info)5582 void JSViewAbstract::JsMask(const JSCallbackInfo& info)
5583 {
5584     JSRef<JSVal> arg = info[0];
5585     if (!arg->IsObject()) {
5586         ViewAbstractModel::GetInstance()->SetProgressMask(nullptr);
5587         return;
5588     }
5589     auto paramObject = JSRef<JSObject>::Cast(arg);
5590     JSRef<JSVal> typeParam = paramObject->GetProperty("type");
5591     if (!typeParam->IsNull() && !typeParam->IsUndefined() && typeParam->IsString() &&
5592         typeParam->ToString() == "ProgressMask") {
5593         auto progressMask = AceType::MakeRefPtr<NG::ProgressMaskProperty>();
5594         JSRef<JSVal> jValue = paramObject->GetProperty("value");
5595         auto value = jValue->IsNumber() ? jValue->ToNumber<float>() : 0.0f;
5596         if (value < 0.0f) {
5597             value = 0.0f;
5598         }
5599         progressMask->SetValue(value);
5600         JSRef<JSVal> jTotal = paramObject->GetProperty("total");
5601         auto total = jTotal->IsNumber() ? jTotal->ToNumber<float>() : DEFAULT_PROGRESS_TOTAL;
5602         if (total < 0.0f) {
5603             total = DEFAULT_PROGRESS_TOTAL;
5604         }
5605         progressMask->SetMaxValue(total);
5606         JSRef<JSVal> jColor = paramObject->GetProperty("color");
5607         Color colorVal;
5608         if (ParseJsColor(jColor, colorVal)) {
5609             progressMask->SetColor(colorVal);
5610         } else {
5611             RefPtr<ProgressTheme> theme = GetTheme<ProgressTheme>();
5612             progressMask->SetColor(theme->GetMaskColor());
5613         }
5614         ViewAbstractModel::GetInstance()->SetProgressMask(progressMask);
5615     } else {
5616         JSShapeAbstract* maskShape = JSRef<JSObject>::Cast(arg)->Unwrap<JSShapeAbstract>();
5617         if (maskShape == nullptr) {
5618             return;
5619         };
5620         ViewAbstractModel::GetInstance()->SetMask(maskShape->GetBasicShape());
5621     }
5622 }
5623 
JsFocusable(const JSCallbackInfo & info)5624 void JSViewAbstract::JsFocusable(const JSCallbackInfo& info)
5625 {
5626     if (!info[0]->IsBoolean()) {
5627         return;
5628     }
5629     ViewAbstractModel::GetInstance()->SetFocusable(info[0]->ToBoolean());
5630 }
5631 
JsOnFocusMove(const JSCallbackInfo & args)5632 void JSViewAbstract::JsOnFocusMove(const JSCallbackInfo& args)
5633 {
5634     JSRef<JSVal> arg = args[0];
5635     if (arg->IsFunction()) {
5636         RefPtr<JsFocusFunction> jsOnFocusMove = AceType::MakeRefPtr<JsFocusFunction>(JSRef<JSFunc>::Cast(arg));
5637         WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5638         auto onFocusMove = [execCtx = args.GetExecutionContext(), func = std::move(jsOnFocusMove), node = frameNode](
5639                                int info) {
5640             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5641             ACE_SCORING_EVENT("onFocusMove");
5642             PipelineContext::SetCallBackNode(node);
5643             func->Execute(info);
5644         };
5645         ViewAbstractModel::GetInstance()->SetOnFocusMove(std::move(onFocusMove));
5646     }
5647 }
5648 
JsOnKeyEvent(const JSCallbackInfo & args)5649 void JSViewAbstract::JsOnKeyEvent(const JSCallbackInfo& args)
5650 {
5651     JSRef<JSVal> arg = args[0];
5652     if (arg->IsUndefined() && IsDisableEventVersion()) {
5653         ViewAbstractModel::GetInstance()->DisableOnKeyEvent();
5654         return;
5655     }
5656     if (!arg->IsFunction()) {
5657         return;
5658     }
5659     RefPtr<JsKeyFunction> JsOnKeyEvent = AceType::MakeRefPtr<JsKeyFunction>(JSRef<JSFunc>::Cast(arg));
5660     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5661     auto onKeyEvent = [execCtx = args.GetExecutionContext(), func = std::move(JsOnKeyEvent), node = frameNode](
5662                           KeyEventInfo& info) {
5663         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5664         ACE_SCORING_EVENT("onKey");
5665         PipelineContext::SetCallBackNode(node);
5666         func->Execute(info);
5667     };
5668     ViewAbstractModel::GetInstance()->SetOnKeyEvent(std::move(onKeyEvent));
5669 }
5670 
JsOnFocus(const JSCallbackInfo & args)5671 void JSViewAbstract::JsOnFocus(const JSCallbackInfo& args)
5672 {
5673     JSRef<JSVal> arg = args[0];
5674     if (arg->IsUndefined() && IsDisableEventVersion()) {
5675         ViewAbstractModel::GetInstance()->DisableOnFocus();
5676         return;
5677     }
5678     if (!arg->IsFunction()) {
5679         return;
5680     }
5681     RefPtr<JsFocusFunction> jsOnFocus = AceType::MakeRefPtr<JsFocusFunction>(JSRef<JSFunc>::Cast(arg));
5682     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5683     auto onFocus = [execCtx = args.GetExecutionContext(), func = std::move(jsOnFocus), node = frameNode]() {
5684         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5685         ACE_SCORING_EVENT("onFocus");
5686         PipelineContext::SetCallBackNode(node);
5687         func->Execute();
5688     };
5689 
5690     ViewAbstractModel::GetInstance()->SetOnFocus(std::move(onFocus));
5691 }
5692 
JsOnBlur(const JSCallbackInfo & args)5693 void JSViewAbstract::JsOnBlur(const JSCallbackInfo& args)
5694 {
5695     JSRef<JSVal> arg = args[0];
5696     if (arg->IsUndefined() && IsDisableEventVersion()) {
5697         ViewAbstractModel::GetInstance()->DisableOnBlur();
5698         return;
5699     }
5700     if (!arg->IsFunction()) {
5701         return;
5702     }
5703     RefPtr<JsFocusFunction> jsOnBlur = AceType::MakeRefPtr<JsFocusFunction>(JSRef<JSFunc>::Cast(arg));
5704     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5705     auto onBlur = [execCtx = args.GetExecutionContext(), func = std::move(jsOnBlur), node = frameNode]() {
5706         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5707         ACE_SCORING_EVENT("onBlur");
5708         PipelineContext::SetCallBackNode(node);
5709         func->Execute();
5710     };
5711 
5712     ViewAbstractModel::GetInstance()->SetOnBlur(std::move(onBlur));
5713 }
5714 
JsTabIndex(const JSCallbackInfo & info)5715 void JSViewAbstract::JsTabIndex(const JSCallbackInfo& info)
5716 {
5717     JSRef<JSVal> arg = info[0];
5718     if (!arg->IsNumber()) {
5719         return;
5720     }
5721     ViewAbstractModel::GetInstance()->SetTabIndex(arg->ToNumber<int32_t>());
5722 }
5723 
JsFocusOnTouch(const JSCallbackInfo & info)5724 void JSViewAbstract::JsFocusOnTouch(const JSCallbackInfo& info)
5725 {
5726     JSRef<JSVal> arg = info[0];
5727     if (!arg->IsBoolean()) {
5728         return;
5729     }
5730     auto isFocusOnTouch = arg->ToBoolean();
5731     ViewAbstractModel::GetInstance()->SetFocusOnTouch(isFocusOnTouch);
5732 }
5733 
JsDefaultFocus(const JSCallbackInfo & info)5734 void JSViewAbstract::JsDefaultFocus(const JSCallbackInfo& info)
5735 {
5736     JSRef<JSVal> arg = info[0];
5737     if (!arg->IsBoolean()) {
5738         return;
5739     }
5740     auto isDefaultFocus = arg->ToBoolean();
5741     ViewAbstractModel::GetInstance()->SetDefaultFocus(isDefaultFocus);
5742 }
5743 
JsGroupDefaultFocus(const JSCallbackInfo & info)5744 void JSViewAbstract::JsGroupDefaultFocus(const JSCallbackInfo& info)
5745 {
5746     JSRef<JSVal> arg = info[0];
5747     if (!arg->IsBoolean()) {
5748         return;
5749     }
5750     auto isGroupDefaultFocus = arg->ToBoolean();
5751     ViewAbstractModel::GetInstance()->SetGroupDefaultFocus(isGroupDefaultFocus);
5752 }
5753 
JsKey(const std::string & key)5754 void JSViewAbstract::JsKey(const std::string& key)
5755 {
5756     ViewAbstractModel::GetInstance()->SetInspectorId(key);
5757 }
5758 
JsId(const JSCallbackInfo & info)5759 void JSViewAbstract::JsId(const JSCallbackInfo& info)
5760 {
5761     JSRef<JSVal> arg = info[0];
5762     if (!arg->IsString() || arg->IsNull() || arg->IsUndefined()) {
5763         return;
5764     }
5765     std::string id = arg->ToString();
5766     if (id.empty()) {
5767         return;
5768     }
5769     JsKey(id);
5770 }
5771 
JsRestoreId(int32_t restoreId)5772 void JSViewAbstract::JsRestoreId(int32_t restoreId)
5773 {
5774     ViewAbstractModel::GetInstance()->SetRestoreId(restoreId);
5775 }
5776 
JsDebugLine(const JSCallbackInfo & info)5777 void JSViewAbstract::JsDebugLine(const JSCallbackInfo& info)
5778 {
5779     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING };
5780     if (!CheckJSCallbackInfo("JsDebugLine", info, checkList)) {
5781         return;
5782     }
5783 
5784     ViewAbstractModel::GetInstance()->SetDebugLine(info[0]->ToString());
5785 }
5786 
JsOpacityPassThrough(const JSCallbackInfo & info)5787 void JSViewAbstract::JsOpacityPassThrough(const JSCallbackInfo& info)
5788 {
5789     double opacity = 0.0;
5790     if (!ParseJsDouble(info[0], opacity)) {
5791         return;
5792     }
5793 
5794     if ((LessNotEqual(opacity, 0.0)) || opacity > 1) {
5795         opacity = 1.0;
5796     }
5797 
5798     ViewAbstractModel::GetInstance()->SetOpacity(opacity, true);
5799 }
5800 
JsTransitionPassThrough(const JSCallbackInfo & info)5801 void JSViewAbstract::JsTransitionPassThrough(const JSCallbackInfo& info)
5802 {
5803     if (info.Length() > 1) {
5804         return;
5805     }
5806     if (info.Length() == 0) {
5807         ViewAbstractModel::GetInstance()->SetTransition(
5808             NG::TransitionOptions::GetDefaultTransition(TransitionType::ALL));
5809         return;
5810     }
5811     if (!info[0]->IsObject()) {
5812         return;
5813     }
5814     auto obj = JSRef<JSObject>::Cast(info[0]);
5815     if (!obj->GetProperty("successor_")->IsUndefined()) {
5816         auto chainedEffect = ParseChainedTransition(obj, info.GetExecutionContext());
5817         ViewAbstractModel::GetInstance()->SetChainedTransition(chainedEffect);
5818         return;
5819     }
5820     auto options = ParseJsTransition(obj);
5821     ViewAbstractModel::GetInstance()->SetTransition(options, true);
5822 }
5823 
JsAccessibilityGroup(bool accessible)5824 void JSViewAbstract::JsAccessibilityGroup(bool accessible)
5825 {
5826     ViewAbstractModel::GetInstance()->SetAccessibilityGroup(accessible);
5827 }
5828 
JsAccessibilityText(const std::string & text)5829 void JSViewAbstract::JsAccessibilityText(const std::string& text)
5830 {
5831     ViewAbstractModel::GetInstance()->SetAccessibilityText(text);
5832 }
5833 
JsAccessibilityDescription(const std::string & description)5834 void JSViewAbstract::JsAccessibilityDescription(const std::string& description)
5835 {
5836     std::pair<bool, std::string> autoEventPair(false, "");
5837     std::pair<bool, std::string> descriptionPair(false, "");
5838     ParseAccessibilityDescriptionJson(description, autoEventPair, descriptionPair);
5839     if (descriptionPair.first) {
5840         ViewAbstractModel::GetInstance()->SetAccessibilityDescription(descriptionPair.second);
5841     } else {
5842         ViewAbstractModel::GetInstance()->SetAccessibilityDescription(description);
5843     }
5844     if (autoEventPair.first) {
5845         ViewAbstractModel::GetInstance()->SetAutoEventParam(autoEventPair.second);
5846     }
5847 }
5848 
ParseAccessibilityDescriptionJson(const std::string & description,std::pair<bool,std::string> & autoEventPair,std::pair<bool,std::string> & descriptionPair)5849 void JSViewAbstract::ParseAccessibilityDescriptionJson(const std::string& description,
5850     std::pair<bool, std::string>& autoEventPair, std::pair<bool, std::string>& descriptionPair)
5851 {
5852     if (description.empty()) {
5853         return;
5854     }
5855     if (!StartWith(description, "{") || !EndWith(description, "}")) {
5856         return;
5857     }
5858     auto jsonObj = JsonUtil::ParseJsonString(description);
5859     if (!jsonObj || !jsonObj->IsValid() || !jsonObj->IsObject()) {
5860         return;
5861     }
5862     if (jsonObj->Contains("$autoEventParam")) {
5863         auto param = jsonObj->GetValue("$autoEventParam");
5864         if (param) {
5865             autoEventPair = std::make_pair(true, param->ToString());
5866         }
5867     }
5868     if (jsonObj->Contains("$accessibilityDescription")) {
5869         descriptionPair = std::make_pair(true, jsonObj->GetString("$accessibilityDescription"));
5870     } else if (jsonObj->Contains("$autoEventParam")) {
5871         descriptionPair = std::make_pair(true, "");
5872     }
5873 }
5874 
JsAccessibilityImportance(const std::string & importance)5875 void JSViewAbstract::JsAccessibilityImportance(const std::string& importance)
5876 {
5877     ViewAbstractModel::GetInstance()->SetAccessibilityImportance(importance);
5878 }
5879 
JsAccessibilityLevel(const std::string & level)5880 void JSViewAbstract::JsAccessibilityLevel(const std::string& level)
5881 {
5882     ViewAbstractModel::GetInstance()->SetAccessibilityImportance(level);
5883 }
5884 
JsAccessibilityVirtualNode(const JSCallbackInfo & info)5885 void JSViewAbstract::JsAccessibilityVirtualNode(const JSCallbackInfo& info)
5886 {
5887     // parse builder
5888     if (!info[0]->IsObject()) {
5889         return;
5890     }
5891     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
5892     auto builder = obj->GetProperty("builder");
5893 
5894     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
5895     CHECK_NULL_VOID(builderFunc);
5896     auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc)]() {
5897         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5898         ACE_SCORING_EVENT("AccessibilityVirtualNode");
5899         func->Execute();
5900     };
5901     NG::ViewAbstractModelNG::GetInstance()->SetAccessibilityVirtualNode(std::move(buildFunc));
5902 }
5903 
JsBackground(const JSCallbackInfo & info)5904 void JSViewAbstract::JsBackground(const JSCallbackInfo& info)
5905 {
5906     // Check the parameters
5907     if (info.Length() <= 0 || !info[0]->IsObject()) {
5908         return;
5909     }
5910     JSRef<JSObject> backgroundObj = JSRef<JSObject>::Cast(info[0]);
5911     auto builder = backgroundObj->GetProperty("builder");
5912     if (!builder->IsFunction()) {
5913         return;
5914     }
5915     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
5916     CHECK_NULL_VOID(builderFunc);
5917     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5918     auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = frameNode]() {
5919         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5920         ACE_SCORING_EVENT("BindBackground");
5921         PipelineContext::SetCallBackNode(node);
5922         func->Execute();
5923     };
5924     Alignment alignment = Alignment::CENTER;
5925     if (info.Length() >= PARAMETER_LENGTH_SECOND && info[1]->IsObject()) {
5926         JSRef<JSObject> object = JSRef<JSObject>::Cast(info[1]);
5927         auto align = object->GetProperty("align");
5928         auto value = align->ToNumber<int32_t>();
5929         alignment = ParseAlignment(value);
5930     }
5931     ViewAbstractModel::GetInstance()->BindBackground(std::move(buildFunc), alignment);
5932 }
5933 
JsBindContextMenu(const JSCallbackInfo & info)5934 void JSViewAbstract::JsBindContextMenu(const JSCallbackInfo& info)
5935 {
5936     // Check the parameters
5937     if (info.Length() <= 0 || !info[0]->IsObject()) {
5938         return;
5939     }
5940     JSRef<JSObject> menuObj = JSRef<JSObject>::Cast(info[0]);
5941     auto builder = menuObj->GetProperty("builder");
5942     if (!builder->IsFunction()) {
5943         return;
5944     }
5945     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
5946     CHECK_NULL_VOID(builderFunc);
5947 
5948     ResponseType responseType = ResponseType::LONG_PRESS;
5949     if (info.Length() >= PARAMETER_LENGTH_SECOND && info[1]->IsNumber()) {
5950         auto response = info[1]->ToNumber<int32_t>();
5951         responseType = static_cast<ResponseType>(response);
5952     }
5953     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
5954     std::function<void()> buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc),
5955                                           node = frameNode]() {
5956         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
5957         ACE_SCORING_EVENT("BuildContextMenu");
5958         PipelineContext::SetCallBackNode(node);
5959         func->Execute();
5960     };
5961 
5962     NG::MenuParam menuParam;
5963     menuParam.previewMode = MenuPreviewMode::NONE;
5964     std::function<void()> previewBuildFunc = nullptr;
5965     if (info.Length() >= PARAMETER_LENGTH_THIRD && info[2]->IsObject()) {
5966         ParseBindContentOptionParam(info, info[2], menuParam, previewBuildFunc);
5967     }
5968     if (responseType != ResponseType::LONG_PRESS) {
5969         menuParam.previewMode = MenuPreviewMode::NONE;
5970     }
5971     menuParam.type = NG::MenuType::CONTEXT_MENU;
5972     ViewAbstractModel::GetInstance()->BindContextMenu(responseType, buildFunc, menuParam, previewBuildFunc);
5973 }
5974 
JsBindContentCover(const JSCallbackInfo & info)5975 void JSViewAbstract::JsBindContentCover(const JSCallbackInfo& info)
5976 {
5977     // parse isShow
5978     bool isShow = false;
5979     DoubleBindCallback callback = nullptr;
5980     if (info[0]->IsBoolean()) {
5981         isShow = info[0]->ToBoolean();
5982     } else if (info[0]->IsObject()) {
5983         JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(info[0]);
5984         callback = ParseDoubleBindCallback(info, callbackObj);
5985         auto isShowObj = callbackObj->GetProperty("value");
5986         isShow = isShowObj->IsBoolean() ? isShowObj->ToBoolean() : false;
5987     }
5988 
5989     // parse builder
5990     if (!info[1]->IsObject()) {
5991         return;
5992     }
5993     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
5994     auto builder = obj->GetProperty("builder");
5995     if (!builder->IsFunction()) {
5996         return;
5997     }
5998     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
5999     CHECK_NULL_VOID(builderFunc);
6000     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
6001     auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = frameNode]() {
6002         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6003         ACE_SCORING_EVENT("BindContentCover");
6004         PipelineContext::SetCallBackNode(node);
6005         func->Execute();
6006     };
6007 
6008     // parse ModalTransition
6009     NG::ModalStyle modalStyle;
6010     modalStyle.modalTransition = NG::ModalTransition::DEFAULT;
6011     std::function<void()> onShowCallback;
6012     std::function<void()> onDismissCallback;
6013     if (info.Length() == 3) {
6014         if (info[2]->IsObject()) {
6015             ParseOverlayCallback(info[2], onShowCallback, onDismissCallback);
6016             ParseModalStyle(info[2], modalStyle);
6017         } else if (info[2]->IsNumber()) {
6018             auto transitionNumber = info[2]->ToNumber<int32_t>();
6019             if (transitionNumber >= 0 && transitionNumber <= 2) {
6020                 modalStyle.modalTransition = static_cast<NG::ModalTransition>(transitionNumber);
6021             }
6022         }
6023     }
6024     ViewAbstractModel::GetInstance()->BindContentCover(isShow, std::move(callback), std::move(buildFunc), modalStyle,
6025         std::move(onShowCallback), std::move(onDismissCallback));
6026 }
6027 
ParseModalStyle(const JSRef<JSObject> & paramObj,NG::ModalStyle & modalStyle)6028 void JSViewAbstract::ParseModalStyle(const JSRef<JSObject>& paramObj, NG::ModalStyle& modalStyle)
6029 {
6030     auto modalTransition = paramObj->GetProperty("modalTransition");
6031     auto backgroundColor = paramObj->GetProperty("backgroundColor");
6032     if (modalTransition->IsNumber()) {
6033         auto transitionNumber = modalTransition->ToNumber<int32_t>();
6034         if (transitionNumber >= 0 && transitionNumber <= 2) {
6035             modalStyle.modalTransition = static_cast<NG::ModalTransition>(transitionNumber);
6036         }
6037     }
6038     Color color;
6039     if (ParseJsColor(backgroundColor, color)) {
6040         modalStyle.backgroundColor = color;
6041     }
6042 }
6043 
JsBindSheet(const JSCallbackInfo & info)6044 void JSViewAbstract::JsBindSheet(const JSCallbackInfo& info)
6045 {
6046     // parse isShow
6047     bool isShow = false;
6048     DoubleBindCallback callback = nullptr;
6049     if (info[0]->IsBoolean()) {
6050         isShow = info[0]->ToBoolean();
6051     } else if (info[0]->IsObject()) {
6052         JSRef<JSObject> callbackObj = JSRef<JSObject>::Cast(info[0]);
6053         callback = ParseDoubleBindCallback(info, callbackObj);
6054         auto isShowObj = callbackObj->GetProperty("value");
6055         isShow = isShowObj->IsBoolean() ? isShowObj->ToBoolean() : false;
6056     }
6057 
6058     // parse builder
6059     if (!info[1]->IsObject()) {
6060         return;
6061     }
6062     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
6063     auto builder = obj->GetProperty("builder");
6064     if (!builder->IsFunction()) {
6065         return;
6066     }
6067     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
6068     CHECK_NULL_VOID(builderFunc);
6069     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
6070     auto buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = frameNode]() {
6071         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6072         ACE_SCORING_EVENT("BindSheet");
6073         PipelineContext::SetCallBackNode(node);
6074         func->Execute();
6075     };
6076 
6077     // parse SheetStyle and callbacks
6078     NG::SheetStyle sheetStyle;
6079     sheetStyle.sheetMode = NG::SheetMode::LARGE;
6080     sheetStyle.showDragBar = true;
6081     sheetStyle.showCloseIcon = true;
6082     std::function<void()> onShowCallback;
6083     std::function<void()> onDismissCallback;
6084     std::function<void()> shouldDismissFunc;
6085     std::function<void()> titleBuilderFunction;
6086     if (info.Length() == 3) {
6087         if (info[2]->IsObject()) {
6088             ParseSheetCallback(info[2], onShowCallback, onDismissCallback, shouldDismissFunc);
6089             ParseSheetStyle(info[2], sheetStyle);
6090             ParseSheetTitle(info[2], sheetStyle, titleBuilderFunction);
6091         }
6092     }
6093     ViewAbstractModel::GetInstance()->BindSheet(isShow, std::move(callback), std::move(buildFunc),
6094         std::move(titleBuilderFunction), sheetStyle, std::move(onShowCallback), std::move(onDismissCallback),
6095         std::move(shouldDismissFunc));
6096 }
6097 
ParseSheetStyle(const JSRef<JSObject> & paramObj,NG::SheetStyle & sheetStyle)6098 void JSViewAbstract::ParseSheetStyle(const JSRef<JSObject>& paramObj, NG::SheetStyle& sheetStyle)
6099 {
6100     auto height = paramObj->GetProperty("height");
6101     auto showDragBar = paramObj->GetProperty("dragBar");
6102     auto backgroundColor = paramObj->GetProperty("backgroundColor");
6103     auto maskColor = paramObj->GetProperty("maskColor");
6104     auto sheetDetents = paramObj->GetProperty("detents");
6105     auto backgroundBlurStyle = paramObj->GetProperty("blurStyle");
6106     auto showCloseIcon = paramObj->GetProperty("showClose");
6107     auto type = paramObj->GetProperty("preferType");
6108     auto interactive = paramObj->GetProperty("enableOutsideInteractive");
6109 
6110     std::vector<NG::SheetHeight> detents;
6111     if (ParseSheetDetents(sheetDetents, detents)) {
6112         sheetStyle.detents = detents;
6113     }
6114     BlurStyleOption styleOption;
6115     if (ParseSheetBackgroundBlurStyle(backgroundBlurStyle, styleOption)) {
6116         sheetStyle.backgroundBlurStyle = styleOption;
6117     }
6118     bool showClose = true;
6119     if (showCloseIcon->IsNull() || showCloseIcon->IsUndefined()) {
6120         sheetStyle.showCloseIcon = showClose;
6121     } else {
6122         if (ParseJsBool(showCloseIcon, showClose)) {
6123             sheetStyle.showCloseIcon = showClose;
6124         }
6125     }
6126     bool isInteractive = false;
6127     if (ParseJsBool(interactive, isInteractive)) {
6128         sheetStyle.interactive = isInteractive;
6129     }
6130     if (showDragBar->IsNull() || showDragBar->IsUndefined()) {
6131         sheetStyle.showDragBar = true;
6132     } else {
6133         if (showDragBar->IsBoolean()) {
6134             sheetStyle.showDragBar = showDragBar->ToBoolean();
6135         }
6136     }
6137     if (type->IsNull() || type->IsUndefined()) {
6138         sheetStyle.sheetType.reset();
6139     } else {
6140         if (type->IsNumber()) {
6141             auto sheetType = type->ToNumber<int32_t>();
6142             if (sheetType >= static_cast<int>(NG::SheetType::SHEET_BOTTOM) &&
6143                 sheetType <= static_cast<int>(NG::SheetType::SHEET_POPUP)) {
6144                 sheetStyle.sheetType = static_cast<NG::SheetType>(sheetType);
6145             }
6146         }
6147     }
6148     Color color;
6149     if (ParseJsColor(backgroundColor, color)) {
6150         sheetStyle.backgroundColor = color;
6151     }
6152     // parse maskColor
6153     Color parseMaskColor;
6154     if (!maskColor->IsNull() && !maskColor->IsUndefined() && JSViewAbstract::ParseJsColor(maskColor, parseMaskColor)) {
6155         sheetStyle.maskColor = std::move(parseMaskColor);
6156     }
6157     CalcDimension sheetHeight;
6158     if (height->IsString()) {
6159         std::string heightStr = height->ToString();
6160         // Remove all " ".
6161         heightStr.erase(std::remove(heightStr.begin(), heightStr.end(), ' '), heightStr.end());
6162         std::transform(heightStr.begin(), heightStr.end(), heightStr.begin(), ::tolower);
6163         if (heightStr == SHEET_HEIGHT_MEDIUM) {
6164             sheetStyle.sheetMode = NG::SheetMode::MEDIUM;
6165             sheetStyle.height.reset();
6166             return;
6167         }
6168         if (heightStr == SHEET_HEIGHT_LARGE) {
6169             sheetStyle.sheetMode = NG::SheetMode::LARGE;
6170             sheetStyle.height.reset();
6171             return;
6172         }
6173         if (heightStr == SHEET_HEIGHT_FITCONTENT) {
6174             sheetStyle.sheetMode = NG::SheetMode::AUTO;
6175             sheetStyle.height.reset();
6176             return;
6177         }
6178         if (heightStr.find("calc") != std::string::npos) {
6179             sheetHeight = CalcDimension(heightStr, DimensionUnit::CALC);
6180         } else {
6181             sheetHeight = StringUtils::StringToDimensionWithUnit(heightStr, DimensionUnit::VP, -1.0);
6182         }
6183         if (sheetHeight.Value() < 0) {
6184             sheetStyle.sheetMode = NG::SheetMode::LARGE;
6185             sheetStyle.height.reset();
6186             return;
6187         }
6188     }
6189     if (!ParseJsDimensionVpNG(height, sheetHeight)) {
6190         sheetStyle.sheetMode = NG::SheetMode::LARGE;
6191         sheetStyle.height.reset();
6192     } else {
6193         sheetStyle.height = sheetHeight;
6194         sheetStyle.sheetMode.reset();
6195     }
6196 }
6197 
ParseSheetDetents(const JSRef<JSVal> & args,std::vector<NG::SheetHeight> & sheetDetents)6198 bool JSViewAbstract::ParseSheetDetents(const JSRef<JSVal>& args, std::vector<NG::SheetHeight>& sheetDetents)
6199 {
6200     if (!args->IsArray()) {
6201         return false;
6202     }
6203     JSRef<JSArray> array = JSRef<JSArray>::Cast(args);
6204     NG::SheetHeight sheetDetent;
6205     for (size_t i = 0; i < array->Length(); i++) {
6206         ParseSheetDetentHeight(array->GetValueAt(i), sheetDetent);
6207         if ((!sheetDetent.height.has_value()) && (!sheetDetent.sheetMode.has_value())) {
6208             continue;
6209         }
6210         sheetDetents.emplace_back(sheetDetent);
6211         sheetDetent.height.reset();
6212         sheetDetent.sheetMode.reset();
6213     }
6214     return true;
6215 }
6216 
ParseSheetDetentHeight(const JSRef<JSVal> & args,NG::SheetHeight & detent)6217 void JSViewAbstract::ParseSheetDetentHeight(const JSRef<JSVal>& args, NG::SheetHeight& detent)
6218 {
6219     CalcDimension sheetHeight;
6220     if (args->IsString()) {
6221         std::string heightStr = args->ToString();
6222         // Remove all " ".
6223         heightStr.erase(std::remove(heightStr.begin(), heightStr.end(), ' '), heightStr.end());
6224         std::transform(heightStr.begin(), heightStr.end(), heightStr.begin(), ::tolower);
6225         if (heightStr == SHEET_HEIGHT_MEDIUM) {
6226             detent.sheetMode = NG::SheetMode::MEDIUM;
6227             detent.height.reset();
6228             return;
6229         }
6230         if (heightStr == SHEET_HEIGHT_LARGE) {
6231             detent.sheetMode = NG::SheetMode::LARGE;
6232             detent.height.reset();
6233             return;
6234         }
6235         if (heightStr == SHEET_HEIGHT_FITCONTENT) {
6236             detent.sheetMode = NG::SheetMode::AUTO;
6237             detent.height.reset();
6238             return;
6239         }
6240         if (heightStr.find("calc") != std::string::npos) {
6241             sheetHeight = CalcDimension(heightStr, DimensionUnit::CALC);
6242         } else {
6243             sheetHeight = StringUtils::StringToDimensionWithUnit(heightStr, DimensionUnit::VP, -1.0);
6244         }
6245         if (sheetHeight.Value() < 0) {
6246             detent.sheetMode = NG::SheetMode::LARGE;
6247             detent.height.reset();
6248             return;
6249         }
6250     }
6251     if (!ParseJsDimensionVpNG(args, sheetHeight)) {
6252         detent.sheetMode = NG::SheetMode::LARGE;
6253         detent.height.reset();
6254     } else {
6255         detent.height = sheetHeight;
6256         detent.sheetMode.reset();
6257     }
6258 }
6259 
ParseSheetBackgroundBlurStyle(const JSRef<JSVal> & args,BlurStyleOption & blurStyleOptions)6260 bool JSViewAbstract::ParseSheetBackgroundBlurStyle(const JSRef<JSVal>& args, BlurStyleOption& blurStyleOptions)
6261 {
6262     if (args->IsNumber()) {
6263         auto sheetBlurStyle = args->ToNumber<int32_t>();
6264         if (sheetBlurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
6265             sheetBlurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
6266             blurStyleOptions.blurStyle = static_cast<BlurStyle>(sheetBlurStyle);
6267         } else {
6268             return false;
6269         }
6270     } else {
6271         return false;
6272     }
6273     return true;
6274 }
6275 
ParseSheetCallback(const JSRef<JSObject> & paramObj,std::function<void ()> & onAppear,std::function<void ()> & onDisappear,std::function<void ()> & shouldDismiss)6276 void JSViewAbstract::ParseSheetCallback(const JSRef<JSObject>& paramObj, std::function<void()>& onAppear,
6277     std::function<void()>& onDisappear, std::function<void()>& shouldDismiss)
6278 {
6279     auto showCallback = paramObj->GetProperty("onAppear");
6280     auto dismissCallback = paramObj->GetProperty("onDisappear");
6281     auto shouldDismissFunc = paramObj->GetProperty("shouldDismiss");
6282     if (showCallback->IsFunction()) {
6283         RefPtr<JsFunction> jsFunc =
6284             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(showCallback));
6285         onAppear = [func = std::move(jsFunc)]() { func->Execute(); };
6286     }
6287     if (dismissCallback->IsFunction()) {
6288         RefPtr<JsFunction> jsFunc =
6289             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(dismissCallback));
6290         onDisappear = [func = std::move(jsFunc)]() { func->Execute(); };
6291     }
6292     if (shouldDismissFunc->IsFunction()) {
6293         RefPtr<JsFunction> jsFunc =
6294             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(shouldDismissFunc));
6295         shouldDismiss = [func = std::move(jsFunc)]() {
6296             JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
6297             objectTemplate->SetInternalFieldCount(1);
6298             JSRef<JSObject> dismissObj = objectTemplate->NewInstance();
6299             dismissObj->SetPropertyObject(
6300                 "dismiss", JSRef<JSFunc>::New<FunctionCallback>(JSViewAbstract::JsDismissSheet));
6301             JSRef<JSVal> newJSVal = JSRef<JSObject>::Cast(dismissObj);
6302             func->ExecuteJS(1, &newJSVal);
6303         };
6304     }
6305 }
6306 
ParseSheetTitle(const JSRef<JSObject> & paramObj,NG::SheetStyle & sheetStyle,std::function<void ()> & titleBuilderFunction)6307 void JSViewAbstract::ParseSheetTitle(
6308     const JSRef<JSObject>& paramObj, NG::SheetStyle& sheetStyle, std::function<void()>& titleBuilderFunction)
6309 {
6310     auto title = paramObj->GetProperty("title");
6311     std::string mainTitle;
6312     std::string subtitle;
6313     if (title->IsFunction()) {
6314         sheetStyle.isTitleBuilder = true;
6315         auto titleBuilderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(title));
6316         CHECK_NULL_VOID(titleBuilderFunc);
6317         titleBuilderFunction = [func = std::move(titleBuilderFunc)]() {
6318             ACE_SCORING_EVENT("BindSheet");
6319             func->Execute();
6320         };
6321     } else if (title->IsObject()) {
6322         JSRef<JSObject> obj = JSRef<JSObject>::Cast(title);
6323         sheetStyle.isTitleBuilder = false;
6324         auto sheetTitle = obj->GetProperty("title");
6325         auto sheetSubtitle = obj->GetProperty("subtitle");
6326         if (ParseJsString(sheetTitle, mainTitle)) {
6327             sheetStyle.sheetTitle = mainTitle;
6328         }
6329         if (ParseJsString(sheetSubtitle, subtitle)) {
6330             sheetStyle.sheetSubtitle = subtitle;
6331         }
6332     }
6333 }
6334 
JsDismissSheet(panda::JsiRuntimeCallInfo * runtimeCallInfo)6335 panda::Local<panda::JSValueRef> JSViewAbstract::JsDismissSheet(panda::JsiRuntimeCallInfo* runtimeCallInfo)
6336 {
6337     ViewAbstractModel::GetInstance()->DismissSheet();
6338     return JSValueRef::Undefined(runtimeCallInfo->GetVM());
6339 }
6340 
ParseOverlayCallback(const JSRef<JSObject> & paramObj,std::function<void ()> & onAppear,std::function<void ()> & onDisappear)6341 void JSViewAbstract::ParseOverlayCallback(
6342     const JSRef<JSObject>& paramObj, std::function<void()>& onAppear, std::function<void()>& onDisappear)
6343 {
6344     auto showCallback = paramObj->GetProperty("onAppear");
6345     auto dismissCallback = paramObj->GetProperty("onDisappear");
6346     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
6347     if (showCallback->IsFunction()) {
6348         RefPtr<JsFunction> jsFunc =
6349             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(showCallback));
6350         onAppear = [func = std::move(jsFunc), node = frameNode]() {
6351             PipelineContext::SetCallBackNode(node);
6352             func->Execute();
6353         };
6354     }
6355     if (dismissCallback->IsFunction()) {
6356         RefPtr<JsFunction> jsFunc =
6357             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(dismissCallback));
6358         onDisappear = [func = std::move(jsFunc), node = frameNode]() {
6359             PipelineContext::SetCallBackNode(node);
6360             func->Execute();
6361         };
6362     }
6363 }
6364 
JSCreateAnimatableProperty(const JSCallbackInfo & info)6365 void JSViewAbstract::JSCreateAnimatableProperty(const JSCallbackInfo& info)
6366 {
6367     if (info.Length() < 3 || !info[0]->IsString()) { /* 3:args number */
6368         return;
6369     }
6370 
6371     JSRef<JSVal> callback = info[2]; /* 2:args index */
6372     if (!callback->IsFunction()) {
6373         return;
6374     }
6375     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
6376     std::string propertyName = info[0]->ToString();
6377     if (info[1]->IsNumber()) {
6378         float numValue = info[1]->ToNumber<float>();
6379         std::function<void(float)> onCallbackEvent;
6380         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(callback));
6381         onCallbackEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), id = Container::CurrentId(),
6382                               node = frameNode](const float val) {
6383             ContainerScope scope(id);
6384             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6385             auto newJSVal = JSRef<JSVal>::Make(ToJSValue(val));
6386             PipelineContext::SetCallBackNode(node);
6387             func->ExecuteJS(1, &newJSVal);
6388         };
6389         ViewAbstractModel::GetInstance()->CreateAnimatablePropertyFloat(propertyName, numValue, onCallbackEvent);
6390     } else if (info[1]->IsObject()) {
6391         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
6392         RefPtr<JSAnimatableArithmetic> animatableArithmeticImpl =
6393             AceType::MakeRefPtr<JSAnimatableArithmetic>(obj, info.GetExecutionContext());
6394         RefPtr<CustomAnimatableArithmetic> animatableArithmetic =
6395             AceType::DynamicCast<CustomAnimatableArithmetic>(animatableArithmeticImpl);
6396         std::function<void(const RefPtr<NG::CustomAnimatableArithmetic>&)> onCallbackEvent;
6397         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(callback));
6398         onCallbackEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), id = Container::CurrentId(),
6399                               node = frameNode](const RefPtr<NG::CustomAnimatableArithmetic>& value) {
6400             ContainerScope scope(id);
6401             RefPtr<JSAnimatableArithmetic> impl = AceType::DynamicCast<JSAnimatableArithmetic>(value);
6402             if (!impl) {
6403                 return;
6404             }
6405             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
6406             auto newJSVal = JSRef<JSVal>(impl->GetObject());
6407             PipelineContext::SetCallBackNode(node);
6408             func->ExecuteJS(1, &newJSVal);
6409         };
6410         ViewAbstractModel::GetInstance()->CreateAnimatableArithmeticProperty(
6411             propertyName, animatableArithmetic, onCallbackEvent);
6412     }
6413 }
6414 
JSUpdateAnimatableProperty(const JSCallbackInfo & info)6415 void JSViewAbstract::JSUpdateAnimatableProperty(const JSCallbackInfo& info)
6416 {
6417     if (info.Length() < 2 || !info[0]->IsString()) { /* 2:args number */
6418         return;
6419     }
6420 
6421     std::string propertyName = info[0]->ToString();
6422     float numValue = 0.0;
6423     if (info[1]->IsNumber()) {
6424         numValue = info[1]->ToNumber<float>();
6425         ViewAbstractModel::GetInstance()->UpdateAnimatablePropertyFloat(propertyName, numValue);
6426     } else if (info[1]->IsObject()) {
6427         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[1]);
6428         RefPtr<JSAnimatableArithmetic> animatableArithmeticImpl =
6429             AceType::MakeRefPtr<JSAnimatableArithmetic>(obj, info.GetExecutionContext());
6430         RefPtr<CustomAnimatableArithmetic> animatableArithmetic =
6431             AceType::DynamicCast<CustomAnimatableArithmetic>(animatableArithmeticImpl);
6432         ViewAbstractModel::GetInstance()->UpdateAnimatableArithmeticProperty(propertyName, animatableArithmetic);
6433     }
6434 }
6435 
JsExpandSafeArea(const JSCallbackInfo & info)6436 void JSViewAbstract::JsExpandSafeArea(const JSCallbackInfo& info)
6437 {
6438     NG::SafeAreaExpandOpts opts { .type = NG::SAFE_AREA_TYPE_ALL, .edges = NG::SAFE_AREA_EDGE_ALL };
6439     if (info.Length() >= 1 && info[0]->IsArray()) {
6440         auto paramArray = JSRef<JSArray>::Cast(info[0]);
6441         uint32_t safeAreaType = NG::SAFE_AREA_TYPE_NONE;
6442         for (size_t i = 0; i < paramArray->Length(); ++i) {
6443             if (!paramArray->GetValueAt(i)->IsNumber() ||
6444                 paramArray->GetValueAt(i)->ToNumber<uint32_t>() >= SAFE_AREA_TYPE_LIMIT) {
6445                 safeAreaType = NG::SAFE_AREA_TYPE_ALL;
6446                 break;
6447             }
6448             safeAreaType |= (1 << paramArray->GetValueAt(i)->ToNumber<uint32_t>());
6449         }
6450         opts.type = safeAreaType;
6451     }
6452     if (info.Length() >= 2 && info[1]->IsArray()) {
6453         auto paramArray = JSRef<JSArray>::Cast(info[1]);
6454         uint32_t safeAreaEdge = NG::SAFE_AREA_EDGE_NONE;
6455         for (size_t i = 0; i < paramArray->Length(); ++i) {
6456             if (!paramArray->GetValueAt(i)->IsNumber() ||
6457                 paramArray->GetValueAt(i)->ToNumber<uint32_t>() >= SAFE_AREA_EDGE_LIMIT) {
6458                 safeAreaEdge = NG::SAFE_AREA_EDGE_ALL;
6459                 break;
6460             }
6461             safeAreaEdge |= (1 << paramArray->GetValueAt(i)->ToNumber<uint32_t>());
6462         }
6463         opts.edges = safeAreaEdge;
6464     }
6465 
6466     ViewAbstractModel::GetInstance()->UpdateSafeAreaExpandOpts(opts);
6467 }
6468 
JsPointLight(const JSCallbackInfo & info)6469 void JSViewAbstract::JsPointLight(const JSCallbackInfo& info)
6470 {
6471     if (!info[0]->IsObject()) {
6472         return;
6473     }
6474 
6475     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
6476     JSRef<JSObject> lightSource = object->GetProperty("lightSource");
6477     if (!lightSource->IsUndefined()) {
6478         JSRef<JSVal> positionX = lightSource->GetProperty("positionX");
6479         JSRef<JSVal> positionY = lightSource->GetProperty("positionY");
6480         JSRef<JSVal> positionZ = lightSource->GetProperty("positionZ");
6481         JSRef<JSVal> intensity = lightSource->GetProperty("intensity");
6482 
6483         CalcDimension dimPositionX, dimPositionY, dimPositionZ;
6484         if (ParseJsDimensionVp(positionX, dimPositionX) && ParseJsDimensionVp(positionY, dimPositionY) &&
6485             ParseJsDimensionVp(positionZ, dimPositionZ)) {
6486             ViewAbstractModel::GetInstance()->SetLightPosition(dimPositionX, dimPositionY, dimPositionZ);
6487         }
6488 
6489         if (intensity->IsNumber()) {
6490             float intensityValue = intensity->ToNumber<float>();
6491             ViewAbstractModel::GetInstance()->SetLightIntensity(intensityValue);
6492         }
6493     }
6494 
6495     auto resourceWrapper = CreateResourceWrapper();
6496     if (!resourceWrapper) {
6497         return;
6498     }
6499     double bloomRadius = resourceWrapper->GetDoubleByName(BLOOM_RADIUS_SYS_RES_NAME);
6500     Color bloomColor = resourceWrapper->GetColorByName(BLOOM_COLOR_SYS_RES_NAME);
6501     Dimension illuminatedBorderWidth = resourceWrapper->GetDimensionByName(ILLUMINATED_BORDER_WIDTH_SYS_RES_NAME);
6502 
6503     JSRef<JSVal> illuminated = object->GetProperty("illuminated");
6504     if (illuminated->IsNumber()) {
6505         uint32_t illuminatedValue = illuminated->ToNumber<uint32_t>();
6506         ViewAbstractModel::GetInstance()->SetLightIlluminated(illuminatedValue);
6507         ViewAbstractModel::GetInstance()->SetIlluminatedBorderWidth(illuminatedBorderWidth);
6508     }
6509 
6510     JSRef<JSVal> bloom = object->GetProperty("bloom");
6511     if (bloom->IsNumber()) {
6512         float bloomValue = bloom->ToNumber<float>();
6513         ViewAbstractModel::GetInstance()->SetBloom(bloomValue);
6514 
6515         Shadow shadow;
6516         shadow.SetBlurRadius(bloomValue * bloomRadius);
6517         shadow.SetColor(bloomColor);
6518         std::vector<Shadow> shadows { shadow };
6519         ViewAbstractModel::GetInstance()->SetBackShadow(shadows);
6520     }
6521 }
6522 
JSBind(BindingTarget globalObj)6523 void JSViewAbstract::JSBind(BindingTarget globalObj)
6524 {
6525     JSClass<JSViewAbstract>::Declare("JSViewAbstract");
6526 
6527     // static methods
6528     MethodOptions opt = MethodOptions::NONE;
6529     JSClass<JSViewAbstract>::StaticMethod("pop", &JSViewAbstract::Pop, opt);
6530 
6531     JSClass<JSViewAbstract>::StaticMethod("width", &JSViewAbstract::JsWidth);
6532     JSClass<JSViewAbstract>::StaticMethod("height", &JSViewAbstract::JsHeight);
6533     JSClass<JSViewAbstract>::StaticMethod("responseRegion", &JSViewAbstract::JsResponseRegion);
6534     JSClass<JSViewAbstract>::StaticMethod("mouseResponseRegion", &JSViewAbstract::JsMouseResponseRegion);
6535     JSClass<JSViewAbstract>::StaticMethod("size", &JSViewAbstract::JsSize);
6536     JSClass<JSViewAbstract>::StaticMethod("constraintSize", &JSViewAbstract::JsConstraintSize);
6537     JSClass<JSViewAbstract>::StaticMethod("layoutPriority", &JSViewAbstract::JsLayoutPriority);
6538     JSClass<JSViewAbstract>::StaticMethod("pixelRound", &JSViewAbstract::JsPixelRound);
6539     JSClass<JSViewAbstract>::StaticMethod("layoutWeight", &JSViewAbstract::JsLayoutWeight);
6540 
6541     JSClass<JSViewAbstract>::StaticMethod("margin", &JSViewAbstract::JsMargin);
6542     JSClass<JSViewAbstract>::StaticMethod("marginTop", &JSViewAbstract::SetMarginTop, opt);
6543     JSClass<JSViewAbstract>::StaticMethod("marginBottom", &JSViewAbstract::SetMarginBottom, opt);
6544     JSClass<JSViewAbstract>::StaticMethod("marginLeft", &JSViewAbstract::SetMarginLeft, opt);
6545     JSClass<JSViewAbstract>::StaticMethod("marginRight", &JSViewAbstract::SetMarginRight, opt);
6546 
6547     JSClass<JSViewAbstract>::StaticMethod("padding", &JSViewAbstract::JsPadding);
6548     JSClass<JSViewAbstract>::StaticMethod("paddingTop", &JSViewAbstract::SetPaddingTop, opt);
6549     JSClass<JSViewAbstract>::StaticMethod("paddingBottom", &JSViewAbstract::SetPaddingBottom, opt);
6550     JSClass<JSViewAbstract>::StaticMethod("paddingLeft", &JSViewAbstract::SetPaddingLeft, opt);
6551     JSClass<JSViewAbstract>::StaticMethod("paddingRight", &JSViewAbstract::SetPaddingRight, opt);
6552 
6553     JSClass<JSViewAbstract>::StaticMethod("foregroundColor", &JSViewAbstract::JsForegroundColor);
6554     JSClass<JSViewAbstract>::StaticMethod("backgroundColor", &JSViewAbstract::JsBackgroundColor);
6555     JSClass<JSViewAbstract>::StaticMethod("backgroundImage", &JSViewAbstract::JsBackgroundImage);
6556     JSClass<JSViewAbstract>::StaticMethod("backgroundImageSize", &JSViewAbstract::JsBackgroundImageSize);
6557     JSClass<JSViewAbstract>::StaticMethod("backgroundImagePosition", &JSViewAbstract::JsBackgroundImagePosition);
6558     JSClass<JSViewAbstract>::StaticMethod("backgroundBlurStyle", &JSViewAbstract::JsBackgroundBlurStyle);
6559     JSClass<JSViewAbstract>::StaticMethod("backgroundEffect", &JSViewAbstract::JsBackgroundEffect);
6560     JSClass<JSViewAbstract>::StaticMethod("foregroundBlurStyle", &JSViewAbstract::JsForegroundBlurStyle);
6561     JSClass<JSViewAbstract>::StaticMethod("lightUpEffect", &JSViewAbstract::JsLightUpEffect);
6562     JSClass<JSViewAbstract>::StaticMethod("sphericalEffect", &JSViewAbstract::JsSphericalEffect);
6563     JSClass<JSViewAbstract>::StaticMethod("pixelStretchEffect", &JSViewAbstract::JsPixelStretchEffect);
6564     JSClass<JSViewAbstract>::StaticMethod("outline", &JSViewAbstract::JsOutline);
6565     JSClass<JSViewAbstract>::StaticMethod("outlineWidth", &JSViewAbstract::JsOutlineWidth);
6566     JSClass<JSViewAbstract>::StaticMethod("outlineStyle", &JSViewAbstract::JsOutlineStyle);
6567     JSClass<JSViewAbstract>::StaticMethod("outlineColor", &JSViewAbstract::JsOutlineColor);
6568     JSClass<JSViewAbstract>::StaticMethod("outlineRadius", &JSViewAbstract::JsOutlineRadius);
6569     JSClass<JSViewAbstract>::StaticMethod("border", &JSViewAbstract::JsBorder);
6570     JSClass<JSViewAbstract>::StaticMethod("borderWidth", &JSViewAbstract::JsBorderWidth);
6571     JSClass<JSViewAbstract>::StaticMethod("borderColor", &JSViewAbstract::JsBorderColor);
6572     JSClass<JSViewAbstract>::StaticMethod("borderRadius", &JSViewAbstract::JsBorderRadius);
6573     JSClass<JSViewAbstract>::StaticMethod("borderStyle", &JSViewAbstract::JsBorderStyle);
6574     JSClass<JSViewAbstract>::StaticMethod("borderImage", &JSViewAbstract::JsBorderImage);
6575 
6576     JSClass<JSViewAbstract>::StaticMethod("scale", &JSViewAbstract::JsScale);
6577     JSClass<JSViewAbstract>::StaticMethod("scaleX", &JSViewAbstract::JsScaleX);
6578     JSClass<JSViewAbstract>::StaticMethod("scaleY", &JSViewAbstract::JsScaleY);
6579     JSClass<JSViewAbstract>::StaticMethod("opacity", &JSViewAbstract::JsOpacity);
6580     JSClass<JSViewAbstract>::StaticMethod("rotate", &JSViewAbstract::JsRotate);
6581     JSClass<JSViewAbstract>::StaticMethod("rotateX", &JSViewAbstract::JsRotateX);
6582     JSClass<JSViewAbstract>::StaticMethod("rotateY", &JSViewAbstract::JsRotateY);
6583     JSClass<JSViewAbstract>::StaticMethod("translate", &JSViewAbstract::JsTranslate);
6584     JSClass<JSViewAbstract>::StaticMethod("translateX", &JSViewAbstract::JsTranslateX);
6585     JSClass<JSViewAbstract>::StaticMethod("translateY", &JSViewAbstract::JsTranslateY);
6586     JSClass<JSViewAbstract>::StaticMethod("transform", &JSViewAbstract::JsTransform);
6587     JSClass<JSViewAbstract>::StaticMethod("transition", &JSViewAbstract::JsTransition);
6588 
6589     JSClass<JSViewAbstract>::StaticMethod("align", &JSViewAbstract::JsAlign);
6590     JSClass<JSViewAbstract>::StaticMethod("position", &JSViewAbstract::JsPosition);
6591     JSClass<JSViewAbstract>::StaticMethod("markAnchor", &JSViewAbstract::JsMarkAnchor);
6592     JSClass<JSViewAbstract>::StaticMethod("offset", &JSViewAbstract::JsOffset);
6593     JSClass<JSViewAbstract>::StaticMethod("enabled", &JSViewAbstract::JsEnabled);
6594     JSClass<JSViewAbstract>::StaticMethod("aspectRatio", &JSViewAbstract::JsAspectRatio);
6595     JSClass<JSViewAbstract>::StaticMethod("overlay", &JSViewAbstract::JsOverlay);
6596 
6597     JSClass<JSViewAbstract>::StaticMethod("blur", &JSViewAbstract::JsBlur);
6598     JSClass<JSViewAbstract>::StaticMethod("useEffect", &JSViewAbstract::JsUseEffect);
6599     JSClass<JSViewAbstract>::StaticMethod("useShadowBatching", &JSViewAbstract::JsUseShadowBatching);
6600     JSClass<JSViewAbstract>::StaticMethod("colorBlend", &JSViewAbstract::JsColorBlend);
6601     JSClass<JSViewAbstract>::StaticMethod("backdropBlur", &JSViewAbstract::JsBackdropBlur);
6602     JSClass<JSViewAbstract>::StaticMethod("linearGradientBlur", &JSViewAbstract::JsLinearGradientBlur);
6603     JSClass<JSViewAbstract>::StaticMethod("backgroundBrightness", &JSViewAbstract::JsBackgroundBrightness);
6604     JSClass<JSViewAbstract>::StaticMethod("windowBlur", &JSViewAbstract::JsWindowBlur);
6605     JSClass<JSViewAbstract>::StaticMethod("visibility", &JSViewAbstract::SetVisibility);
6606     JSClass<JSViewAbstract>::StaticMethod("flexBasis", &JSViewAbstract::JsFlexBasis);
6607     JSClass<JSViewAbstract>::StaticMethod("flexGrow", &JSViewAbstract::JsFlexGrow);
6608     JSClass<JSViewAbstract>::StaticMethod("flexShrink", &JSViewAbstract::JsFlexShrink);
6609     JSClass<JSViewAbstract>::StaticMethod("alignSelf", &JSViewAbstract::JsAlignSelf);
6610     JSClass<JSViewAbstract>::StaticMethod("displayPriority", &JSViewAbstract::JsDisplayPriority);
6611     JSClass<JSViewAbstract>::StaticMethod("useAlign", &JSViewAbstract::JsUseAlign);
6612     JSClass<JSViewAbstract>::StaticMethod("zIndex", &JSViewAbstract::JsZIndex);
6613     JSClass<JSViewAbstract>::StaticMethod("sharedTransition", &JSViewAbstract::JsSharedTransition);
6614     JSClass<JSViewAbstract>::StaticMethod("direction", &JSViewAbstract::SetDirection, opt);
6615 #ifndef WEARABLE_PRODUCT
6616     JSClass<JSViewAbstract>::StaticMethod("bindPopup", &JSViewAbstract::JsBindPopup);
6617 #endif
6618 
6619     JSClass<JSViewAbstract>::StaticMethod("background", &JSViewAbstract::JsBackground);
6620     JSClass<JSViewAbstract>::StaticMethod("bindMenu", &JSViewAbstract::JsBindMenu);
6621     JSClass<JSViewAbstract>::StaticMethod("bindContextMenu", &JSViewAbstract::JsBindContextMenu);
6622     JSClass<JSViewAbstract>::StaticMethod("bindContentCover", &JSViewAbstract::JsBindContentCover);
6623     JSClass<JSViewAbstract>::StaticMethod("bindSheet", &JSViewAbstract::JsBindSheet);
6624     JSClass<JSViewAbstract>::StaticMethod("draggable", &JSViewAbstract::JsSetDraggable);
6625     JSClass<JSViewAbstract>::StaticMethod("dragPreviewOptions", &JSViewAbstract::JsSetDragPreviewOptions);
6626     JSClass<JSViewAbstract>::StaticMethod("onDragStart", &JSViewAbstract::JsOnDragStart);
6627     JSClass<JSViewAbstract>::StaticMethod("onDragEnter", &JSViewAbstract::JsOnDragEnter);
6628     JSClass<JSViewAbstract>::StaticMethod("onDragMove", &JSViewAbstract::JsOnDragMove);
6629     JSClass<JSViewAbstract>::StaticMethod("onDragLeave", &JSViewAbstract::JsOnDragLeave);
6630     JSClass<JSViewAbstract>::StaticMethod("onDrop", &JSViewAbstract::JsOnDrop);
6631     JSClass<JSViewAbstract>::StaticMethod("onDragEnd", &JSViewAbstract::JsOnDragEnd);
6632 
6633     JSClass<JSViewAbstract>::StaticMethod("linearGradient", &JSViewAbstract::JsLinearGradient);
6634     JSClass<JSViewAbstract>::StaticMethod("sweepGradient", &JSViewAbstract::JsSweepGradient);
6635     JSClass<JSViewAbstract>::StaticMethod("radialGradient", &JSViewAbstract::JsRadialGradient);
6636     JSClass<JSViewAbstract>::StaticMethod("motionPath", &JSViewAbstract::JsMotionPath);
6637     JSClass<JSViewAbstract>::StaticMethod("gridSpan", &JSViewAbstract::JsGridSpan);
6638     JSClass<JSViewAbstract>::StaticMethod("gridOffset", &JSViewAbstract::JsGridOffset);
6639     JSClass<JSViewAbstract>::StaticMethod("useSizeType", &JSViewAbstract::JsUseSizeType);
6640     JSClass<JSViewAbstract>::StaticMethod("shadow", &JSViewAbstract::JsShadow);
6641     JSClass<JSViewAbstract>::StaticMethod("blendMode", &JSViewAbstract::JsBlendMode);
6642     JSClass<JSViewAbstract>::StaticMethod("grayscale", &JSViewAbstract::JsGrayScale);
6643     JSClass<JSViewAbstract>::StaticMethod("focusable", &JSViewAbstract::JsFocusable);
6644     JSClass<JSViewAbstract>::StaticMethod("onKeyEvent", &JSViewAbstract::JsOnKeyEvent);
6645     JSClass<JSViewAbstract>::StaticMethod("onFocusMove", &JSViewAbstract::JsOnFocusMove);
6646     JSClass<JSViewAbstract>::StaticMethod("onFocus", &JSViewAbstract::JsOnFocus);
6647     JSClass<JSViewAbstract>::StaticMethod("onBlur", &JSViewAbstract::JsOnBlur);
6648     JSClass<JSViewAbstract>::StaticMethod("tabIndex", &JSViewAbstract::JsTabIndex);
6649     JSClass<JSViewAbstract>::StaticMethod("focusOnTouch", &JSViewAbstract::JsFocusOnTouch);
6650     JSClass<JSViewAbstract>::StaticMethod("defaultFocus", &JSViewAbstract::JsDefaultFocus);
6651     JSClass<JSViewAbstract>::StaticMethod("groupDefaultFocus", &JSViewAbstract::JsGroupDefaultFocus);
6652     JSClass<JSViewAbstract>::StaticMethod("brightness", &JSViewAbstract::JsBrightness);
6653     JSClass<JSViewAbstract>::StaticMethod("contrast", &JSViewAbstract::JsContrast);
6654     JSClass<JSViewAbstract>::StaticMethod("saturate", &JSViewAbstract::JsSaturate);
6655     JSClass<JSViewAbstract>::StaticMethod("sepia", &JSViewAbstract::JsSepia);
6656     JSClass<JSViewAbstract>::StaticMethod("invert", &JSViewAbstract::JsInvert);
6657     JSClass<JSViewAbstract>::StaticMethod("systemBarEffect", &JSViewAbstract::JsSystemBarEffect);
6658     JSClass<JSViewAbstract>::StaticMethod("hueRotate", &JSViewAbstract::JsHueRotate);
6659     JSClass<JSViewAbstract>::StaticMethod("clip", &JSViewAbstract::JsClip);
6660     JSClass<JSViewAbstract>::StaticMethod("mask", &JSViewAbstract::JsMask);
6661     JSClass<JSViewAbstract>::StaticMethod("key", &JSViewAbstract::JsKey);
6662     JSClass<JSViewAbstract>::StaticMethod("id", &JSViewAbstract::JsId);
6663     JSClass<JSViewAbstract>::StaticMethod("restoreId", &JSViewAbstract::JsRestoreId);
6664     JSClass<JSViewAbstract>::StaticMethod("hoverEffect", &JSViewAbstract::JsHoverEffect);
6665     JSClass<JSViewAbstract>::StaticMethod("onMouse", &JSViewAbstract::JsOnMouse);
6666     JSClass<JSViewAbstract>::StaticMethod("onHover", &JSViewAbstract::JsOnHover);
6667     JSClass<JSViewAbstract>::StaticMethod("onClick", &JSViewAbstract::JsOnClick);
6668     JSClass<JSViewAbstract>::StaticMethod("onGestureJudgeBegin", &JSViewAbstract::JsOnGestureJudgeBegin);
6669     JSClass<JSViewAbstract>::StaticMethod("clickEffect", &JSViewAbstract::JsClickEffect);
6670     JSClass<JSViewAbstract>::StaticMethod("debugLine", &JSViewAbstract::JsDebugLine);
6671     JSClass<JSViewAbstract>::StaticMethod("geometryTransition", &JSViewAbstract::JsGeometryTransition);
6672     JSClass<JSViewAbstract>::StaticMethod("onAreaChange", &JSViewAbstract::JsOnAreaChange);
6673     JSClass<JSViewAbstract>::StaticMethod("touchable", &JSInteractableView::JsTouchable);
6674     JSClass<JSViewAbstract>::StaticMethod("monopolizeEvents", &JSInteractableView::JsMonopolizeEvents);
6675 
6676     JSClass<JSViewAbstract>::StaticMethod("accessibilityGroup", &JSViewAbstract::JsAccessibilityGroup);
6677     JSClass<JSViewAbstract>::StaticMethod("accessibilityText", &JSViewAbstract::JsAccessibilityText);
6678     JSClass<JSViewAbstract>::StaticMethod("accessibilityDescription", &JSViewAbstract::JsAccessibilityDescription);
6679     JSClass<JSViewAbstract>::StaticMethod("accessibilityImportance", &JSViewAbstract::JsAccessibilityImportance);
6680     JSClass<JSViewAbstract>::StaticMethod("accessibilityLevel", &JSViewAbstract::JsAccessibilityLevel);
6681     JSClass<JSViewAbstract>::StaticMethod("accessibilityVirtualNode", &JSViewAbstract::JsAccessibilityVirtualNode);
6682     JSClass<JSViewAbstract>::StaticMethod("onAccessibility", &JSInteractableView::JsOnAccessibility);
6683     JSClass<JSViewAbstract>::StaticMethod("alignRules", &JSViewAbstract::JsAlignRules);
6684     JSClass<JSViewAbstract>::StaticMethod("onVisibleAreaChange", &JSViewAbstract::JsOnVisibleAreaChange);
6685     JSClass<JSViewAbstract>::StaticMethod("hitTestBehavior", &JSViewAbstract::JsHitTestBehavior);
6686     JSClass<JSViewAbstract>::StaticMethod("onChildTouchTest", &JSViewAbstract::JsOnChildTouchTest);
6687     JSClass<JSViewAbstract>::StaticMethod("keyboardShortcut", &JSViewAbstract::JsKeyboardShortcut);
6688     JSClass<JSViewAbstract>::StaticMethod("obscured", &JSViewAbstract::JsObscured);
6689     JSClass<JSViewAbstract>::StaticMethod("allowDrop", &JSViewAbstract::JsAllowDrop);
6690     JSClass<JSViewAbstract>::StaticMethod("dragPreview", &JSViewAbstract::JsDragPreview);
6691 
6692     JSClass<JSViewAbstract>::StaticMethod("createAnimatableProperty", &JSViewAbstract::JSCreateAnimatableProperty);
6693     JSClass<JSViewAbstract>::StaticMethod("updateAnimatableProperty", &JSViewAbstract::JSUpdateAnimatableProperty);
6694     JSClass<JSViewAbstract>::StaticMethod("renderGroup", &JSViewAbstract::JSRenderGroup);
6695     JSClass<JSViewAbstract>::StaticMethod("renderFit", &JSViewAbstract::JSRenderFit);
6696 
6697     JSClass<JSViewAbstract>::StaticMethod("freeze", &JSViewAbstract::JsSetFreeze);
6698 
6699     JSClass<JSViewAbstract>::StaticMethod("expandSafeArea", &JSViewAbstract::JsExpandSafeArea);
6700 
6701     JSClass<JSViewAbstract>::Bind(globalObj);
6702 }
JsAllowDrop(const JSCallbackInfo & info)6703 void JSViewAbstract::JsAllowDrop(const JSCallbackInfo& info)
6704 {
6705     std::set<std::string> allowDropSet;
6706     allowDropSet.clear();
6707     if (!info[0]->IsUndefined() && info[0]->IsArray()) {
6708         auto allowDropArray = JSRef<JSArray>::Cast(info[0]);
6709         std::string allowDrop;
6710         for (size_t i = 0; i < allowDropArray->Length(); i++) {
6711             allowDrop = allowDropArray->GetValueAt(i)->ToString();
6712             allowDropSet.insert(allowDrop);
6713         }
6714     }
6715     ViewAbstractModel::GetInstance()->SetAllowDrop(allowDropSet);
6716 }
6717 
JsDragPreview(const JSCallbackInfo & info)6718 void JSViewAbstract::JsDragPreview(const JSCallbackInfo& info)
6719 {
6720     if (!info[0]->IsObject()) {
6721         return;
6722     }
6723     NG::DragDropInfo dragPreviewInfo;
6724     JSRef<JSVal> builder;
6725     JSRef<JSVal> pixelMap;
6726     JSRef<JSVal> extraInfo;
6727     if (info[0]->IsFunction()) {
6728         builder = info[0];
6729     } else if (info[0]->IsObject()) {
6730         auto dragItemInfo = JSRef<JSObject>::Cast(info[0]);
6731         builder = dragItemInfo->GetProperty("builder");
6732 #if defined(PIXEL_MAP_SUPPORTED)
6733         pixelMap = dragItemInfo->GetProperty("pixelMap");
6734         dragPreviewInfo.pixelMap = CreatePixelMapFromNapiValue(pixelMap);
6735 #endif
6736         extraInfo = dragItemInfo->GetProperty("extraInfo");
6737         ParseJsString(extraInfo, dragPreviewInfo.extraInfo);
6738     } else {
6739         return;
6740     }
6741 
6742     if (builder->IsFunction()) {
6743         RefPtr<JsFunction> builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
6744         if (builderFunc != nullptr) {
6745             ViewStackModel::GetInstance()->NewScope();
6746             {
6747                 ACE_SCORING_EVENT("dragPreview.builder");
6748                 builderFunc->Execute();
6749             }
6750             RefPtr<AceType> node = ViewStackModel::GetInstance()->Finish();
6751             dragPreviewInfo.customNode = AceType::DynamicCast<NG::UINode>(node);
6752         }
6753     }
6754     ViewAbstractModel::GetInstance()->SetDragPreview(dragPreviewInfo);
6755 }
6756 
JsAlignRules(const JSCallbackInfo & info)6757 void JSViewAbstract::JsAlignRules(const JSCallbackInfo& info)
6758 {
6759     if (!info[0]->IsObject()) {
6760         return;
6761     }
6762 
6763     JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(info[0]);
6764     if (valueObj->IsEmpty()) {
6765         return;
6766     }
6767     const char* keys[] = { "left", "middle", "right", "top", "center", "bottom", "bias" };
6768     std::map<AlignDirection, AlignRule> alignRules;
6769     BiasPair biasPair(DEFAULT_BIAS, DEFAULT_BIAS);
6770     for (uint32_t i = 0; i < sizeof(keys) / sizeof(const char*); i++) {
6771         auto rule = valueObj->GetProperty(keys[i]);
6772         if (rule->IsObject()) {
6773             JSRef<JSObject> val = JSRef<JSObject>::Cast(rule);
6774             JSRef<JSVal> align = val->GetProperty("align");
6775             AlignRule alignRule;
6776             alignRule.anchor = val->GetProperty("anchor")->ToString();
6777             if (i < HORIZONTAL_DIRECTION_RANGE) {
6778                 alignRule.horizontal = static_cast<HorizontalAlign>(val->GetProperty("align")->ToNumber<int32_t>());
6779             } else {
6780                 alignRule.vertical = static_cast<VerticalAlign>(val->GetProperty("align")->ToNumber<int32_t>());
6781             }
6782             if (i < VERTICAL_DIRECTION_RANGE) {
6783                 alignRules[static_cast<AlignDirection>(i)] = alignRule;
6784             }
6785             auto biasX = val->GetProperty("horizontal");
6786             if (biasX->IsNumber()) {
6787                 biasPair.first = biasX->ToNumber<float>();
6788             }
6789             auto biasY = val->GetProperty("vertical");
6790             if (biasY->IsNumber()) {
6791                 biasPair.second = biasY->ToNumber<float>();
6792             }
6793         }
6794     }
6795 
6796     ViewAbstractModel::GetInstance()->SetAlignRules(alignRules);
6797     ViewAbstractModel::GetInstance()->SetBias(biasPair);
6798 }
6799 
SetMarginTop(const JSCallbackInfo & info)6800 void JSViewAbstract::SetMarginTop(const JSCallbackInfo& info)
6801 {
6802     CalcDimension value;
6803     if (!ParseJsDimensionVp(info[0], value)) {
6804         return;
6805     }
6806     ViewAbstractModel::GetInstance()->SetMargins(value, std::nullopt, std::nullopt, std::nullopt);
6807 }
6808 
SetMarginBottom(const JSCallbackInfo & info)6809 void JSViewAbstract::SetMarginBottom(const JSCallbackInfo& info)
6810 {
6811     CalcDimension value;
6812     if (!ParseJsDimensionVp(info[0], value)) {
6813         return;
6814     }
6815     ViewAbstractModel::GetInstance()->SetMargins(std::nullopt, value, std::nullopt, std::nullopt);
6816 }
6817 
SetMarginLeft(const JSCallbackInfo & info)6818 void JSViewAbstract::SetMarginLeft(const JSCallbackInfo& info)
6819 {
6820     CalcDimension value;
6821     if (!ParseJsDimensionVp(info[0], value)) {
6822         return;
6823     }
6824     ViewAbstractModel::GetInstance()->SetMargins(std::nullopt, std::nullopt, value, std::nullopt);
6825 }
6826 
SetMarginRight(const JSCallbackInfo & info)6827 void JSViewAbstract::SetMarginRight(const JSCallbackInfo& info)
6828 {
6829     CalcDimension value;
6830     if (!ParseJsDimensionVp(info[0], value)) {
6831         return;
6832     }
6833     ViewAbstractModel::GetInstance()->SetMargins(std::nullopt, std::nullopt, std::nullopt, value);
6834 }
6835 
SetPaddingTop(const JSCallbackInfo & info)6836 void JSViewAbstract::SetPaddingTop(const JSCallbackInfo& info)
6837 {
6838     CalcDimension value;
6839     if (!ParseJsDimensionVp(info[0], value)) {
6840         return;
6841     }
6842     ViewAbstractModel::GetInstance()->SetPaddings(value, std::nullopt, std::nullopt, std::nullopt);
6843 }
6844 
SetPaddingBottom(const JSCallbackInfo & info)6845 void JSViewAbstract::SetPaddingBottom(const JSCallbackInfo& info)
6846 {
6847     CalcDimension value;
6848     if (!ParseJsDimensionVp(info[0], value)) {
6849         return;
6850     }
6851     ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, value, std::nullopt, std::nullopt);
6852 }
6853 
SetPaddingLeft(const JSCallbackInfo & info)6854 void JSViewAbstract::SetPaddingLeft(const JSCallbackInfo& info)
6855 {
6856     CalcDimension value;
6857     if (!ParseJsDimensionVp(info[0], value)) {
6858         return;
6859     }
6860     ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, std::nullopt, value, std::nullopt);
6861 }
6862 
SetPaddingRight(const JSCallbackInfo & info)6863 void JSViewAbstract::SetPaddingRight(const JSCallbackInfo& info)
6864 {
6865     CalcDimension value;
6866     if (!ParseJsDimensionVp(info[0], value)) {
6867         return;
6868     }
6869     ViewAbstractModel::GetInstance()->SetPaddings(std::nullopt, std::nullopt, std::nullopt, value);
6870 }
6871 
SetColorBlend(Color color)6872 void JSViewAbstract::SetColorBlend(Color color)
6873 {
6874     ViewAbstractModel::GetInstance()->SetColorBlend(color);
6875 }
6876 
SetLinearGradientBlur(NG::LinearGradientBlurPara blurPara)6877 void JSViewAbstract::SetLinearGradientBlur(NG::LinearGradientBlurPara blurPara)
6878 {
6879     ViewAbstractModel::GetInstance()->SetLinearGradientBlur(blurPara);
6880 }
6881 
SetDynamicLightUp(float rate,float lightUpDegree)6882 void JSViewAbstract::SetDynamicLightUp(float rate, float lightUpDegree)
6883 {
6884     ViewAbstractModel::GetInstance()->SetDynamicLightUp(rate, lightUpDegree);
6885 }
6886 
SetWindowBlur(float progress,WindowBlurStyle blurStyle)6887 void JSViewAbstract::SetWindowBlur(float progress, WindowBlurStyle blurStyle)
6888 {
6889     ViewAbstractModel::GetInstance()->SetWindowBlur(progress, blurStyle);
6890 }
6891 
ParseJsonDimension(const std::unique_ptr<JsonValue> & jsonValue,CalcDimension & result,DimensionUnit defaultUnit,bool checkIllegal)6892 bool JSViewAbstract::ParseJsonDimension(
6893     const std::unique_ptr<JsonValue>& jsonValue, CalcDimension& result, DimensionUnit defaultUnit, bool checkIllegal)
6894 {
6895     if (!jsonValue || jsonValue->IsNull()) {
6896         return false;
6897     }
6898     if (!jsonValue->IsNumber() && !jsonValue->IsString() && !jsonValue->IsObject()) {
6899         return false;
6900     }
6901     if (jsonValue->IsNumber()) {
6902         result = Dimension(jsonValue->GetDouble(), defaultUnit);
6903         return true;
6904     }
6905     if (jsonValue->IsString()) {
6906         if (checkIllegal) {
6907             return StringUtils::StringToDimensionWithUnitNG(jsonValue->GetString(), result, defaultUnit);
6908         }
6909         result = StringUtils::StringToCalcDimension(jsonValue->GetString(), false, defaultUnit);
6910         return true;
6911     }
6912     auto resVal = JsonUtil::ParseJsonString(jsonValue->ToString());
6913     auto resId = resVal->GetValue("id");
6914     if (!resId || !resId->IsNumber()) {
6915         return false;
6916     }
6917 
6918     auto resourceWrapper = CreateResourceWrapper();
6919     if (!resourceWrapper) {
6920         return false;
6921     }
6922     result = resourceWrapper->GetDimension(resId->GetUInt());
6923     return true;
6924 }
6925 
ParseJsonDimensionVp(const std::unique_ptr<JsonValue> & jsonValue,CalcDimension & result,bool checkIllegal)6926 bool JSViewAbstract::ParseJsonDimensionVp(
6927     const std::unique_ptr<JsonValue>& jsonValue, CalcDimension& result, bool checkIllegal)
6928 {
6929     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
6930         return ParseJsonDimension(jsonValue, result, DimensionUnit::VP, true);
6931     }
6932     return ParseJsonDimension(jsonValue, result, DimensionUnit::VP, checkIllegal);
6933 }
6934 
ParseJsonDouble(const std::unique_ptr<JsonValue> & jsonValue,double & result)6935 bool JSViewAbstract::ParseJsonDouble(const std::unique_ptr<JsonValue>& jsonValue, double& result)
6936 {
6937     if (!jsonValue || jsonValue->IsNull()) {
6938         return false;
6939     }
6940     if (!jsonValue->IsNumber() && !jsonValue->IsString() && !jsonValue->IsObject()) {
6941         return false;
6942     }
6943     if (jsonValue->IsNumber()) {
6944         result = jsonValue->GetDouble();
6945         return true;
6946     }
6947     if (jsonValue->IsString()) {
6948         result = StringUtils::StringToDouble(jsonValue->GetString());
6949         return true;
6950     }
6951     // parse json Resource
6952     auto resVal = JsonUtil::ParseJsonString(jsonValue->ToString());
6953     auto resId = resVal->GetValue("id");
6954     CHECK_NULL_RETURN(resId && resId->IsNumber(), false);
6955     auto id = resId->GetUInt();
6956     auto resType = resVal->GetValue("type");
6957     CHECK_NULL_RETURN(resType && resType->IsNumber(), false);
6958     auto type = resType->GetUInt();
6959 
6960     auto resourceWrapper = CreateResourceWrapper();
6961     if (!resourceWrapper) {
6962         return false;
6963     }
6964     if (type == static_cast<uint32_t>(ResourceType::STRING)) {
6965         auto numberString = resourceWrapper->GetString(id);
6966         return StringUtils::StringToDouble(numberString, result);
6967     }
6968     if (type == static_cast<uint32_t>(ResourceType::INTEGER)) {
6969         result = resourceWrapper->GetInt(id);
6970         return true;
6971     }
6972     if (type == static_cast<uint32_t>(ResourceType::FLOAT)) {
6973         result = resourceWrapper->GetDouble(id);
6974         return true;
6975     }
6976     return false;
6977 }
6978 
ParseJsonColor(const std::unique_ptr<JsonValue> & jsonValue,Color & result)6979 bool JSViewAbstract::ParseJsonColor(const std::unique_ptr<JsonValue>& jsonValue, Color& result)
6980 {
6981     if (!jsonValue || jsonValue->IsNull()) {
6982         return false;
6983     }
6984     if (!jsonValue->IsNumber() && !jsonValue->IsString() && !jsonValue->IsObject()) {
6985         return false;
6986     }
6987     if (jsonValue->IsNumber()) {
6988         result = Color(ColorAlphaAdapt(jsonValue->GetUInt()));
6989         return true;
6990     }
6991 
6992     bool isSetColor = false;
6993     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
6994         isSetColor = jsonValue->IsString();
6995     } else {
6996         isSetColor = jsonValue->IsString() && jsonValue->GetString() != "";
6997     }
6998     if (isSetColor) {
6999         result = Color::FromString(jsonValue->GetString());
7000         return true;
7001     }
7002     auto resVal = JsonUtil::ParseJsonString(jsonValue->ToString());
7003     auto resId = resVal->GetValue("id");
7004     if (!resId || !resId->IsNumber()) {
7005         return false;
7006     }
7007     auto resourceWrapper = CreateResourceWrapper();
7008     if (!resourceWrapper) {
7009         return false;
7010     }
7011     result = resourceWrapper->GetColor(resId->GetUInt());
7012     return true;
7013 }
7014 
ParseShadowProps(const JSRef<JSVal> & jsValue,Shadow & shadow)7015 bool JSViewAbstract::ParseShadowProps(const JSRef<JSVal>& jsValue, Shadow& shadow)
7016 {
7017     int32_t shadowStyle = 0;
7018     if (ParseJsInteger<int32_t>(jsValue, shadowStyle)) {
7019         auto style = static_cast<ShadowStyle>(shadowStyle);
7020         return GetShadowFromTheme(style, shadow);
7021     }
7022     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
7023     double radius = 0.0;
7024     ParseJsDouble(jsObj->GetProperty("radius"), radius);
7025     if (LessNotEqual(radius, 0.0)) {
7026         radius = 0.0;
7027     }
7028     shadow.SetBlurRadius(radius);
7029     CalcDimension offsetX;
7030     if (ParseJsResource(jsObj->GetProperty("offsetX"), offsetX)) {
7031         shadow.SetOffsetX(offsetX.Value());
7032     } else {
7033         if (ParseJsDimensionVp(jsObj->GetProperty("offsetX"), offsetX)) {
7034             shadow.SetOffsetX(offsetX.Value());
7035         }
7036     }
7037 
7038     CalcDimension offsetY;
7039     if (ParseJsResource(jsObj->GetProperty("offsetY"), offsetY)) {
7040         shadow.SetOffsetY(offsetY.Value());
7041     } else {
7042         if (ParseJsDimensionVp(jsObj->GetProperty("offsetY"), offsetY)) {
7043             shadow.SetOffsetY(offsetY.Value());
7044         }
7045     }
7046     Color color;
7047     ShadowColorStrategy shadowColorStrategy;
7048     if (ParseJsShadowColorStrategy(jsObj->GetProperty("color"), shadowColorStrategy)) {
7049         shadow.SetShadowColorStrategy(shadowColorStrategy);
7050     } else if (ParseJsColor(jsObj->GetProperty("color"), color)) {
7051         shadow.SetColor(color);
7052     }
7053     auto type = jsObj->GetPropertyValue<int32_t>("type", static_cast<int32_t>(ShadowType::COLOR));
7054     type = std::clamp(type, static_cast<int32_t>(ShadowType::COLOR), static_cast<int32_t>(ShadowType::BLUR));
7055     shadow.SetShadowType(static_cast<ShadowType>(type));
7056     bool isFilled = jsObj->GetPropertyValue<bool>("fill", false);
7057     shadow.SetIsFilled(isFilled);
7058     return true;
7059 }
7060 
GetShadowFromTheme(ShadowStyle shadowStyle,Shadow & shadow)7061 bool JSViewAbstract::GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow)
7062 {
7063     auto colorMode = SystemProperties::GetColorMode();
7064     if (shadowStyle == ShadowStyle::None) {
7065         return true;
7066     }
7067 
7068     auto container = Container::Current();
7069     CHECK_NULL_RETURN(container, false);
7070     auto pipelineContext = container->GetPipelineContext();
7071     CHECK_NULL_RETURN(pipelineContext, false);
7072 
7073     auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
7074     if (!shadowTheme) {
7075         return false;
7076     }
7077 
7078     shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
7079     return true;
7080 }
7081 
ParseJsResource(const JSRef<JSVal> & jsValue,CalcDimension & result)7082 bool JSViewAbstract::ParseJsResource(const JSRef<JSVal>& jsValue, CalcDimension& result)
7083 {
7084     if (!jsValue->IsObject()) {
7085         return false;
7086     }
7087     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
7088     auto resourceWrapper = CreateResourceWrapper();
7089     CHECK_NULL_RETURN(resourceWrapper, false);
7090     uint32_t type = jsObj->GetPropertyValue<uint32_t>("type", 0);
7091     if (type == static_cast<uint32_t>(ResourceType::STRING)) {
7092         auto value = resourceWrapper->GetString(jsObj->GetPropertyValue<uint32_t>("id", 0));
7093         return StringUtils::StringToCalcDimensionNG(value, result, false);
7094     }
7095     if (type == static_cast<uint32_t>(ResourceType::INTEGER)) {
7096         auto value = std::to_string(resourceWrapper->GetInt(jsObj->GetPropertyValue<uint32_t>("id", 0)));
7097         StringUtils::StringToDimensionWithUnitNG(value, result);
7098         return true;
7099     }
7100 
7101     if (type == static_cast<uint32_t>(ResourceType::FLOAT)) {
7102         result = resourceWrapper->GetDimension(jsObj->GetPropertyValue<uint32_t>("id", 0));
7103         return true;
7104     }
7105     return false;
7106 }
7107 
ParseDataDetectorConfig(const JSCallbackInfo & info,std::string & types,std::function<void (const std::string &)> & onResult)7108 bool JSViewAbstract::ParseDataDetectorConfig(
7109     const JSCallbackInfo& info, std::string& types, std::function<void(const std::string&)>& onResult)
7110 {
7111     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
7112     JSRef<JSVal> typeValue = obj->GetProperty("types");
7113     if (!typeValue->IsArray()) {
7114         return false;
7115     }
7116     JSRef<JSArray> array = JSRef<JSArray>::Cast(typeValue);
7117     for (size_t i = 0; i < array->Length(); i++) {
7118         JSRef<JSVal> value = array->GetValueAt(i);
7119         auto index = value->ToNumber<int32_t>();
7120         if (index < 0 || index >= static_cast<int32_t>(TEXT_DETECT_TYPES.size())) {
7121             return false;
7122         }
7123         if (i != 0) {
7124             types.append(",");
7125         }
7126         types.append(TEXT_DETECT_TYPES[index]);
7127     }
7128     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
7129     JSRef<JSVal> resultCallback = obj->GetProperty("onDetectResultUpdate");
7130     if (resultCallback->IsFunction()) {
7131         auto jsFunc = AceType::MakeRefPtr<JsClipboardFunction>(JSRef<JSFunc>::Cast(resultCallback));
7132         onResult = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
7133                        const std::string& result) {
7134             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7135             PipelineContext::SetCallBackNode(node);
7136             func->Execute(result);
7137         };
7138     }
7139     return true;
7140 }
7141 
GetAngle(const std::string & key,const std::unique_ptr<JsonValue> & jsonValue,std::optional<float> & angle)7142 void JSViewAbstract::GetAngle(
7143     const std::string& key, const std::unique_ptr<JsonValue>& jsonValue, std::optional<float>& angle)
7144 {
7145     auto value = jsonValue->GetValue(key);
7146     if (value && value->IsString()) {
7147         angle = static_cast<float>(StringUtils::StringToDegree(value->GetString()));
7148     } else if (value && value->IsNumber()) {
7149         angle = static_cast<float>(value->GetDouble());
7150     }
7151 }
7152 
GetJsAngle(const std::string & key,const JSRef<JSVal> & jsValue,std::optional<float> & angle)7153 void JSViewAbstract::GetJsAngle(
7154     const std::string& key, const JSRef<JSVal>& jsValue, std::optional<float>& angle)
7155 {
7156     if (!jsValue->IsObject()) {
7157         return;
7158     }
7159     JSRef<JSVal> value = JSRef<JSObject>::Cast(jsValue)->GetProperty(key.c_str());
7160     if (value->IsString()) {
7161         angle = static_cast<float>(StringUtils::StringToDegree(value->ToString()));
7162     } else if (value->IsNumber()) {
7163         angle = value->ToNumber<float>();
7164     }
7165 }
7166 
CheckAngle(std::optional<float> & angle)7167 void JSViewAbstract::CheckAngle(std::optional<float>& angle)
7168 {
7169     if (LessNotEqual(angle.value(), 0.0f)) {
7170         angle = 0.0f;
7171     } else if (GreatNotEqual(angle.value(), MAX_ANGLE)) {
7172         angle = MAX_ANGLE;
7173     }
7174 }
7175 
GetPerspective(const std::string & key,const std::unique_ptr<JsonValue> & jsonValue,float & perspective)7176 void JSViewAbstract::GetPerspective(
7177     const std::string& key, const std::unique_ptr<JsonValue>& jsonValue, float& perspective)
7178 {
7179     auto value = jsonValue->GetValue(key);
7180     if (value && value->IsNumber()) {
7181         perspective = static_cast<float>(value->GetDouble());
7182     }
7183 }
7184 
GetJsPerspective(const std::string & key,const JSRef<JSVal> & jsValue,float & perspective)7185 void JSViewAbstract::GetJsPerspective(const std::string& key, const JSRef<JSVal>& jsValue, float& perspective)
7186 {
7187     if (!jsValue->IsObject()) {
7188         return;
7189     }
7190     auto value = JSRef<JSObject>::Cast(jsValue)->GetProperty(key.c_str());
7191     if (value->IsNumber()) {
7192         perspective = value->ToNumber<float>();
7193     }
7194 }
7195 
GetGradientColorStops(Gradient & gradient,const std::unique_ptr<JsonValue> & colorStops)7196 void JSViewAbstract::GetGradientColorStops(Gradient& gradient, const std::unique_ptr<JsonValue>& colorStops)
7197 {
7198     if (!colorStops || colorStops->IsNull() || !colorStops->IsArray()) {
7199         return;
7200     }
7201 
7202     for (int32_t i = 0; i < colorStops->GetArraySize(); i++) {
7203         GradientColor gradientColor;
7204         auto item = colorStops->GetArrayItem(i);
7205         if (item && !item->IsNull() && item->IsArray() && item->GetArraySize() >= 1) {
7206             auto colorParams = item->GetArrayItem(0);
7207             // color
7208             Color color;
7209             if (!ParseJsonColor(colorParams, color)) {
7210                 continue;
7211             }
7212             gradientColor.SetColor(color);
7213             gradientColor.SetHasValue(false);
7214             // stop value
7215             if (item->GetArraySize() <= 1) {
7216                 continue;
7217             }
7218             auto stopValue = item->GetArrayItem(1);
7219             double value = 0.0;
7220             if (ParseJsonDouble(stopValue, value)) {
7221                 value = std::clamp(value, 0.0, 1.0);
7222                 gradientColor.SetHasValue(true);
7223                 gradientColor.SetDimension(CalcDimension(value * 100.0, DimensionUnit::PERCENT));
7224             }
7225             gradient.AddColor(gradientColor);
7226         }
7227     }
7228 }
7229 
NewGetGradientColorStops(NG::Gradient & gradient,const std::unique_ptr<JsonValue> & colorStops)7230 void JSViewAbstract::NewGetGradientColorStops(NG::Gradient& gradient, const std::unique_ptr<JsonValue>& colorStops)
7231 {
7232     if (!colorStops || colorStops->IsNull() || !colorStops->IsArray()) {
7233         return;
7234     }
7235 
7236     for (int32_t i = 0; i < colorStops->GetArraySize(); i++) {
7237         NG::GradientColor gradientColor;
7238         auto item = colorStops->GetArrayItem(i);
7239         if (item && !item->IsNull() && item->IsArray() && item->GetArraySize() >= 1) {
7240             auto colorParams = item->GetArrayItem(0);
7241             // color
7242             Color color;
7243             if (!ParseJsonColor(colorParams, color)) {
7244                 continue;
7245             }
7246             gradientColor.SetColor(color);
7247             gradientColor.SetHasValue(false);
7248             // stop value
7249             if (item->GetArraySize() <= 1) {
7250                 continue;
7251             }
7252             auto stopValue = item->GetArrayItem(1);
7253             double value = 0.0;
7254             if (ParseJsonDouble(stopValue, value)) {
7255                 value = std::clamp(value, 0.0, 1.0);
7256                 gradientColor.SetHasValue(true);
7257                 //  [0, 1] -> [0, 100.0];
7258                 gradientColor.SetDimension(CalcDimension(value * 100.0, DimensionUnit::PERCENT));
7259             }
7260             gradient.AddColor(gradientColor);
7261         }
7262     }
7263 }
7264 
NewGetJsGradientColorStops(NG::Gradient & gradient,const JSRef<JSVal> & colorStops)7265 void JSViewAbstract::NewGetJsGradientColorStops(NG::Gradient& gradient, const JSRef<JSVal>& colorStops)
7266 {
7267     if (!colorStops->IsArray()) {
7268         return;
7269     }
7270 
7271     JSRef<JSArray> jsArray = JSRef<JSArray>::Cast(colorStops);
7272     size_t length = jsArray->Length();
7273     for (size_t i = 0; i < length; i++) {
7274         NG::GradientColor gradientColor;
7275         JSRef<JSVal> item = jsArray->GetValueAt(i);
7276         if (!item->IsArray()) {
7277             continue;
7278         }
7279         JSRef<JSArray> subArray = JSRef<JSArray>::Cast(item);
7280         if (subArray->Length() < 2) {
7281             continue;
7282         }
7283         // color
7284         Color color;
7285         if (!ParseJsColor(subArray->GetValueAt(0), color)) {
7286             continue;
7287         }
7288         gradientColor.SetColor(color);
7289         gradientColor.SetHasValue(false);
7290         // stop value
7291         double value = 0.0;
7292         if (ParseJsDouble(subArray->GetValueAt(1), value)) {
7293             value = std::clamp(value, 0.0, 1.0);
7294             gradientColor.SetHasValue(true);
7295         }
7296         //  [0, 1] -> [0, 100.0];
7297         gradientColor.SetDimension(CalcDimension(value * 100.0, DimensionUnit::PERCENT));
7298         gradient.AddColor(gradientColor);
7299     }
7300 }
7301 
SetDirection(const std::string & dir)7302 void JSViewAbstract::SetDirection(const std::string& dir)
7303 {
7304     TextDirection direction = TextDirection::AUTO;
7305     if (dir == "Ltr") {
7306         direction = TextDirection::LTR;
7307     } else if (dir == "Rtl") {
7308         direction = TextDirection::RTL;
7309     } else if (dir == "Auto") {
7310         direction = TextDirection::AUTO;
7311     } else if (dir == "undefined" && Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
7312         direction = TextDirection::AUTO;
7313     }
7314     ViewAbstractModel::GetInstance()->SetLayoutDirection(direction);
7315 }
7316 
GetThemeConstants(const JSRef<JSObject> & jsObj)7317 RefPtr<ThemeConstants> JSViewAbstract::GetThemeConstants(const JSRef<JSObject>& jsObj)
7318 {
7319     std::string bundleName;
7320     std::string moduleName;
7321     if (!jsObj->IsUndefined()) {
7322         JSRef<JSVal> bundle = jsObj->GetProperty("bundleName");
7323         JSRef<JSVal> module = jsObj->GetProperty("moduleName");
7324         if (bundle->IsString() && module->IsString()) {
7325             bundleName = bundle->ToString();
7326             moduleName = module->ToString();
7327         }
7328     }
7329 
7330     auto cardId = CardScope::CurrentId();
7331     if (cardId != INVALID_CARD_ID) {
7332         auto container = Container::Current();
7333         auto weak = container->GetCardPipeline(cardId);
7334         auto cardPipelineContext = weak.Upgrade();
7335         CHECK_NULL_RETURN(cardPipelineContext, nullptr);
7336         auto cardThemeManager = cardPipelineContext->GetThemeManager();
7337         CHECK_NULL_RETURN(cardThemeManager, nullptr);
7338         return cardThemeManager->GetThemeConstants(bundleName, moduleName);
7339     }
7340 
7341 #ifdef PLUGIN_COMPONENT_SUPPORTED
7342     if (Container::CurrentId() >= MIN_PLUGIN_SUBCONTAINER_ID) {
7343         auto pluginContainer = PluginManager::GetInstance().GetPluginSubContainer(Container::CurrentId());
7344         if (!pluginContainer) {
7345             return nullptr;
7346         }
7347         auto pluginPipelineContext = pluginContainer->GetPipelineContext();
7348         if (!pluginPipelineContext) {
7349             return nullptr;
7350         }
7351         auto pluginThemeManager = pluginPipelineContext->GetThemeManager();
7352         if (!pluginThemeManager) {
7353             return nullptr;
7354         }
7355         return pluginThemeManager->GetThemeConstants(bundleName, moduleName);
7356     }
7357 #endif
7358     auto container = Container::Current();
7359     CHECK_NULL_RETURN(container, nullptr);
7360     auto pipelineContext = container->GetPipelineContext();
7361     CHECK_NULL_RETURN(pipelineContext, nullptr);
7362     auto themeManager = pipelineContext->GetThemeManager();
7363     CHECK_NULL_RETURN(themeManager, nullptr);
7364     return themeManager->GetThemeConstants(bundleName, moduleName);
7365 }
7366 
JsHoverEffect(const JSCallbackInfo & info)7367 void JSViewAbstract::JsHoverEffect(const JSCallbackInfo& info)
7368 {
7369     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::NUMBER };
7370     if (!CheckJSCallbackInfo("HoverEffect", info, checkList)) {
7371         ViewAbstractModel::GetInstance()->SetHoverEffect(HoverEffectType::AUTO);
7372         return;
7373     }
7374     if (!info[0]->IsNumber()) {
7375         return;
7376     }
7377     ViewAbstractModel::GetInstance()->SetHoverEffect(static_cast<HoverEffectType>(info[0]->ToNumber<int32_t>()));
7378 }
7379 
JsOnMouse(const JSCallbackInfo & info)7380 void JSViewAbstract::JsOnMouse(const JSCallbackInfo& info)
7381 {
7382     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
7383         ViewAbstractModel::GetInstance()->DisableOnMouse();
7384         return;
7385     }
7386     if (!info[0]->IsFunction()) {
7387         return;
7388     }
7389 
7390     RefPtr<JsClickFunction> jsOnMouseFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
7391     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
7392     auto onMouse = [execCtx = info.GetExecutionContext(), func = std::move(jsOnMouseFunc), node = targetNode](
7393                        MouseInfo& mouseInfo) {
7394         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7395         ACE_SCORING_EVENT("onMouse");
7396         PipelineContext::SetCallBackNode(node);
7397         func->Execute(mouseInfo);
7398     };
7399     ViewAbstractModel::GetInstance()->SetOnMouse(std::move(onMouse));
7400 }
7401 
JsOnHover(const JSCallbackInfo & info)7402 void JSViewAbstract::JsOnHover(const JSCallbackInfo& info)
7403 {
7404     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
7405         ViewAbstractModel::GetInstance()->DisableOnHover();
7406         return;
7407     }
7408     if (!info[0]->IsFunction()) {
7409         return;
7410     }
7411 
7412     RefPtr<JsHoverFunction> jsOnHoverFunc = AceType::MakeRefPtr<JsHoverFunction>(JSRef<JSFunc>::Cast(info[0]));
7413     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
7414     auto onHover = [execCtx = info.GetExecutionContext(), func = std::move(jsOnHoverFunc), node = frameNode](
7415                        bool isHover, HoverInfo& hoverInfo) {
7416         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7417         ACE_SCORING_EVENT("onHover");
7418         PipelineContext::SetCallBackNode(node);
7419         func->HoverExecute(isHover, hoverInfo);
7420     };
7421     ViewAbstractModel::GetInstance()->SetOnHover(std::move(onHover));
7422 }
7423 
JsOnClick(const JSCallbackInfo & info)7424 void JSViewAbstract::JsOnClick(const JSCallbackInfo& info)
7425 {
7426     if (info[0]->IsUndefined() && IsDisableEventVersion()) {
7427         ViewAbstractModel::GetInstance()->DisableOnClick();
7428         return;
7429     }
7430     if (!info[0]->IsFunction()) {
7431         return;
7432     }
7433 
7434     auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
7435     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
7436     auto onTap = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), node = targetNode](
7437                      GestureEvent& info) {
7438         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7439         ACE_SCORING_EVENT("onClick");
7440         PipelineContext::SetCallBackNode(node);
7441         func->Execute(info);
7442     };
7443     auto onClick = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, node = targetNode](
7444                        const ClickInfo* info) {
7445         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7446         ACE_SCORING_EVENT("onClick");
7447         PipelineContext::SetCallBackNode(node);
7448         func->Execute(*info);
7449     };
7450     ViewAbstractModel::GetInstance()->SetOnClick(std::move(onTap), std::move(onClick));
7451 }
7452 
JsOnGestureJudgeBegin(const JSCallbackInfo & info)7453 void JSViewAbstract::JsOnGestureJudgeBegin(const JSCallbackInfo& info)
7454 {
7455     if (info[0]->IsUndefined() || !info[0]->IsFunction()) {
7456         ViewAbstractModel::GetInstance()->SetOnGestureJudgeBegin(nullptr);
7457         return;
7458     }
7459 
7460     auto jsOnGestureJudgeFunc = AceType::MakeRefPtr<JsGestureJudgeFunction>(JSRef<JSFunc>::Cast(info[0]));
7461     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
7462     auto onGestureJudgefunc = [execCtx = info.GetExecutionContext(), func = jsOnGestureJudgeFunc, node = frameNode](
7463                                   const RefPtr<NG::GestureInfo>& gestureInfo,
7464                                   const std::shared_ptr<BaseGestureEvent>& info) -> GestureJudgeResult {
7465         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, GestureJudgeResult::CONTINUE);
7466         ACE_SCORING_EVENT("onGestureJudgeBegin");
7467         PipelineContext::SetCallBackNode(node);
7468         return func->Execute(gestureInfo, info);
7469     };
7470     ViewAbstractModel::GetInstance()->SetOnGestureJudgeBegin(std::move(onGestureJudgefunc));
7471 }
7472 
JsClickEffect(const JSCallbackInfo & info)7473 void JSViewAbstract::JsClickEffect(const JSCallbackInfo& info)
7474 {
7475     if (info[0]->IsUndefined() || info[0]->IsNull()) {
7476         ViewAbstractModel::GetInstance()->SetClickEffectLevel(ClickEffectLevel::UNDEFINED, DEFAULT_SCALE_LIGHT);
7477         return;
7478     }
7479     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
7480     JSRef<JSVal> clickEffectLevel = obj->GetProperty("level");
7481     int32_t clickEffectLevelValue = 0;
7482     if (clickEffectLevel->IsNumber()) {
7483         clickEffectLevelValue = clickEffectLevel->ToNumber<int32_t>();
7484         if (clickEffectLevelValue < static_cast<int32_t>(ClickEffectLevel::LIGHT) ||
7485             clickEffectLevelValue > static_cast<int32_t>(ClickEffectLevel::HEAVY)) {
7486             clickEffectLevelValue = 0;
7487         }
7488     }
7489 
7490     JSRef<JSVal> scaleNumber = obj->GetProperty("scale");
7491     float scaleNumberValue = DEFAULT_SCALE_LIGHT;
7492     if (!scaleNumber->IsNumber()) {
7493         if ((ClickEffectLevel)clickEffectLevelValue == ClickEffectLevel::MIDDLE ||
7494             (ClickEffectLevel)clickEffectLevelValue == ClickEffectLevel::HEAVY) {
7495             scaleNumberValue = DEFAULT_SCALE_MIDDLE_OR_HEAVY;
7496         }
7497         ViewAbstractModel::GetInstance()->SetClickEffectLevel(
7498             (ClickEffectLevel)clickEffectLevelValue, scaleNumberValue);
7499         return;
7500     }
7501 
7502     scaleNumberValue = scaleNumber->ToNumber<float>();
7503     if (LessNotEqual(scaleNumberValue, 0.0) || GreatNotEqual(scaleNumberValue, 1.0)) {
7504         if ((ClickEffectLevel)clickEffectLevelValue == ClickEffectLevel::MIDDLE ||
7505             (ClickEffectLevel)clickEffectLevelValue == ClickEffectLevel::HEAVY) {
7506             scaleNumberValue = DEFAULT_SCALE_MIDDLE_OR_HEAVY;
7507         } else {
7508             scaleNumberValue = DEFAULT_SCALE_LIGHT;
7509         }
7510     }
7511 
7512     ViewAbstractModel::GetInstance()->SetClickEffectLevel((ClickEffectLevel)clickEffectLevelValue, scaleNumberValue);
7513 }
7514 
JsOnVisibleAreaChange(const JSCallbackInfo & info)7515 void JSViewAbstract::JsOnVisibleAreaChange(const JSCallbackInfo& info)
7516 {
7517     if (info.Length() != 2) {
7518         return;
7519     }
7520 
7521     if (!info[0]->IsArray() || !info[1]->IsFunction()) {
7522         return;
7523     }
7524 
7525     auto ratioArray = JSRef<JSArray>::Cast(info[0]);
7526     size_t size = ratioArray->Length();
7527     std::vector<double> ratioVec(size);
7528     ratioVec.clear();
7529     for (size_t i = 0; i < size; i++) {
7530         double ratio = 0.0;
7531         ParseJsDouble(ratioArray->GetValueAt(i), ratio);
7532         if (LessOrEqual(ratio, VISIBLE_RATIO_MIN)) {
7533             ratio = VISIBLE_RATIO_MIN;
7534         }
7535 
7536         if (GreatOrEqual(ratio, VISIBLE_RATIO_MAX)) {
7537             ratio = VISIBLE_RATIO_MAX;
7538         }
7539         ratioVec.push_back(ratio);
7540     }
7541 
7542     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[1]));
7543     WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
7544     auto onVisibleChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
7545                                bool visible, double ratio) {
7546         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7547         ACE_SCORING_EVENT("onVisibleAreaChange");
7548 
7549         JSRef<JSVal> params[2];
7550         params[0] = JSRef<JSVal>::Make(ToJSValue(visible));
7551         params[1] = JSRef<JSVal>::Make(ToJSValue(ratio));
7552         PipelineContext::SetCallBackNode(node);
7553         func->ExecuteJS(2, params);
7554     };
7555     ViewAbstractModel::GetInstance()->SetOnVisibleChange(std::move(onVisibleChange), ratioVec);
7556 }
7557 
JsHitTestBehavior(const JSCallbackInfo & info)7558 void JSViewAbstract::JsHitTestBehavior(const JSCallbackInfo& info)
7559 {
7560     if (info.Length() != 1) {
7561         return;
7562     }
7563 
7564     NG::HitTestMode hitTestModeNG = NG::HitTestMode::HTMDEFAULT;
7565     hitTestModeNG = static_cast<NG::HitTestMode>(info[0]->ToNumber<int32_t>());
7566     ViewAbstractModel::GetInstance()->SetHitTestMode(hitTestModeNG);
7567 }
7568 
JsOnChildTouchTest(const JSCallbackInfo & info)7569 void JSViewAbstract::JsOnChildTouchTest(const JSCallbackInfo& info)
7570 {
7571     std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::FUNCTION };
7572     if (!CheckJSCallbackInfo("onChildTouchTest", info, checkList)) {
7573         return;
7574     }
7575 
7576     RefPtr<JsOnChildTouchTestFunction> jsOnChildTouchTestFunc =
7577         AceType::MakeRefPtr<JsOnChildTouchTestFunction>(JSRef<JSFunc>::Cast(info[0]));
7578 
7579     auto onTouchTestFunc = [execCtx = info.GetExecutionContext(), func = std::move(jsOnChildTouchTestFunc)](
7580                                const std::vector<NG::TouchTestInfo>& touchInfo) -> NG::TouchResult {
7581         NG::TouchResult touchRes;
7582         NG::TouchResult defaultRes;
7583         defaultRes.strategy = NG::TouchTestStrategy::DEFAULT;
7584         defaultRes.id = "";
7585         auto ret = func->Execute(touchInfo);
7586         if (!ret->IsObject()) {
7587             TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest return value is not object, parse failed.");
7588             return defaultRes;
7589         }
7590 
7591         auto retObj = JSRef<JSObject>::Cast(ret);
7592         auto strategy = retObj->GetProperty("strategy");
7593         if (!strategy->IsNumber()) {
7594             TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest return value strategy is not number, parse failed.");
7595             return defaultRes;
7596         }
7597         touchRes.strategy = static_cast<NG::TouchTestStrategy>(strategy->ToNumber<int32_t>());
7598         auto id = retObj->GetProperty("id");
7599         if (!id->IsString()) {
7600             TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest return value id is not string, parse failed.");
7601             return defaultRes;
7602         }
7603         touchRes.id = id->ToString();
7604         return touchRes;
7605     };
7606     ViewAbstractModel::GetInstance()->SetOnTouchTestFunc(std::move(onTouchTestFunc));
7607 }
7608 
JsForegroundColor(const JSCallbackInfo & info)7609 void JSViewAbstract::JsForegroundColor(const JSCallbackInfo& info)
7610 {
7611     Color foregroundColor;
7612     ForegroundColorStrategy strategy;
7613     if (ParseJsColorStrategy(info[0], strategy)) {
7614         ViewAbstractModel::GetInstance()->SetForegroundColorStrategy(strategy);
7615         return;
7616     }
7617     if (!ParseJsColor(info[0], foregroundColor)) {
7618         return;
7619     }
7620     ViewAbstractModel::GetInstance()->SetForegroundColor(foregroundColor);
7621 }
7622 
JsKeyboardShortcut(const JSCallbackInfo & info)7623 void JSViewAbstract::JsKeyboardShortcut(const JSCallbackInfo& info)
7624 {
7625     // KeyboardShortcut only allows 2 or 3 params.
7626     if (info.Length() < 2 || info.Length() > 3) {
7627         return;
7628     }
7629     if ((!info[0]->IsString() && !info[0]->IsNumber()) || !info[1]->IsArray()) {
7630         ViewAbstractModel::GetInstance()->SetKeyboardShortcut("", std::vector<ModifierKey>(), nullptr);
7631         return;
7632     }
7633 
7634     std::string value;
7635     if (info[0]->IsString()) {
7636         value = info[0]->ToString();
7637         if (value.empty() || value.size() > 1) {
7638             ViewAbstractModel::GetInstance()->SetKeyboardShortcut("", std::vector<ModifierKey>(), nullptr);
7639             return;
7640         }
7641     } else {
7642         FunctionKey functionkey = static_cast<FunctionKey>(info[0]->ToNumber<int32_t>());
7643         value = GetFunctionKeyName(functionkey);
7644     }
7645 
7646     auto keysArray = JSRef<JSArray>::Cast(info[1]);
7647     size_t size = keysArray->Length();
7648     std::vector<ModifierKey> keys(size);
7649     keys.clear();
7650     for (size_t i = 0; i < size; i++) {
7651         JSRef<JSVal> key = keysArray->GetValueAt(i);
7652         if (key->IsNumber()) {
7653             keys.emplace_back(static_cast<ModifierKey>(key->ToNumber<int32_t>()));
7654         }
7655     }
7656 
7657     // KeyboardShortcut allows 3 params, the third param is function callback.
7658     if (info.Length() == 3 && info[2]->IsFunction()) {
7659         RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[2]));
7660         WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
7661         auto onKeyboardShortcutAction = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
7662                                             node = frameNode]() {
7663             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
7664             ACE_SCORING_EVENT("onKeyboardShortcutAction");
7665             PipelineContext::SetCallBackNode(node);
7666             func->ExecuteJS();
7667         };
7668         ViewAbstractModel::GetInstance()->SetKeyboardShortcut(value, keys, std::move(onKeyboardShortcutAction));
7669         return;
7670     }
7671     ViewAbstractModel::GetInstance()->SetKeyboardShortcut(value, keys, nullptr);
7672 }
7673 
CheckColor(const JSRef<JSVal> & jsValue,Color & result,const char * componentName,const char * propName)7674 bool JSViewAbstract::CheckColor(
7675     const JSRef<JSVal>& jsValue, Color& result, const char* componentName, const char* propName)
7676 {
7677     // Color is undefined or null
7678     if (jsValue->IsUndefined() || jsValue->IsNull()) {
7679         return false;
7680     }
7681     // input type is not in [number, string, Resource]
7682     if (!jsValue->IsNumber() && !jsValue->IsString() && !jsValue->IsObject()) {
7683         return false;
7684     }
7685     // Correct type, incorrect value parsing
7686     if (!ParseJsColor(jsValue, result)) {
7687         return false;
7688     }
7689     return true;
7690 }
7691 
CheckLength(const JSRef<JSVal> & jsValue,CalcDimension & result,const char * componentName,const char * propName)7692 bool JSViewAbstract::CheckLength(
7693     const JSRef<JSVal>& jsValue, CalcDimension& result, const char* componentName, const char* propName)
7694 {
7695     // Length is undefined or null
7696     if (jsValue->IsUndefined() || jsValue->IsNull()) {
7697         return false;
7698     }
7699     // input type is not in [number, string, Resource]
7700     if (!jsValue->IsNumber() && !jsValue->IsString() && !jsValue->IsObject()) {
7701         return false;
7702     }
7703     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN)) {
7704         return ParseJsDimensionVpNG(jsValue, result);
7705     }
7706     // Correct type, incorrect value parsing
7707     if (!ParseJsDimensionVp(jsValue, result)) {
7708         return false;
7709     }
7710     return true;
7711 }
7712 
JsObscured(const JSCallbackInfo & info)7713 void JSViewAbstract::JsObscured(const JSCallbackInfo& info)
7714 {
7715     if (info[0]->IsUndefined()) {
7716         std::vector<ObscuredReasons> reasons(0);
7717         ViewAbstractModel::GetInstance()->SetObscured(reasons);
7718         return;
7719     }
7720     if (!info[0]->IsArray()) {
7721         return;
7722     }
7723 
7724     auto obscuredArray = JSRef<JSArray>::Cast(info[0]);
7725     size_t size = obscuredArray->Length();
7726     std::vector<ObscuredReasons> reasons(size);
7727     reasons.clear();
7728     for (size_t i = 0; i < size; i++) {
7729         JSRef<JSVal> reason = obscuredArray->GetValueAt(i);
7730         if (reason->IsNumber()) {
7731             reasons.emplace_back(static_cast<ObscuredReasons>(reason->ToNumber<int32_t>()));
7732         }
7733     }
7734 
7735     ViewAbstractModel::GetInstance()->SetObscured(reasons);
7736 }
7737 
JSRenderGroup(const JSCallbackInfo & info)7738 void JSViewAbstract::JSRenderGroup(const JSCallbackInfo& info)
7739 {
7740     if (info.Length() != 1) {
7741         return;
7742     }
7743     bool isRenderGroup = false;
7744     if (info[0]->IsBoolean()) {
7745         isRenderGroup = info[0]->ToBoolean();
7746     }
7747     ViewAbstractModel::GetInstance()->SetRenderGroup(isRenderGroup);
7748 }
7749 
JSRenderFit(const JSCallbackInfo & info)7750 void JSViewAbstract::JSRenderFit(const JSCallbackInfo& info)
7751 {
7752     if (info.Length() != 1) {
7753         return;
7754     }
7755     RenderFit renderFit = RenderFit::TOP_LEFT;
7756     if (info[0]->IsNumber()) {
7757         int32_t fitNumber = info[0]->ToNumber<int32_t>();
7758         if (fitNumber >= static_cast<int32_t>(RenderFit::CENTER) &&
7759             fitNumber <= static_cast<int32_t>(RenderFit::RESIZE_COVER_BOTTOM_RIGHT)) {
7760             renderFit = static_cast<RenderFit>(fitNumber);
7761         }
7762     }
7763     // how content fills the node duration implicit animation
7764     ViewAbstractModel::GetInstance()->SetRenderFit(renderFit);
7765 }
7766 
GetJsMediaBundleInfo(const JSRef<JSVal> & jsValue,std::string & bundleName,std::string & moduleName)7767 void JSViewAbstract::GetJsMediaBundleInfo(const JSRef<JSVal>& jsValue, std::string& bundleName, std::string& moduleName)
7768 {
7769     if (!jsValue->IsObject() || jsValue->IsString()) {
7770         return;
7771     }
7772     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
7773     if (!jsObj->IsUndefined()) {
7774         JSRef<JSVal> bundle = jsObj->GetProperty("bundleName");
7775         JSRef<JSVal> module = jsObj->GetProperty("moduleName");
7776         if (bundle->IsString() && module->IsString()) {
7777             bundleName = bundle->ToString();
7778             moduleName = module->ToString();
7779         }
7780     }
7781 }
7782 
ParseImageAnalyzerSubjectOptions(const JSRef<JSVal> & optionVal,ImageAnalyzerConfig & analyzerConfig)7783 void JSViewAbstract::ParseImageAnalyzerSubjectOptions(const JSRef<JSVal>& optionVal,
7784     ImageAnalyzerConfig& analyzerConfig)
7785 {
7786     ImageAnalyzerSubjectOptions subjectOptions;
7787     auto obj = JSRef<JSObject>::Cast(optionVal);
7788     JSRef<JSVal> onAnalyzedVal = obj->GetProperty("onAnalyzed");
7789     if (onAnalyzedVal->IsFunction()) {
7790         RefPtr<JsFunction> jsOnAnalyzedFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(),
7791             JSRef<JSFunc>::Cast(onAnalyzedVal));
7792         onSubcjectAnalyzedFunc onAnalyzedCallback =
7793             [func = std::move(jsOnAnalyzedFunc)](std::string tag, std::vector<uint8_t> data) {
7794             JSRef<JSVal> params[2];
7795             params[0] = JSRef<JSVal>::Make(ToJSValue(tag));
7796             JSRef<JSArray> indexArray = JSRef<JSArray>::New();
7797             for (uint32_t i = 0; i < data.size(); i++) {
7798                 indexArray->SetValueAt(i, JSRef<JSVal>::Make(ToJSValue(data[i])));
7799             }
7800             params[1] = JSRef<JSVal>::Cast(indexArray);
7801             func->ExecuteJS(2, params);
7802         };
7803         subjectOptions.onAnalyzedCallback = std::move(onAnalyzedCallback);
7804     }
7805 
7806     JSRef<JSVal> dataVal = obj->GetProperty("analyzedData");
7807     if (dataVal->IsArray()) {
7808         JSRef<JSArray> dataArray  = JSRef<JSArray>::Cast(dataVal);
7809         std::vector<uint8_t> analyzedData;
7810         for (size_t i = 0; i < dataArray->Length(); ++i) {
7811             JSRef<JSVal> value = dataArray->GetValueAt(i);
7812             if (value->IsNumber()) {
7813                 analyzedData.emplace_back(value->ToNumber<uint8_t>());
7814             }
7815         }
7816         subjectOptions.analyzedData = std::move(analyzedData);
7817     }
7818 
7819 #if defined(PIXEL_MAP_SUPPORTED)
7820     auto pixmapVal = obj->GetProperty("sourcePixelmap");
7821     RefPtr<PixelMap> pixmap = CreatePixelMapFromNapiValue(pixmapVal);
7822     if (pixmap != nullptr) {
7823         subjectOptions.sourcePixelmap = ConvertPixmapNapi(pixmap);
7824     }
7825 #endif
7826     analyzerConfig.subjectOptions_ = std::move(subjectOptions);
7827 }
7828 
ParseImageAnalyzerTextOptions(const JSRef<JSVal> & optionVal,ImageAnalyzerConfig & analyzerConfig)7829 void JSViewAbstract::ParseImageAnalyzerTextOptions(const JSRef<JSVal>& optionVal, ImageAnalyzerConfig& analyzerConfig)
7830 {
7831     ImageAnalyzerTextOptions textOptions;
7832     auto obj = JSRef<JSObject>::Cast(optionVal);
7833     JSRef<JSVal> onAnalyzedVal = obj->GetProperty("onAnalyzed");
7834     if (onAnalyzedVal->IsFunction()) {
7835         RefPtr<JsFunction> jsFunc =
7836             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAnalyzedVal));
7837         onTextAnalyzedFunc onAnalyzedCallback = [func = std::move(jsFunc)] (
7838             std::string tag, std::string data) {
7839             JSRef<JSVal> params[2];
7840             params[0] = JSRef<JSVal>::Make(ToJSValue(tag));
7841             params[1] = JSRef<JSVal>::Make(ToJSValue(data));
7842             func->ExecuteJS(2, params);
7843         };
7844         textOptions.onAnalyzedCallback = std::move(onAnalyzedCallback);
7845     }
7846 
7847     JSRef<JSVal> onTextSelected = obj->GetProperty("onTextSelected");
7848     if (onTextSelected->IsFunction()) {
7849         RefPtr<JsFunction> jsOnTextSelectedFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(),
7850         JSRef<JSFunc>::Cast(onTextSelected));
7851         onTextSelectedFunc onTextSelectedCallback =
7852             [func = std::move(jsOnTextSelectedFunc)] (std::string tag, std::string data) {
7853             JSRef<JSVal> params[2];
7854             params[0] = JSRef<JSVal>::Make(ToJSValue(tag));
7855             params[1] = JSRef<JSVal>::Make(ToJSValue(data));
7856             func->ExecuteJS(2, params);
7857         };
7858         textOptions.onTextSelected = std::move(onTextSelectedCallback);
7859     }
7860 
7861     JSRef<JSVal> dataVal = obj->GetProperty("analyzedData");
7862     if (dataVal->IsArray()) {
7863         std::string analyzedData = dataVal->ToString();
7864         textOptions.analyzedData = std::move(analyzedData);
7865     }
7866     analyzerConfig.textOptions = std::move(textOptions);
7867 }
7868 } // namespace OHOS::Ace::Framework
7869