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