• 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 #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 }