1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_badge_bridge.h"
16 
17 #include "base/geometry/dimension.h"
18 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_theme_utils.h"
19 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
20 #include "core/components/badge/badge_theme.h"
21 #include "core/components/common/properties/text_style.h"
22 
23 namespace OHOS::Ace::NG {
24 namespace {
25 constexpr int32_t DEFAULT_BADGE_POSITION = 0;
26 constexpr Dimension UNDEFINED_DIMENSION(-1.0, DimensionUnit::VP);
27 const uint32_t DEFAULT_TEXT_COLOR = Color::WHITE.GetValue();
28 const uint32_t DEFAULT_BADGE_COLOR = Color::RED.GetValue();
InitBadgeParam(const RefPtr<BadgeTheme> & badgeTheme,ArkUIBadgeParam & param)29 bool InitBadgeParam(const RefPtr<BadgeTheme>& badgeTheme, ArkUIBadgeParam& param)
30 {
31     CHECK_NULL_RETURN(badgeTheme, false);
32     auto positionX = badgeTheme->GetBadgePositionX();
33     auto positionY = badgeTheme->GetBadgePositionY();
34     auto fontSize = badgeTheme->GetBadgeFontSize();
35     auto circleSize = badgeTheme->GetBadgeCircleSize();
36     auto borderWidth = badgeTheme->GetBadgeBorderWidth();
37     auto themeColors = Framework::JSThemeUtils::GetThemeColors();
38     param.position = DEFAULT_BADGE_POSITION;
39     param.isPositionXy = false;
40     param.positionX.value = positionX.Value();
41     param.positionX.units = static_cast<int32_t>(positionX.Unit());
42     param.positionY.value = positionY.Value();
43     param.positionY.units = static_cast<int32_t>(positionY.Unit());
44     if (themeColors.has_value()) {
45         param.textColor = themeColors->FontOnPrimary().GetValue();
46         param.badgeColor = themeColors->Warning().GetValue();
47     } else {
48         param.textColor = DEFAULT_TEXT_COLOR;
49         param.badgeColor = DEFAULT_BADGE_COLOR;
50     }
51     param.fontSize.value = fontSize.Value();
52     param.fontSize.units = static_cast<int32_t>(fontSize.Unit());
53     param.badgeSize.value = circleSize.Value();
54     param.badgeSize.units = static_cast<int32_t>(fontSize.Unit());
55     param.borderColor = themeColors ? themeColors->Warning().GetValue() : badgeTheme->GetBadgeBorderColor().GetValue();
56     param.borderWidth.value = borderWidth.Value();
57     param.borderWidth.units = static_cast<int32_t>(borderWidth.Unit());
58     param.fontWeight = static_cast<int32_t>(FontWeight::NORMAL);
59     param.isDefaultFontSize = true;
60     param.isDefaultBadgeSize = true;
61     return true;
62 }
63 
ParsePosition(const EcmaVM * vm,const ArkUIRuntimeCallInfo * runtimeCallInfo,ArkUIBadgeParam & param)64 void ParsePosition(const EcmaVM* vm, const ArkUIRuntimeCallInfo* runtimeCallInfo, ArkUIBadgeParam& param)
65 {
66     CHECK_NULL_VOID(vm);
67     CHECK_NULL_VOID(runtimeCallInfo);
68     Local<JSValueRef> position = runtimeCallInfo->GetCallArgRef(1);
69     Local<JSValueRef> positionX = runtimeCallInfo->GetCallArgRef(2);    // 2: parameter index
70     Local<JSValueRef> positionY = runtimeCallInfo->GetCallArgRef(3);    // 3: parameter index
71     Local<JSValueRef> positionObj = runtimeCallInfo->GetCallArgRef(11); // 11: parameter index
72     if (!position->IsNull() && position->IsNumber()) {
73         param.isPositionXy = false;
74         param.position = position->Int32Value(vm);
75     } else if (!positionX->IsUndefined() || !positionY->IsUndefined() ||
76                (positionObj->IsBoolean() && positionObj->ToBoolean(vm)->Value())) {
77         param.isPositionXy = true;
78         CalcDimension dimenX;
79         CalcDimension dimenY;
80         bool xResult = ArkTSUtils::ParseJsDimensionVp(vm, positionX, dimenX);
81         bool yResult = ArkTSUtils::ParseJsDimensionVp(vm, positionY, dimenY);
82         if (xResult || yResult) {
83             param.positionX.value = dimenX.Value();
84             param.positionX.units = static_cast<int32_t>(dimenX.Unit());
85             param.positionY.value = dimenY.Value();
86             param.positionY.units = static_cast<int32_t>(dimenY.Unit());
87         }
88     }
89 }
90 
ParseFontSize(const EcmaVM * vm,const ArkUIRuntimeCallInfo * runtimeCallInfo,ArkUIBadgeParam & param)91 void ParseFontSize(const EcmaVM* vm, const ArkUIRuntimeCallInfo* runtimeCallInfo, ArkUIBadgeParam& param)
92 {
93     CHECK_NULL_VOID(vm);
94     CHECK_NULL_VOID(runtimeCallInfo);
95     Local<JSValueRef> fontSize = runtimeCallInfo->GetCallArgRef(9); // 9: parameter index
96     CalcDimension fontSizeVal;
97     if (ArkTSUtils::ParseJsDimensionNG(vm, fontSize, fontSizeVal, DimensionUnit::FP)) {
98         if (fontSizeVal.IsNonNegative() && fontSizeVal.Unit() != DimensionUnit::PERCENT) {
99             param.fontSize.value = fontSizeVal.Value();
100             param.fontSize.units = static_cast<int32_t>(fontSizeVal.Unit());
101             param.isDefaultFontSize = false;
102         }
103     } else if (fontSize->IsUndefined()) {
104         param.fontSize.value = UNDEFINED_DIMENSION.Value();
105         param.fontSize.units = static_cast<int32_t>(UNDEFINED_DIMENSION.Unit());
106     }
107 }
108 
ParseBadgeSize(const EcmaVM * vm,const ArkUIRuntimeCallInfo * runtimeCallInfo,ArkUIBadgeParam & param)109 void ParseBadgeSize(const EcmaVM* vm, const ArkUIRuntimeCallInfo* runtimeCallInfo, ArkUIBadgeParam& param)
110 {
111     CHECK_NULL_VOID(vm);
112     CHECK_NULL_VOID(runtimeCallInfo);
113     Local<JSValueRef> badgeSize = runtimeCallInfo->GetCallArgRef(5); // 5: parameter index
114     CalcDimension badgeSizeVal;
115     if (ArkTSUtils::ParseJsDimensionNG(vm, badgeSize, badgeSizeVal, DimensionUnit::FP)) {
116         if (badgeSizeVal.IsNonNegative() && badgeSizeVal.Unit() != DimensionUnit::PERCENT) {
117             param.badgeSize.value = badgeSizeVal.Value();
118             param.badgeSize.units = static_cast<int32_t>(badgeSizeVal.Unit());
119             param.isDefaultBadgeSize = false;
120         }
121     }
122 }
123 
ParseBadgeBaseParam(const EcmaVM * vm,const ArkUIRuntimeCallInfo * runtimeCallInfo,const RefPtr<BadgeTheme> & badgeTheme,ArkUIBadgeParam & param)124 bool ParseBadgeBaseParam(const EcmaVM* vm, const ArkUIRuntimeCallInfo* runtimeCallInfo,
125     const RefPtr<BadgeTheme>& badgeTheme, ArkUIBadgeParam& param)
126 {
127     CHECK_NULL_RETURN(vm, false);
128     CHECK_NULL_RETURN(runtimeCallInfo, false);
129     CHECK_NULL_RETURN(badgeTheme, false);
130     Local<JSValueRef> badgeColor = runtimeCallInfo->GetCallArgRef(4);  // 4: parameter index
131     Local<JSValueRef> borderColor = runtimeCallInfo->GetCallArgRef(6); // 6: parameter index
132     Local<JSValueRef> borderWidth = runtimeCallInfo->GetCallArgRef(7); // 7: parameter index
133     Local<JSValueRef> textColor = runtimeCallInfo->GetCallArgRef(8);   // 8: parameter index
134     Local<JSValueRef> fontWeight = runtimeCallInfo->GetCallArgRef(10); // 10: parameter index
135     if (!InitBadgeParam(badgeTheme, param)) {
136         return false;
137     }
138     ParsePosition(vm, runtimeCallInfo, param);
139     ParseFontSize(vm, runtimeCallInfo, param);
140     ParseBadgeSize(vm, runtimeCallInfo, param);
141 
142     Color badgeColorVal, textColorVal, borderColorVal;
143     if (ArkTSUtils::ParseJsColor(vm, badgeColor, badgeColorVal)) {
144         param.badgeColor = badgeColorVal.GetValue();
145     }
146     if (ArkTSUtils::ParseJsColorAlpha(vm, textColor, textColorVal)) {
147         param.textColor = textColorVal.GetValue();
148     }
149     if (ArkTSUtils::ParseJsColorAlpha(vm, borderColor, borderColorVal)) {
150         param.borderColor = borderColorVal.GetValue();
151     }
152     std::string fontWeightVal;
153     if (fontWeight->IsNumber()) {
154         fontWeightVal = std::to_string(fontWeight->Int32Value(vm));
155     } else {
156         ArkTSUtils::ParseJsString(vm, fontWeight, fontWeightVal);
157     }
158     CalcDimension borderWidthVal;
159     if (ArkTSUtils::ParseJsDimensionVp(vm, borderWidth, borderWidthVal)) {
160         if (borderWidthVal.IsNonNegative() && borderWidthVal.Unit() != DimensionUnit::PERCENT) {
161             param.borderWidth.value = borderWidthVal.Value();
162             param.borderWidth.units = static_cast<int32_t>(borderWidthVal.Unit());
163         }
164     }
165     param.fontWeight = static_cast<ArkUI_Int32>(Framework::ConvertStrToFontWeight(fontWeightVal));
166     return true;
167 }
168 } // namespace
169 
SetBadgeParamWithNumber(ArkUIRuntimeCallInfo * runtimeCallInfo)170 ArkUINativeModuleValue BadgeBridge::SetBadgeParamWithNumber(ArkUIRuntimeCallInfo* runtimeCallInfo)
171 {
172     EcmaVM* vm = runtimeCallInfo->GetVM();
173     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
174     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
175     Local<JSValueRef> countArg = runtimeCallInfo->GetCallArgRef(12);    // 12: parameter index
176     Local<JSValueRef> maxCountArg = runtimeCallInfo->GetCallArgRef(13); // 13: parameter index
177     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
178 
179     ArkUIBadgeParam style;
180     int32_t count = 0;
181     int32_t maxCount = 0;
182     bool hasValue = false;
183     auto badgeTheme = ArkTSUtils::GetTheme<BadgeTheme>();
184     CHECK_NULL_RETURN(badgeTheme, panda::JSValueRef::Undefined(vm));
185     if (!ParseBadgeBaseParam(vm, runtimeCallInfo, badgeTheme, style)) {
186         return panda::JSValueRef::Undefined(vm);
187     }
188     if (!countArg->IsNull() && countArg->IsNumber()) {
189         count = countArg->Int32Value(vm);
190         hasValue = true;
191     }
192     if (!maxCountArg->IsNull() && maxCountArg->IsNumber()) {
193         maxCount = maxCountArg->Int32Value(vm);
194     } else {
195         maxCount = badgeTheme->GetMaxCount();
196     }
197 
198     GetArkUINodeModifiers()->getBadgeModifier()->setBadgeParamWithNumber(nativeNode, &style, count, hasValue, maxCount);
199     return panda::JSValueRef::Undefined(vm);
200 }
201 
SetBadgeParamWithString(ArkUIRuntimeCallInfo * runtimeCallInfo)202 ArkUINativeModuleValue BadgeBridge::SetBadgeParamWithString(ArkUIRuntimeCallInfo* runtimeCallInfo)
203 {
204     EcmaVM* vm = runtimeCallInfo->GetVM();
205     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
206     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
207     Local<JSValueRef> valueArg = runtimeCallInfo->GetCallArgRef(12); // 12: parameter index
208     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
209 
210     ArkUIBadgeParam style;
211     const char* value = nullptr;
212     auto badgeTheme = ArkTSUtils::GetTheme<BadgeTheme>();
213     CHECK_NULL_RETURN(badgeTheme, panda::JSValueRef::Undefined(vm));
214     if (!ParseBadgeBaseParam(vm, runtimeCallInfo, badgeTheme, style)) {
215         return panda::JSValueRef::Undefined(vm);
216     }
217     if (!valueArg->IsNull() && valueArg->IsString(vm)) {
218         value = valueArg->ToString(vm)->ToString(vm).c_str();
219     }
220 
221     GetArkUINodeModifiers()->getBadgeModifier()->setBadgeParamWithString(nativeNode, &style, value);
222     return panda::JSValueRef::Undefined(vm);
223 }
224 } // namespace OHOS::Ace::NG
225