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_relative_container_bridge.h"
16 
17 #include "base/geometry/calc_dimension.h"
18 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
19 #include "core/components_ng/pattern/relative_container/relative_container_model_ng.h"
20 #include "core/interfaces/arkoala/arkoala_api.h"
21 
22 namespace OHOS::Ace::NG {
23 namespace {
24 constexpr int NUM_0 = 0;
25 constexpr int NUM_1 = 1;
26 constexpr int NUM_2 = 2;
27 constexpr int NUM_3 = 3;
28 constexpr int POSITION_DIMENSION = 2;
29 constexpr char END_CHAR = '\0';
30 
ParseStringToCharPtr(std::string str)31 ArkUI_CharPtr ParseStringToCharPtr(std::string str)
32 {
33     char* id = static_cast<char*>(malloc((str.length() + 1) * sizeof(char)));
34     CHECK_NULL_RETURN(id, nullptr);
35     str.copy(id, str.length());
36     id[str.length()] = END_CHAR;
37     return id;
38 }
39 
FreeGuideLineCharPtr(ArkUIGuidelineStyle * values,ArkUI_Int32 size)40 void FreeGuideLineCharPtr(ArkUIGuidelineStyle* values, ArkUI_Int32 size)
41 {
42     for (int32_t i = 0; i < size; ++i) {
43         free(const_cast<char*>(values[i].id));
44         values[i].id = nullptr;
45     }
46 }
47 
FreeBarrierCharPtr(ArkUIBarrierStyle * values,ArkUI_Int32 size)48 void FreeBarrierCharPtr(ArkUIBarrierStyle* values, ArkUI_Int32 size)
49 {
50     for (int32_t i = 0; i < size; ++i) {
51         free(const_cast<char*>(values[i].id));
52         values[i].id = nullptr;
53         auto referencedIdChar = values[i].referencedId;
54         auto referencedIdSize = values[i].referencedIdSize;
55         for (int32_t j = 0; j < referencedIdSize; ++j) {
56             free(const_cast<char*>(referencedIdChar[j]));
57             referencedIdChar[j] = nullptr;
58         }
59     }
60 }
61 
ParseReferencedId(EcmaVM * vm,int32_t referenceSize,const panda::Local<panda::ArrayRef> & array,std::vector<ArkUI_CharPtr> & referencedIds)62 void ParseReferencedId(EcmaVM* vm, int32_t referenceSize,
63     const panda::Local<panda::ArrayRef>& array, std::vector<ArkUI_CharPtr>& referencedIds)
64 {
65     for (int32_t i = 0; i < referenceSize; i++) {
66         Local<JSValueRef> referencedId = panda::ArrayRef::GetValueAt(vm, array, i);
67         if (referencedId->IsString(vm)) {
68             std::string str = referencedId->ToString(vm)->ToString(vm);
69             referencedIds.push_back(ParseStringToCharPtr(str));
70         }
71     }
72 }
73 } // namespace
74 
SetGuideLine(ArkUIRuntimeCallInfo * runtimeCallInfo)75 ArkUINativeModuleValue RelativeContainerBridge::SetGuideLine(ArkUIRuntimeCallInfo* runtimeCallInfo)
76 {
77     EcmaVM* vm = runtimeCallInfo->GetVM();
78     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
79     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
80     Local<JSValueRef> idsArg = runtimeCallInfo->GetCallArgRef(NUM_1);
81     Local<JSValueRef> directionsArg = runtimeCallInfo->GetCallArgRef(NUM_2);
82     Local<JSValueRef> positionsArg = runtimeCallInfo->GetCallArgRef(NUM_3);
83     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
84     if (!idsArg->IsArray(vm) || !directionsArg->IsArray(vm) || !positionsArg->IsArray(vm)) {
85         GetArkUINodeModifiers()->getRelativeContainerModifier()->resetGuideline(nativeNode);
86         return panda::JSValueRef::Undefined(vm);
87     }
88     std::vector<ArkUIGuidelineStyle> guidelineInfos;
89     auto idsArr = panda::Local<panda::ArrayRef>(idsArg);
90     auto directionsArr = panda::Local<panda::ArrayRef>(directionsArg);
91     auto positionsArr = panda::Local<panda::ArrayRef>(positionsArg);
92     int32_t size = static_cast<int32_t>(idsArr->Length(vm));
93     for (int32_t i = 0; i < size; i++) {
94         ArkUIGuidelineStyle info;
95         Local<JSValueRef> idVal = panda::ArrayRef::GetValueAt(vm, idsArr, i);
96         if (idVal->IsString(vm)) {
97             std::string str = idVal->ToString(vm)->ToString(vm);
98             info.id = ParseStringToCharPtr(str);
99         }
100         Local<JSValueRef> directionVal = panda::ArrayRef::GetValueAt(vm, directionsArr, i);
101         if (directionVal->IsNumber()) {
102             info.direction = directionVal->Int32Value(vm);
103         }
104         Local<JSValueRef> posStartVal = panda::ArrayRef::GetValueAt(vm,
105             positionsArr, i * POSITION_DIMENSION);
106         CalcDimension startPos;
107         if (ArkTSUtils::ParseJsDimensionVpNG(vm, posStartVal, startPos)) {
108             info.start = startPos.Value();
109             info.hasStart = true;
110         }
111         Local<JSValueRef> posEndVal = panda::ArrayRef::GetValueAt(vm,
112             positionsArr, i * POSITION_DIMENSION + 1);
113         CalcDimension endPos;
114         if (ArkTSUtils::ParseJsDimensionVpNG(vm, posEndVal, endPos)) {
115             info.end = endPos.Value();
116             info.hasEnd = true;
117         }
118         guidelineInfos.push_back(info);
119     }
120     ArkUIGuidelineStyle* values = guidelineInfos.data();
121     GetArkUINodeModifiers()->getRelativeContainerModifier()->setGuideLine(nativeNode, values, size);
122     FreeGuideLineCharPtr(values, size);
123     return panda::JSValueRef::Undefined(vm);
124 }
125 
ResetGuideLine(ArkUIRuntimeCallInfo * runtimeCallInfo)126 ArkUINativeModuleValue RelativeContainerBridge::ResetGuideLine(ArkUIRuntimeCallInfo* runtimeCallInfo)
127 {
128     EcmaVM* vm = runtimeCallInfo->GetVM();
129     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
130     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
131     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
132     GetArkUINodeModifiers()->getRelativeContainerModifier()->resetGuideline(nativeNode);
133     return panda::JSValueRef::Undefined(vm);
134 }
135 
SetBarrier(ArkUIRuntimeCallInfo * runtimeCallInfo)136 ArkUINativeModuleValue RelativeContainerBridge::SetBarrier(ArkUIRuntimeCallInfo* runtimeCallInfo)
137 {
138     EcmaVM* vm = runtimeCallInfo->GetVM();
139     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
140     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
141     Local<JSValueRef> idsArg = runtimeCallInfo->GetCallArgRef(NUM_1);
142     Local<JSValueRef> directionsArg = runtimeCallInfo->GetCallArgRef(NUM_2);
143     Local<JSValueRef> referenceIdsArg = runtimeCallInfo->GetCallArgRef(NUM_3);
144     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
145     if (!idsArg->IsArray(vm) || !directionsArg->IsArray(vm) || !referenceIdsArg->IsArray(vm)) {
146         GetArkUINodeModifiers()->getRelativeContainerModifier()->resetBarrier(nativeNode);
147         return panda::JSValueRef::Undefined(vm);
148     }
149     std::vector<ArkUIBarrierStyle> barrierInfos;
150     auto idsArr = panda::Local<panda::ArrayRef>(idsArg);
151     auto directionsArr = panda::Local<panda::ArrayRef>(directionsArg);
152     auto referenceIdsArr = panda::Local<panda::ArrayRef>(referenceIdsArg);
153     int32_t size = static_cast<int32_t>(idsArr->Length(vm));
154     std::vector<ArkUI_CharPtr> referencedIds;
155     for (int32_t i = 0; i < size; i++) {
156         ArkUIBarrierStyle info;
157         Local<JSValueRef> idVal = panda::ArrayRef::GetValueAt(vm, idsArr, i);
158         Local<JSValueRef> directionVal = panda::ArrayRef::GetValueAt(vm, directionsArr, i);
159         Local<JSValueRef> referencedIdVal = panda::ArrayRef::GetValueAt(vm, referenceIdsArr, i);
160         if (idVal->IsString(vm)) {
161             std::string str = idVal->ToString(vm)->ToString(vm);
162             info.id = ParseStringToCharPtr(str);
163         }
164         if (directionVal->IsNumber()) {
165             info.direction = directionVal->Int32Value(vm);
166         }
167         if (referencedIdVal->IsArray(vm)) {
168             auto array = panda::Local<panda::ArrayRef>(referencedIdVal);
169             uint32_t referenceSize = array->Length(vm);
170             ParseReferencedId(vm, static_cast<int32_t>(referenceSize), array, referencedIds);
171             info.referencedId = referencedIds.data();
172             info.referencedIdSize = static_cast<int32_t>(referencedIds.size());
173             referencedIds.clear();
174         } else {
175             info.referencedIdSize = 0;
176         }
177         barrierInfos.push_back(info);
178     }
179     ArkUIBarrierStyle* values = barrierInfos.data();
180     GetArkUINodeModifiers()->getRelativeContainerModifier()->setBarrier(nativeNode, values, size);
181     FreeBarrierCharPtr(values, size);
182     return panda::JSValueRef::Undefined(vm);
183 }
184 
ResetBarrier(ArkUIRuntimeCallInfo * runtimeCallInfo)185 ArkUINativeModuleValue RelativeContainerBridge::ResetBarrier(ArkUIRuntimeCallInfo* runtimeCallInfo)
186 {
187     EcmaVM* vm = runtimeCallInfo->GetVM();
188     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
189     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
190     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
191     GetArkUINodeModifiers()->getRelativeContainerModifier()->resetBarrier(nativeNode);
192     return panda::JSValueRef::Undefined(vm);
193 }
194 } // namespace OHOS::Ace::NG
195