1 /*
2 * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development 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 <string>
17
18 #include "interfaces/napi/kits/utils/napi_utils.h"
19 #include "napi/native_api.h"
20 #include "napi/native_engine/native_value.h"
21 #include "napi/native_node_api.h"
22
23 #include "bridge/common/utils/engine_helper.h"
24 #include "bridge/js_frontend/engine/common/js_engine.h"
25 #include "core/common/font_manager.h"
26
27 namespace OHOS::Ace::Napi {
28 namespace {
29 constexpr size_t STR_BUFFER_SIZE = 1024;
30 constexpr int32_t FONT_INFO_INDEX_PATH = 0;
31 constexpr int32_t FONT_INFO_INDEX_POST_SCRIPT_NAME = 1;
32 constexpr int32_t FONT_INFO_INDEX_FULL_NAME = 2;
33 constexpr int32_t FONT_INFO_INDEX_FAMILY = 3;
34 constexpr int32_t FONT_INFO_INDEX_SUB_FAMILY = 4;
35 constexpr int32_t FONT_INFO_INDEX_WEIGHT = 5;
36 constexpr int32_t FONT_INFO_INDEX_WIDTH = 6;
37 constexpr int32_t FONT_INFO_INDEX_ITALIC = 7;
38 constexpr int32_t FONT_INFO_INDEX_MONOSPACE = 8;
39 constexpr int32_t FONT_INFO_INDEX_SYMBOLIC = 9;
40 constexpr int32_t FONT_INFO_INDEX_MAX = 10;
41 }
42
ParseFamilyNameOrSrc(napi_env env,napi_value familyNameOrSrcNApi,std::string & familyNameOrSrc,napi_valuetype valueType,ResourceInfo & info)43 static bool ParseFamilyNameOrSrc(napi_env env, napi_value familyNameOrSrcNApi, std::string& familyNameOrSrc,
44 napi_valuetype valueType, ResourceInfo& info)
45 {
46 napi_typeof(env, familyNameOrSrcNApi, &valueType);
47 if (valueType == napi_string) {
48 size_t nameLen = 0;
49 napi_get_value_string_utf8(env, familyNameOrSrcNApi, nullptr, 0, &nameLen);
50 std::unique_ptr<char[]> name = std::make_unique<char[]>(nameLen + 1);
51 napi_get_value_string_utf8(env, familyNameOrSrcNApi, name.get(), nameLen + 1, &nameLen);
52 familyNameOrSrc = name.get();
53 } else if (valueType == napi_object) {
54 if (!ParseResourceParam(env, familyNameOrSrcNApi, info)) {
55 return false;
56 }
57 if (!ParseString(info, familyNameOrSrc)) {
58 return false;
59 }
60 } else {
61 return false;
62 }
63 return true;
64 }
65
JSRegisterFont(napi_env env,napi_callback_info info)66 static napi_value JSRegisterFont(napi_env env, napi_callback_info info)
67 {
68 size_t argc = 1;
69 napi_value argv = nullptr;
70 napi_value thisVar = nullptr;
71 void* data = nullptr;
72 napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data);
73
74 napi_value familyNameNApi = nullptr;
75 napi_value familySrcNApi = nullptr;
76 std::string familyName;
77 std::string familySrc;
78
79 napi_valuetype valueType = napi_undefined;
80 napi_typeof(env, argv, &valueType);
81 if (valueType == napi_object) {
82 napi_get_named_property(env, argv, "familyName", &familyNameNApi);
83 napi_get_named_property(env, argv, "familySrc", &familySrcNApi);
84 } else {
85 return nullptr;
86 }
87
88 ResourceInfo resourceInfo;
89 if (!ParseFamilyNameOrSrc(env, familyNameNApi, familyName, valueType, resourceInfo)) {
90 return nullptr;
91 }
92 if (!ParseFamilyNameOrSrc(env, familySrcNApi, familySrc, valueType, resourceInfo)) {
93 return nullptr;
94 }
95
96 std::string bundleName = resourceInfo.bundleName.has_value() ? resourceInfo.bundleName.value() : "";
97 std::string moduleName = resourceInfo.moduleName.has_value() ? resourceInfo.moduleName.value() : "";
98 auto delegate = EngineHelper::GetCurrentDelegateSafely();
99 if (!delegate) {
100 TAG_LOGW(AceLogTag::ACE_FONT, "can not get delegate.");
101 return nullptr;
102 }
103 TAG_LOGI(AceLogTag::ACE_FONT, "begin to register font.");
104 delegate->RegisterFont(familyName, familySrc, bundleName, moduleName);
105 return nullptr;
106 }
107
JSgetSystemFontList(napi_env env,napi_callback_info info)108 static napi_value JSgetSystemFontList(napi_env env, napi_callback_info info)
109 {
110 napi_value arrayResult = nullptr;
111 napi_create_array(env, &arrayResult);
112 bool isArray = false;
113 if (napi_is_array(env, arrayResult, &isArray) != napi_ok || !isArray) {
114 return arrayResult;
115 }
116 std::vector<std::string> fontList;
117 auto delegate = EngineHelper::GetCurrentDelegateSafely();
118 if (!delegate) {
119 return nullptr;
120 }
121 delegate->GetSystemFontList(fontList);
122
123 int32_t index = 0;
124 for (const std::string& font : fontList) {
125 napi_value result = nullptr;
126 napi_create_string_utf8(env, font.c_str(), font.length(), &result);
127 napi_set_element(env, arrayResult, index++, result);
128 }
129 return arrayResult;
130 }
131
JSgetFontByName(napi_env env,napi_callback_info info)132 static napi_value JSgetFontByName(napi_env env, napi_callback_info info)
133 {
134 size_t argc = 1;
135 napi_value argv = nullptr;
136 napi_value thisVar = nullptr;
137 void* data = nullptr;
138 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data));
139 NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
140
141 napi_valuetype type;
142 NAPI_CALL(env, napi_typeof(env, argv, &type));
143 NAPI_ASSERT(env, type == napi_string, "type mismatch");
144 char fontName[STR_BUFFER_SIZE] = { 0 };
145 size_t len = 0;
146 napi_get_value_string_utf8(env, argv, fontName, STR_BUFFER_SIZE, &len);
147 NAPI_ASSERT(env, len < STR_BUFFER_SIZE, "condition string too long");
148 std::string fontNameStr(fontName, len);
149
150 FontInfo fontInfo;
151 auto delegate = EngineHelper::GetCurrentDelegateSafely();
152 if (!delegate) {
153 return nullptr;
154 }
155 if (!delegate->GetSystemFont(fontNameStr, fontInfo)) {
156 return nullptr;
157 }
158
159 napi_value resultArray[FONT_INFO_INDEX_MAX] = { 0 };
160 napi_create_string_utf8(env, fontInfo.path.c_str(), NAPI_AUTO_LENGTH, &resultArray[FONT_INFO_INDEX_PATH]);
161 napi_create_string_utf8(env, fontInfo.postScriptName.c_str(), NAPI_AUTO_LENGTH,
162 &resultArray[FONT_INFO_INDEX_POST_SCRIPT_NAME]);
163 napi_create_string_utf8(env, fontInfo.fullName.c_str(), NAPI_AUTO_LENGTH, &resultArray[FONT_INFO_INDEX_FULL_NAME]);
164 napi_create_string_utf8(env, fontInfo.family.c_str(), NAPI_AUTO_LENGTH, &resultArray[FONT_INFO_INDEX_FAMILY]);
165 napi_create_string_utf8(env, fontInfo.subfamily.c_str(), NAPI_AUTO_LENGTH,
166 &resultArray[FONT_INFO_INDEX_SUB_FAMILY]);
167 napi_create_int32(env, fontInfo.weight, &resultArray[FONT_INFO_INDEX_WEIGHT]);
168 napi_create_int32(env, fontInfo.width, &resultArray[FONT_INFO_INDEX_WIDTH]);
169 napi_get_boolean(env, fontInfo.italic, &resultArray[FONT_INFO_INDEX_ITALIC]);
170 napi_get_boolean(env, fontInfo.monoSpace, &resultArray[FONT_INFO_INDEX_MONOSPACE]);
171 napi_get_boolean(env, fontInfo.symbolic, &resultArray[FONT_INFO_INDEX_SYMBOLIC]);
172
173 napi_value result = nullptr;
174 napi_create_object(env, &result);
175 napi_set_named_property(env, result, "path", resultArray[FONT_INFO_INDEX_PATH]);
176 napi_set_named_property(env, result, "postScriptName", resultArray[FONT_INFO_INDEX_POST_SCRIPT_NAME]);
177 napi_set_named_property(env, result, "fullName", resultArray[FONT_INFO_INDEX_FULL_NAME]);
178 napi_set_named_property(env, result, "family", resultArray[FONT_INFO_INDEX_FAMILY]);
179 napi_set_named_property(env, result, "subfamily", resultArray[FONT_INFO_INDEX_SUB_FAMILY]);
180 napi_set_named_property(env, result, "weight", resultArray[FONT_INFO_INDEX_WEIGHT]);
181 napi_set_named_property(env, result, "width", resultArray[FONT_INFO_INDEX_WIDTH]);
182 napi_set_named_property(env, result, "italic", resultArray[FONT_INFO_INDEX_ITALIC]);
183 napi_set_named_property(env, result, "monoSpace", resultArray[FONT_INFO_INDEX_MONOSPACE]);
184 napi_set_named_property(env, result, "symbolic", resultArray[FONT_INFO_INDEX_SYMBOLIC]);
185
186 return result;
187 }
188
GetUIFontGenericInfo(napi_env env,const FontConfigJsonInfo & fontConfigJsonInfo)189 static napi_value GetUIFontGenericInfo(napi_env env, const FontConfigJsonInfo& fontConfigJsonInfo)
190 {
191 napi_value genericSetResult = nullptr;
192 napi_create_array(env, &genericSetResult);
193 int32_t index = 0;
194 for (const FontGenericInfo& generic: fontConfigJsonInfo.genericSet) {
195 napi_value genericResult = nullptr;
196 napi_create_object(env, &genericResult);
197 napi_value familyResult = nullptr;
198 napi_create_string_utf8(env, generic.familyName.c_str(), generic.familyName.length(), &familyResult);
199 napi_value aliasSetResult = nullptr;
200 napi_create_array(env, &aliasSetResult);
201 int32_t index2 = 0;
202 for (const AliasInfo& alias: generic.aliasSet) {
203 napi_value aliasResult = nullptr;
204 napi_create_object(env, &aliasResult);
205 napi_value familyNameResult = nullptr;
206 napi_create_string_utf8(env, alias.familyName.c_str(), alias.familyName.length(), &familyNameResult);
207 napi_value weightResult = nullptr;
208 napi_create_int32(env, alias.weight, &weightResult);
209 napi_set_named_property(env, aliasResult, "name", familyNameResult);
210 napi_set_named_property(env, aliasResult, "weight", weightResult);
211 napi_set_element(env, aliasSetResult, index2++, aliasResult);
212 }
213 index2 = 0;
214 napi_value adjustSetResult = nullptr;
215 napi_create_array(env, &adjustSetResult);
216 for (const AdjustInfo& adjust: generic.adjustSet) {
217 napi_value adjustResult = nullptr;
218 napi_create_object(env, &adjustResult);
219 napi_value weightResult = nullptr;
220 napi_create_int32(env, adjust.origValue, &weightResult);
221 napi_value toResult = nullptr;
222 napi_create_int32(env, adjust.newValue, &toResult);
223 napi_set_named_property(env, adjustResult, "weight", weightResult);
224 napi_set_named_property(env, adjustResult, "to", toResult);
225 napi_set_element(env, adjustSetResult, index2++, adjustResult);
226 }
227 napi_set_named_property(env, genericResult, "family", familyResult);
228 napi_set_named_property(env, genericResult, "alias", aliasSetResult);
229 napi_set_named_property(env, genericResult, "adjust", adjustSetResult);
230 napi_set_element(env, genericSetResult, index++, genericResult);
231 }
232 return genericSetResult;
233 }
234
GetUIFontFallbackInfo(napi_env env,const FontConfigJsonInfo & fontConfigJsonInfo)235 static napi_value GetUIFontFallbackInfo(napi_env env, const FontConfigJsonInfo& fontConfigJsonInfo)
236 {
237 napi_value fallbackGroupSetResult = nullptr;
238 napi_create_array(env, &fallbackGroupSetResult);
239 int32_t index = 0;
240 for (const FallbackGroup& fallbackGroup: fontConfigJsonInfo.fallbackGroupSet) {
241 napi_value fallbackGroupResult = nullptr;
242 napi_create_object(env, &fallbackGroupResult);
243 napi_value fontSetNameResult = nullptr;
244 napi_create_string_utf8(env, fallbackGroup.groupName.c_str(),
245 fallbackGroup.groupName.length(), &fontSetNameResult);
246 napi_value fallbackListResult = nullptr;
247 napi_create_array(env, &fallbackListResult);
248 int32_t index2 = 0;
249 for (const FallbackInfo& fallback: fallbackGroup.fallbackInfoSet) {
250 napi_value fallbackResult = nullptr;
251 napi_create_object(env, &fallbackResult);
252 napi_value familyResult = nullptr;
253 napi_create_string_utf8(env, fallback.familyName.c_str(), fallback.familyName.length(), &familyResult);
254 napi_value languageResult = nullptr;
255 napi_create_string_utf8(env, fallback.font.c_str(), fallback.font.length(), &languageResult);
256
257 napi_set_named_property(env, fallbackResult, "language", languageResult);
258 napi_set_named_property(env, fallbackResult, "family", familyResult);
259 napi_set_element(env, fallbackListResult, index2++, fallbackResult);
260 }
261 napi_set_named_property(env, fallbackGroupResult, "fontSetName", fontSetNameResult);
262 napi_set_named_property(env, fallbackGroupResult, "fallback", fallbackListResult);
263 napi_set_element(env, fallbackGroupSetResult, index++, fallbackGroupResult);
264 }
265 return fallbackGroupSetResult;
266 }
267
JsGetUIFontConfig(napi_env env,napi_callback_info info)268 static napi_value JsGetUIFontConfig(napi_env env, napi_callback_info info)
269 {
270 FontConfigJsonInfo fontConfigJsonInfo;
271 auto delegate = EngineHelper::GetCurrentDelegateSafely();
272 if (!delegate) {
273 return nullptr;
274 }
275 delegate->GetUIFontConfig(fontConfigJsonInfo);
276 napi_value result = nullptr;
277 napi_create_object(env, &result);
278 napi_value fontDirSetResult = nullptr;
279 napi_create_array(env, &fontDirSetResult);
280 int32_t index = 0;
281 for (const std::string& fontDir : fontConfigJsonInfo.fontDirSet) {
282 napi_value fontDirResult = nullptr;
283 napi_create_string_utf8(env, fontDir.c_str(), fontDir.length(), &fontDirResult);
284 napi_set_element(env, fontDirSetResult, index++, fontDirResult);
285 }
286 napi_value genericSetResult = GetUIFontGenericInfo(env, fontConfigJsonInfo);
287 napi_value fallbackGroupSetResult = GetUIFontFallbackInfo(env, fontConfigJsonInfo);
288
289 napi_set_named_property(env, result, "fontDir", fontDirSetResult);
290 napi_set_named_property(env, result, "generic", genericSetResult);
291 napi_set_named_property(env, result, "fallbackGroups", fallbackGroupSetResult);
292 return result;
293 }
294
FontExport(napi_env env,napi_value exports)295 static napi_value FontExport(napi_env env, napi_value exports)
296 {
297 napi_property_descriptor fontDesc[] = {
298 DECLARE_NAPI_FUNCTION("registerFont", JSRegisterFont),
299 DECLARE_NAPI_FUNCTION("getSystemFontList", JSgetSystemFontList),
300 DECLARE_NAPI_FUNCTION("getFontByName", JSgetFontByName),
301 DECLARE_NAPI_FUNCTION("getUIFontConfig", JsGetUIFontConfig)
302 };
303 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(fontDesc) / sizeof(fontDesc[0]), fontDesc));
304 return exports;
305 }
306
307 static napi_module fontModule = {
308 .nm_version = 1,
309 .nm_flags = 0,
310 .nm_filename = nullptr,
311 .nm_register_func = FontExport,
312 .nm_modname = "font",
313 .nm_priv = ((void*)0),
314 .reserved = { 0 },
315 };
316
FontRegister()317 extern "C" __attribute__((constructor)) void FontRegister()
318 {
319 napi_module_register(&fontModule);
320 }
321 } // namespace OHOS::Ace::Napi
322