• 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 <codecvt>
17 #include <cstdint>
18 #include <sys/stat.h>
19 
20 #include "ani_common.h"
21 #include "ani_font_collection.h"
22 #include "ani_resource_parser.h"
23 #include "ani_text_utils.h"
24 #include "utils/text_log.h"
25 
26 namespace OHOS::Text::ANI {
27 using namespace OHOS::Rosen;
28 
29 namespace {
LoadString(ani_env * env,ani_object path,std::shared_ptr<OHOS::Rosen::FontCollection> fontCollection,std::string familyName)30 void LoadString(
31     ani_env* env, ani_object path, std::shared_ptr<OHOS::Rosen::FontCollection> fontCollection, std::string familyName)
32 {
33     std::unique_ptr<uint8_t[]> data;
34     size_t dataLen = 0;
35 
36     std::string pathStr;
37     ani_status ret = AniTextUtils::AniToStdStringUtf8(env, reinterpret_cast<ani_string>(path), pathStr);
38     if (ret != ANI_OK) {
39         return;
40     }
41     if (!AniTextUtils::SplitAbsoluteFontPath(pathStr) || !AniTextUtils::ReadFile(pathStr, dataLen, data)) {
42         TEXT_LOGE("Failed to split absolute font path");
43         return;
44     }
45     fontCollection->LoadFont(familyName, data.get(), dataLen);
46 }
47 
LoadResource(ani_env * env,ani_object path,std::shared_ptr<OHOS::Rosen::FontCollection> fontCollection,std::string familyName)48 void LoadResource(
49     ani_env* env, ani_object path, std::shared_ptr<OHOS::Rosen::FontCollection> fontCollection, std::string familyName)
50 {
51     std::unique_ptr<uint8_t[]> data;
52     size_t dataLen = 0;
53 
54     AniResource resource = AniResourceParser::ParseResource(env, path);
55     if (!AniResourceParser::ResolveResource(resource, dataLen, data)) {
56         TEXT_LOGE("Failed to resolve resource");
57         return;
58     }
59     fontCollection->LoadFont(familyName, data.get(), dataLen);
60 }
61 } // namespace
62 
AniFontCollection()63 AniFontCollection::AniFontCollection()
64 {
65     fontCollection_ = FontCollection::From(nullptr);
66 }
67 
AniFontCollection(std::shared_ptr<FontCollection> fc)68 AniFontCollection::AniFontCollection(std::shared_ptr<FontCollection> fc)
69 {
70     fontCollection_ = fc;
71 }
72 
Constructor(ani_env * env,ani_object object)73 void AniFontCollection::Constructor(ani_env* env, ani_object object)
74 {
75     AniFontCollection* aniFontCollection = new AniFontCollection();
76     ani_status ret = env->Object_SetFieldByName_Long(object, NATIVE_OBJ, reinterpret_cast<ani_long>(aniFontCollection));
77     if (ret != ANI_OK) {
78         TEXT_LOGE("Failed to create ani font collection obj");
79         delete aniFontCollection;
80         aniFontCollection = nullptr;
81         return;
82     }
83 }
84 
GetGlobalInstance(ani_env * env,ani_class cls)85 ani_object AniFontCollection::GetGlobalInstance(ani_env* env, ani_class cls)
86 {
87     static AniFontCollection aniFontCollection = AniFontCollection(FontCollection::Create());
88 
89     ani_object obj = AniTextUtils::CreateAniObject(env, ANI_CLASS_FONT_COLLECTION, ":V");
90     ani_status ret = env->Object_SetFieldByName_Long(obj, NATIVE_OBJ, reinterpret_cast<ani_long>(&aniFontCollection));
91     if (ret != ANI_OK) {
92         TEXT_LOGE("Failed to create ani font collection obj");
93         return nullptr;
94     }
95     return obj;
96 }
97 
LoadFontSync(ani_env * env,ani_object obj,ani_string name,ani_object path)98 void AniFontCollection::LoadFontSync(ani_env* env, ani_object obj, ani_string name, ani_object path)
99 {
100     std::string familyName;
101     ani_status ret = AniTextUtils::AniToStdStringUtf8(env, name, familyName);
102     if (ret != ANI_OK) {
103         return;
104     }
105     auto aniFontCollection = AniTextUtils::GetNativeFromObj<AniFontCollection>(env, obj);
106     if (aniFontCollection == nullptr || aniFontCollection->fontCollection_ == nullptr) {
107         TEXT_LOGE("Null font collection");
108         return;
109     }
110 
111     ani_class stringClass;
112     env->FindClass("Lstd/core/String;", &stringClass);
113     ani_boolean isString = false;
114     env->Object_InstanceOf(path, stringClass, &isString);
115 
116     if (isString) {
117         LoadString(env, path, aniFontCollection->fontCollection_, familyName);
118         return;
119     }
120 
121     ani_class resourceClass;
122     env->FindClass("Lglobal/resource/Resource", &resourceClass);
123     ani_boolean isResource = false;
124     env->Object_InstanceOf(path, resourceClass, &isResource);
125     if (isResource) {
126         LoadResource(env, path, aniFontCollection->fontCollection_, familyName);
127         return;
128     }
129 }
130 
ClearCaches(ani_env * env,ani_object obj)131 void AniFontCollection::ClearCaches(ani_env* env, ani_object obj)
132 {
133     auto aniFontCollection = AniTextUtils::GetNativeFromObj<AniFontCollection>(env, obj);
134     if (aniFontCollection == nullptr || aniFontCollection->fontCollection_ == nullptr) {
135         TEXT_LOGE("Null font collection");
136         return;
137     }
138     aniFontCollection->fontCollection_->ClearCaches();
139 }
140 
AniInit(ani_vm * vm,uint32_t * result)141 ani_status AniFontCollection::AniInit(ani_vm* vm, uint32_t* result)
142 {
143     ani_env* env;
144     ani_status ret = vm->GetEnv(ANI_VERSION_1, &env);
145     if (ret != ANI_OK) {
146         TEXT_LOGE("null env");
147         return ANI_NOT_FOUND;
148     }
149 
150     ani_class cls = nullptr;
151     ret = env->FindClass(ANI_CLASS_FONT_COLLECTION, &cls);
152     if (ret != ANI_OK) {
153         TEXT_LOGE("Failed to find class: %{public}s", ANI_CLASS_FONT_COLLECTION);
154         return ANI_NOT_FOUND;
155     }
156 
157     std::string globalInstance = ":" + std::string(ANI_CLASS_FONT_COLLECTION);
158     std::string loadFontSync = "Lstd/core/String;Lstd/core/Object;:V";
159 
160     std::array methods = {
161         ani_native_function{"constructorNative", ":V", reinterpret_cast<void*>(Constructor)},
162         ani_native_function{"getGlobalInstance", globalInstance.c_str(), reinterpret_cast<void*>(GetGlobalInstance)},
163         ani_native_function{"loadFontSync", loadFontSync.c_str(), reinterpret_cast<void*>(LoadFontSync)},
164         ani_native_function{"clearCaches", ":V", reinterpret_cast<void*>(ClearCaches)},
165     };
166 
167     ret = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
168     if (ret != ANI_OK) {
169         TEXT_LOGE("Failed to bind methods: %{public}s", ANI_CLASS_FONT_COLLECTION);
170         return ANI_NOT_FOUND;
171     }
172     return ANI_OK;
173 }
174 
GetFontCollection()175 std::shared_ptr<FontCollection> AniFontCollection::GetFontCollection()
176 {
177     return fontCollection_;
178 }
179 } // namespace OHOS::Text::ANI