1 /*
2  * Copyright (c) 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/engine/jsi/nativeModule/arkts_native_rect_bridge.h"
17 #include "ecmascript/napi/include/jsnapi.h"
18 #include "base/geometry/calc_dimension.h"
19 #include "base/geometry/dimension.h"
20 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
21 
22 using namespace OHOS::Ace::Framework;
23 
24 namespace OHOS::Ace::NG {
25 namespace {
26 constexpr int CALL_ARG_0 = 0;
27 constexpr int CALL_ARG_1 = 1;
28 constexpr uint32_t VALID_RADIUS_PAIR_FLAG = 1;
29 constexpr uint32_t INVALID_RADIUS_PAIR_FLAG = 0;
30 } // namespace
SetRadiusWidth(ArkUIRuntimeCallInfo * runtimeCallInfo)31 ArkUINativeModuleValue RectBridge::SetRadiusWidth(ArkUIRuntimeCallInfo* runtimeCallInfo)
32 {
33     EcmaVM* vm = runtimeCallInfo->GetVM();
34     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
35     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(CALL_ARG_0);
36     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
37     Local<JSValueRef> jsValue = runtimeCallInfo->GetCallArgRef(CALL_ARG_1);
38     CalcDimension radiusWidth;
39     bool isSupportPercent = true;
40     if (!ArkTSUtils::ParseJsDimensionVpNG(vm, jsValue, radiusWidth, isSupportPercent)) {
41         GetArkUINodeModifiers()->getRectModifier()->resetRectRadiusWidth(nativeNode);
42     }
43     GetArkUINodeModifiers()->getRectModifier()->setRectRadiusWidth(
44         nativeNode, radiusWidth.Value(), static_cast<int32_t>(radiusWidth.Unit()));
45     return panda::JSValueRef::Undefined(vm);
46 }
47 
ResetRadiusWidth(ArkUIRuntimeCallInfo * runtimeCallInfo)48 ArkUINativeModuleValue RectBridge::ResetRadiusWidth(ArkUIRuntimeCallInfo* runtimeCallInfo)
49 {
50     EcmaVM* vm = runtimeCallInfo->GetVM();
51     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
52     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(CALL_ARG_0);
53     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
54     GetArkUINodeModifiers()->getRectModifier()->resetRectRadiusWidth(nativeNode);
55     return panda::JSValueRef::Undefined(vm);
56 }
57 
SetRadiusHeight(ArkUIRuntimeCallInfo * runtimeCallInfo)58 ArkUINativeModuleValue RectBridge::SetRadiusHeight(ArkUIRuntimeCallInfo* runtimeCallInfo)
59 {
60     EcmaVM* vm = runtimeCallInfo->GetVM();
61     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
62     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(CALL_ARG_0);
63     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
64     Local<JSValueRef> jsValue = runtimeCallInfo->GetCallArgRef(CALL_ARG_1);
65     CalcDimension radiusHeight;
66     bool isSupportPercent = true;
67     if (!ArkTSUtils::ParseJsDimensionVpNG(vm, jsValue, radiusHeight, isSupportPercent)) {
68         GetArkUINodeModifiers()->getRectModifier()->resetRectRadiusHeight(nativeNode);
69     }
70     GetArkUINodeModifiers()->getRectModifier()->setRectRadiusHeight(
71         nativeNode, radiusHeight.Value(), static_cast<int32_t>(radiusHeight.Unit()));
72     return panda::JSValueRef::Undefined(vm);
73 }
74 
ResetRadiusHeight(ArkUIRuntimeCallInfo * runtimeCallInfo)75 ArkUINativeModuleValue RectBridge::ResetRadiusHeight(ArkUIRuntimeCallInfo* runtimeCallInfo)
76 {
77     EcmaVM* vm = runtimeCallInfo->GetVM();
78     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
79     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(CALL_ARG_0);
80     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
81     GetArkUINodeModifiers()->getRectModifier()->resetRectRadiusHeight(nativeNode);
82     return panda::JSValueRef::Undefined(vm);
83 }
84 
SetRadius(ArkUIRuntimeCallInfo * runtimeCallInfo)85 ArkUINativeModuleValue RectBridge::SetRadius(ArkUIRuntimeCallInfo* runtimeCallInfo)
86 {
87     EcmaVM* vm = runtimeCallInfo->GetVM();
88     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
89     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(CALL_ARG_0);
90     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
91     Local<JSValueRef> jsValue = runtimeCallInfo->GetCallArgRef(CALL_ARG_1);
92     std::vector<ArkUI_Float32> radiusValues;
93     std::vector<int32_t> radiusUnits;
94     std::vector<uint32_t> radiusValidPairs;
95     if (jsValue->IsArray(vm)) {
96         RectBridge::SetRadiusWithArray(vm, jsValue, radiusValues, radiusUnits, radiusValidPairs);
97         GetArkUINodeModifiers()->getRectModifier()->setRectRadiusWithArray(
98             nativeNode, radiusValues.data(), radiusUnits.data(), radiusValidPairs.data(), radiusValidPairs.size());
99         return panda::JSValueRef::Undefined(vm);
100     }
101     if (jsValue->IsNumber() || jsValue->IsString(vm) || jsValue->IsObject(vm)) {
102         CalcDimension parsedValue;
103         bool isSupportPercent = true;
104         if (!ArkTSUtils::ParseJsDimensionVpNG(vm, jsValue, parsedValue, isSupportPercent)) {
105             parsedValue.Reset();
106         }
107         GetArkUINodeModifiers()->getRectModifier()->setRectRadiusWithValue(
108             nativeNode, parsedValue.Value(), static_cast<int32_t>(parsedValue.Unit()));
109     }
110     return panda::JSValueRef::Undefined(vm);
111 }
112 
ResetRadius(ArkUIRuntimeCallInfo * runtimeCallInfo)113 ArkUINativeModuleValue RectBridge::ResetRadius(ArkUIRuntimeCallInfo* runtimeCallInfo)
114 {
115     EcmaVM* vm = runtimeCallInfo->GetVM();
116     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
117     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(CALL_ARG_0);
118     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
119     GetArkUINodeModifiers()->getRectModifier()->resetRectRadius(nativeNode);
120     return panda::JSValueRef::Undefined(vm);
121 }
122 
SetRadiusWithArray(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::vector<ArkUI_Float32> & radiusValues,std::vector<int32_t> & radiusUnits,std::vector<uint32_t> & radiusValidPairs)123 void RectBridge::SetRadiusWithArray(const EcmaVM* vm, const Local<JSValueRef>& jsValue,
124     std::vector<ArkUI_Float32>& radiusValues,
125     std::vector<int32_t>& radiusUnits,
126     std::vector<uint32_t>& radiusValidPairs)
127 {
128     if (!jsValue->IsArray(vm)) {
129         return;
130     }
131     auto arrayVal = panda::Local<panda::ArrayRef>(jsValue);
132     auto length = arrayVal->Length(vm);
133     if (length <= 0) {
134         return;
135     }
136     size_t radiusPairsCount = 4;
137     size_t dataCount = 2;
138     for (size_t i = 0; i < radiusPairsCount; i++) {
139         if (i >= length && length < radiusPairsCount) {
140             SetRadiusArraysInvalidValue(radiusValues, radiusUnits, radiusValidPairs, i);
141             break;
142         }
143         Local<JSValueRef> radiusItem = panda::ArrayRef::GetValueAt(vm, arrayVal, i);
144         if (!radiusItem->IsArray(vm)) {
145             SetRadiusArraysInvalidValue(radiusValues, radiusUnits, radiusValidPairs, i);
146             break;
147         }
148         auto radiusArray = panda::Local<panda::ArrayRef>(radiusItem);
149         if (radiusArray->Length(vm) != dataCount) {
150             SetRadiusArraysInvalidValue(radiusValues, radiusUnits, radiusValidPairs, i);
151             break;
152         }
153         uint32_t indexX = 0;
154         uint32_t indexY = 1;
155         Local<JSValueRef> radiusX = panda::ArrayRef::GetValueAt(vm, radiusArray, indexX);
156         Local<JSValueRef> radiusY = panda::ArrayRef::GetValueAt(vm, radiusArray, indexY);
157         CalcDimension radiusXValue;
158         CalcDimension radiusYValue;
159         bool isSupportPercent = true;
160         if (!ArkTSUtils::ParseJsDimensionVpNG(vm, radiusX, radiusXValue, isSupportPercent)) {
161             radiusXValue.Reset();
162         }
163         if (!ArkTSUtils::ParseJsDimensionVpNG(vm, radiusY, radiusYValue, isSupportPercent)) {
164             radiusYValue.Reset();
165         }
166         radiusValidPairs.push_back(VALID_RADIUS_PAIR_FLAG);
167         radiusValues.push_back(static_cast<ArkUI_Float32>(radiusXValue.Value()));
168         radiusValues.push_back(static_cast<ArkUI_Float32>(radiusYValue.Value()));
169         radiusUnits.push_back(static_cast<int32_t>(radiusXValue.Unit()));
170         radiusUnits.push_back(static_cast<int32_t>(radiusYValue.Unit()));
171     }
172 }
173 
SetRadiusArraysInvalidValue(std::vector<ArkUI_Float32> & radiusValues,std::vector<int32_t> & radiusUnits,std::vector<uint32_t> & radiusValidPairs,int index)174 void RectBridge::SetRadiusArraysInvalidValue(std::vector<ArkUI_Float32>& radiusValues,
175     std::vector<int32_t>& radiusUnits, std::vector<uint32_t>& radiusValidPairs, int index)
176 {
177     radiusValidPairs.push_back(INVALID_RADIUS_PAIR_FLAG);
178     CalcDimension radiusXValue;
179     CalcDimension radiusYValue;
180     radiusXValue.Reset();
181     radiusYValue.Reset();
182     radiusValues.push_back(static_cast<ArkUI_Float32>(radiusXValue.Value()));
183     radiusValues.push_back(static_cast<ArkUI_Float32>(radiusYValue.Value()));
184     radiusUnits.push_back(static_cast<int32_t>(radiusXValue.Unit()));
185     radiusUnits.push_back(static_cast<int32_t>(radiusYValue.Unit()));
186 }
187 } // namespace OHOS::Ace::NG
188