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 #include <ani.h>
16 #include <tuple>
17
18 #include "ani_common.h"
19 #include "ani_font_collection.h"
20 #include "ani_paragraph.h"
21 #include "ani_paragraph_builder.h"
22 #include "ani_text_utils.h"
23 #include "utils/text_log.h"
24
25 namespace OHOS::Text::ANI {
26 #define STRUCT_LIST(...) using AniTypes = std::tuple<__VA_ARGS__>
27
28 // add new struct in this macro
29 STRUCT_LIST(AniFontCollection, AniParagraph, AniParagraphBuilder);
30
31 template <typename T>
InitOneStruct(ani_vm * vm,uint32_t * result)32 static ani_status InitOneStruct(ani_vm* vm, uint32_t* result)
33 {
34 return T::AniInit(vm, result);
35 }
36
37 template <typename Tuple, size_t... Is>
InitAllStruct(ani_vm * vm,uint32_t * result,std::index_sequence<Is...>)38 static ani_status InitAllStruct(ani_vm* vm, uint32_t* result, std::index_sequence<Is...>)
39 {
40 ani_status ret;
41 [[maybe_unused]] bool status =
42 (((ret = InitOneStruct<std::tuple_element_t<Is, Tuple>>(vm, result)) == ANI_OK) && ...);
43 return ret;
44 }
45
46 template <typename T>
SafeDelete(ani_long & ptr)47 void SafeDelete(ani_long& ptr)
48 {
49 if (ptr != 0) {
50 T* pointer = reinterpret_cast<T*>(ptr);
51 delete pointer;
52 pointer = nullptr;
53 ptr = 0;
54 }
55 }
56
Clean(ani_env * env,ani_object object)57 static void Clean(ani_env* env, ani_object object)
58 {
59 ani_long ptr;
60 ani_status ret = env->Object_GetFieldByName_Long(object, "ptr", &ptr);
61 if (ret != ANI_OK) {
62 return;
63 }
64 ani_ref stringRef = nullptr;
65 ret = env->Object_GetFieldByName_Ref(object, "className", &stringRef);
66 if (ret != ANI_OK) {
67 return;
68 }
69
70 std::string className;
71 ret = AniTextUtils::AniToStdStringUtf8(env, reinterpret_cast<ani_string>(stringRef), className);
72 if (ret != ANI_OK) {
73 return;
74 }
75 using DeleteFunc = void (*)(ani_long&);
76 static const std::unordered_map<std::string, DeleteFunc> deleteMap = {
77 {"ParagraphBuilder", SafeDelete<AniParagraphBuilder>}, {"Paragraph", SafeDelete<AniParagraph>},
78 {"FontCollection", SafeDelete<AniFontCollection>}};
79
80 if (deleteMap.count(className)) {
81 deleteMap.at(className)(ptr);
82 }
83 }
84
AniCleanerInit(ani_vm * vm)85 static ani_status AniCleanerInit(ani_vm* vm)
86 {
87 ani_env* env;
88 ani_status ret = vm->GetEnv(ANI_VERSION_1, &env);
89 if (ret != ANI_OK) {
90 TEXT_LOGE("null env, ret %{public}d", ret);
91 return ANI_NOT_FOUND;
92 }
93
94 ani_class cls = nullptr;
95 ret = env->FindClass(ANI_CLASS_CLEANER, &cls);
96 if (ret != ANI_OK) {
97 TEXT_LOGE("Failed to find class, ret %{public}d", ret);
98 return ANI_NOT_FOUND;
99 }
100
101 std::array methods = {
102 ani_native_function{"clean", ":V", reinterpret_cast<void*>(Clean)},
103 };
104
105 ret = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
106 if (ret != ANI_OK) {
107 TEXT_LOGE("Failed to bind methods, ret %{public}d", ret);
108 return ANI_NOT_FOUND;
109 }
110 return ANI_OK;
111 }
112
Init(ani_vm * vm,uint32_t * result)113 static ani_status Init(ani_vm* vm, uint32_t* result)
114 {
115 AniCleanerInit(vm);
116 return InitAllStruct<AniTypes>(vm, result, std::make_index_sequence<std::tuple_size_v<AniTypes>>());
117 }
118 } // namespace OHOS::Text::ANI
119
120 extern "C"
121 {
ANI_Constructor(ani_vm * vm,uint32_t * result)122 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
123 {
124 ani_status status = OHOS::Text::ANI::Init(vm, result);
125 if (status == ANI_OK) {
126 *result = ANI_VERSION_1;
127 }
128 return status;
129 }
130 }