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