• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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