1 /*
2 * Copyright (c) 2025 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 <ani.h>
17 #include <array>
18 #include <iostream>
19
20 #include "base/memory/referenced.h"
21 #include "frameworks/bridge/common/utils/engine_helper.h"
22 #include "frameworks/core/common/container.h"
23 #include "frameworks/core/pipeline/pipeline_base.h"
24 #include "core/components_ng/base/inspector.h"
25
26 namespace {
ANIUtils_ANIStringToStdString(ani_env * env,ani_string ani_str)27 std::string ANIUtils_ANIStringToStdString(ani_env* env, ani_string ani_str)
28 {
29 ani_size strSize;
30 env->String_GetUTF8Size(ani_str, &strSize);
31
32 std::vector<char> buffer(strSize + 1); // +1 for null terminator
33 char* utf8Buffer = buffer.data();
34
35 ani_size bytes_written = 0;
36 env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytes_written);
37
38 utf8Buffer[bytes_written] = '\0';
39 std::string content = std::string(utf8Buffer);
40 return content;
41 }
42 } // namespace
43
getSize(ani_env * env,OHOS::Ace::NG::Rectangle rectangle)44 static ani_object getSize([[maybe_unused]] ani_env* env, OHOS::Ace::NG::Rectangle rectangle)
45 {
46 ani_object obj = {};
47 static const char* className = "L@ohos/arkui/componentUtils/componentUtils/SizeInner;";
48 ani_class cls;
49 if (ANI_OK != env->FindClass(className, &cls)) {
50 return nullptr;
51 }
52 ani_method ctor;
53 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
54 return nullptr;
55 }
56 if (ANI_OK != env->Object_New(cls, ctor, &obj)) {
57 return nullptr;
58 }
59 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "width", rectangle.size.Width())) {
60 return nullptr;
61 }
62 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "height", rectangle.size.Height())) {
63 return nullptr;
64 }
65 return obj;
66 }
67
getLocalOffset(ani_env * env,OHOS::Ace::NG::Rectangle rectangle)68 static ani_object getLocalOffset([[maybe_unused]] ani_env* env, OHOS::Ace::NG::Rectangle rectangle)
69 {
70 ani_object obj = {};
71 static const char* className = "L@ohos/arkui/componentUtils/componentUtils/OffsetInner;";
72 ani_class cls;
73 if (ANI_OK != env->FindClass(className, &cls)) {
74 return nullptr;
75 }
76 ani_method ctor;
77 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
78 return nullptr;
79 }
80 if (ANI_OK != env->Object_New(cls, ctor, &obj)) {
81 return nullptr;
82 }
83 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "x", rectangle.localOffset.GetX())) {
84 return nullptr;
85 }
86 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "y", rectangle.localOffset.GetY())) {
87 return nullptr;
88 }
89 return obj;
90 }
91
getWindowOffset(ani_env * env,OHOS::Ace::NG::Rectangle rectangle)92 static ani_object getWindowOffset([[maybe_unused]] ani_env* env, OHOS::Ace::NG::Rectangle rectangle)
93 {
94 ani_object obj = {};
95 static const char* className = "L@ohos/arkui/componentUtils/componentUtils/OffsetInner;";
96 ani_class cls;
97 if (ANI_OK != env->FindClass(className, &cls)) {
98 return nullptr;
99 }
100 ani_method ctor;
101 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
102 return nullptr;
103 }
104 if (ANI_OK != env->Object_New(cls, ctor, &obj)) {
105 return nullptr;
106 }
107 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "x", rectangle.windowOffset.GetX())) {
108 return nullptr;
109 }
110 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "y", rectangle.windowOffset.GetY())) {
111 return nullptr;
112 }
113 return obj;
114 }
115
getScreenOffset(ani_env * env,OHOS::Ace::NG::Rectangle rectangle)116 static ani_object getScreenOffset([[maybe_unused]] ani_env* env, OHOS::Ace::NG::Rectangle rectangle)
117 {
118 ani_object obj = {};
119 static const char* className = "L@ohos/arkui/componentUtils/componentUtils/OffsetInner;";
120 ani_class cls;
121 if (ANI_OK != env->FindClass(className, &cls)) {
122 return nullptr;
123 }
124 ani_method ctor;
125 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
126 return nullptr;
127 }
128 if (ANI_OK != env->Object_New(cls, ctor, &obj)) {
129 return nullptr;
130 }
131 auto x = rectangle.windowOffset.GetX() + rectangle.screenRect.GetOffset().GetX();
132 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "x", x)) {
133 return nullptr;
134 }
135 auto y = rectangle.windowOffset.GetY() + rectangle.screenRect.GetOffset().GetY();
136 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "y", y)) {
137 return nullptr;
138 }
139 return obj;
140 }
141
getTranslateResult(ani_env * env,OHOS::Ace::NG::Rectangle rectangle)142 static ani_object getTranslateResult([[maybe_unused]] ani_env* env, OHOS::Ace::NG::Rectangle rectangle)
143 {
144 ani_object obj = {};
145 static const char* className = "L@ohos/arkui/componentUtils/componentUtils/TranslateResultInner;";
146 ani_class cls;
147 if (ANI_OK != env->FindClass(className, &cls)) {
148 return nullptr;
149 }
150 ani_method ctor;
151 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
152 return nullptr;
153 }
154 if (ANI_OK != env->Object_New(cls, ctor, &obj)) {
155 return nullptr;
156 }
157 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "x", rectangle.translate.x)) {
158 return nullptr;
159 }
160 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "y", rectangle.translate.y)) {
161 return nullptr;
162 }
163 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "z", rectangle.translate.z)) {
164 return nullptr;
165 }
166 return obj;
167 }
168
getScaleResult(ani_env * env,OHOS::Ace::NG::Rectangle rectangle)169 static ani_object getScaleResult([[maybe_unused]] ani_env* env, OHOS::Ace::NG::Rectangle rectangle)
170 {
171 ani_object obj = {};
172 static const char* className = "L@ohos/arkui/componentUtils/componentUtils/ScaleResultInner;";
173 ani_class cls;
174 if (ANI_OK != env->FindClass(className, &cls)) {
175 return nullptr;
176 }
177 ani_method ctor;
178 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
179 return nullptr;
180 }
181 if (ANI_OK != env->Object_New(cls, ctor, &obj)) {
182 return nullptr;
183 }
184 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "x", rectangle.scale.x)) {
185 return nullptr;
186 }
187 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "y", rectangle.scale.y)) {
188 return nullptr;
189 }
190 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "z", rectangle.scale.z)) {
191 return nullptr;
192 }
193 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "centerX", rectangle.scale.centerX)) {
194 return nullptr;
195 }
196 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "centerY", rectangle.scale.centerY)) {
197 return nullptr;
198 }
199 return obj;
200 }
201
getRotateResult(ani_env * env,OHOS::Ace::NG::Rectangle rectangle)202 static ani_object getRotateResult([[maybe_unused]] ani_env* env, OHOS::Ace::NG::Rectangle rectangle)
203 {
204 ani_object obj = {};
205 static const char* className = "L@ohos/arkui/componentUtils/componentUtils/RotateResultInner;";
206 ani_class cls;
207 if (ANI_OK != env->FindClass(className, &cls)) {
208 return nullptr;
209 }
210 ani_method ctor;
211 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
212 return nullptr;
213 }
214 if (ANI_OK != env->Object_New(cls, ctor, &obj)) {
215 return nullptr;
216 }
217 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "x", rectangle.rotate.x)) {
218 return nullptr;
219 }
220 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "y", rectangle.rotate.y)) {
221 return nullptr;
222 }
223 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "z", rectangle.rotate.z)) {
224 return nullptr;
225 }
226 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "angle", rectangle.rotate.angle)) {
227 return nullptr;
228 }
229 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "centerX", rectangle.rotate.centerX)) {
230 return nullptr;
231 }
232 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "centerY", rectangle.rotate.centerY)) {
233 return nullptr;
234 }
235 return obj;
236 }
237
getRransform(ani_env * env,OHOS::Ace::NG::Rectangle rectangle)238 static ani_object getRransform([[maybe_unused]] ani_env* env, OHOS::Ace::NG::Rectangle rectangle)
239 {
240 const int32_t size = 16;
241 ani_array_double array = nullptr;
242 env->Array_New_Double(size, &array);
243 ani_double matrix4[size] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };
244 for (int32_t i = 0; i < size; i++) {
245 matrix4[i] = ani_double(rectangle.matrix4[i]);
246 }
247 env->Array_SetRegion_Double(array, 0, size, matrix4);
248 return array;
249 }
250
getRectangleById(ani_env * env,ani_string id)251 static ani_object getRectangleById([[maybe_unused]] ani_env* env, ani_string id)
252 {
253 OHOS::Ace::NG::Rectangle rectangle;
254 auto key = ANIUtils_ANIStringToStdString(env, id);
255 OHOS::Ace::NG::Inspector::GetRectangleById(key, rectangle);
256 ani_object rectangleObj = {};
257 static const char* className = "L@ohos/arkui/componentUtils/componentUtils/ComponentInfoInner;";
258 ani_class cls;
259 if (ANI_OK != env->FindClass(className, &cls)) {
260 return nullptr;
261 }
262 ani_method ctor;
263 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
264 return nullptr;
265 }
266 if (ANI_OK != env->Object_New(cls, ctor, &rectangleObj)) {
267 return nullptr;
268 }
269 ani_object size_obj = getSize(env, rectangle);
270 if (size_obj == nullptr) {
271 return nullptr;
272 }
273 if (ANI_OK != env->Object_SetPropertyByName_Ref(rectangleObj, "size", size_obj)) {
274 return nullptr;
275 }
276 ani_object localOffset_obj = getLocalOffset(env, rectangle);
277 if (localOffset_obj == nullptr) {
278 return nullptr;
279 }
280 if (ANI_OK != env->Object_SetPropertyByName_Ref(rectangleObj, "localOffset", localOffset_obj)) {
281 return nullptr;
282 }
283 ani_object windowOffset_obj = getWindowOffset(env, rectangle);
284 if (windowOffset_obj == nullptr) {
285 return nullptr;
286 }
287 if (ANI_OK != env->Object_SetPropertyByName_Ref(rectangleObj, "windowOffset", windowOffset_obj)) {
288 return nullptr;
289 }
290 ani_object screenOffset_obj = getScreenOffset(env, rectangle);
291 if (screenOffset_obj == nullptr) {
292 return nullptr;
293 }
294 if (ANI_OK != env->Object_SetPropertyByName_Ref(rectangleObj, "screenOffset", screenOffset_obj)) {
295 return nullptr;
296 }
297 ani_object translate_obj = getTranslateResult(env, rectangle);
298 if (translate_obj == nullptr) {
299 return nullptr;
300 }
301 if (ANI_OK != env->Object_SetPropertyByName_Ref(rectangleObj, "translate", translate_obj)) {
302 return nullptr;
303 }
304 ani_object scale_obj = getScaleResult(env, rectangle);
305 if (scale_obj == nullptr) {
306 return nullptr;
307 }
308 if (ANI_OK != env->Object_SetPropertyByName_Ref(rectangleObj, "scale", scale_obj)) {
309 return nullptr;
310 }
311 ani_object rotate_obj = getRotateResult(env, rectangle);
312 if (rotate_obj == nullptr) {
313 return nullptr;
314 }
315 if (ANI_OK != env->Object_SetPropertyByName_Ref(rectangleObj, "rotate", rotate_obj)) {
316 return nullptr;
317 }
318 ani_object transform_obj = getRransform(env, rectangle);
319 if (transform_obj == nullptr) {
320 return nullptr;
321 }
322 if (ANI_OK != env->Object_SetPropertyByName_Ref(rectangleObj, "transform", transform_obj)) {
323 return nullptr;
324 }
325 return rectangleObj;
326 }
327
ANI_Constructor(ani_vm * vm,uint32_t * result)328 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
329 {
330 ani_env* env;
331 if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
332 return ANI_ERROR;
333 }
334
335 ani_namespace ns;
336 if (ANI_OK != env->FindNamespace("L@ohos/arkui/componentUtils/componentUtils;", &ns)) {
337 std::cout << "Failed componentUtils to create namespace" << std::endl;
338 return ANI_ERROR;
339 }
340 std::array methods = {
341 ani_native_function { "getRectangleById", nullptr, reinterpret_cast<void*>(getRectangleById) },
342 };
343 if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) {
344 return ANI_ERROR;
345 }
346
347 *result = ANI_VERSION_1;
348 return ANI_OK;
349 }
350