1 /*
2 * Copyright (c) 2024 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 "js_fontdescriptor.h"
17
18 #include "font_descriptor_mgr.h"
19 #include "napi_async_work.h"
20 #include "napi_common.h"
21
22 namespace OHOS::Rosen {
23 namespace {
24 std::unordered_map<int, int> g_weightMap = {
25 {100, static_cast<int>(FontWeight::W100)},
26 {200, static_cast<int>(FontWeight::W200)},
27 {300, static_cast<int>(FontWeight::W300)},
28 {400, static_cast<int>(FontWeight::W400)},
29 {500, static_cast<int>(FontWeight::W500)},
30 {600, static_cast<int>(FontWeight::W600)},
31 {700, static_cast<int>(FontWeight::W700)},
32 {800, static_cast<int>(FontWeight::W800)},
33 {900, static_cast<int>(FontWeight::W900)}
34 };
35 }
36
Init(napi_env env,napi_value exportObj)37 napi_value JsFontDescriptor::Init(napi_env env, napi_value exportObj)
38 {
39 napi_property_descriptor properties[] = {
40 DECLARE_NAPI_STATIC_FUNCTION("getSystemFontFullNamesByType", JsFontDescriptor::GetSystemFontFullNamesByType),
41 DECLARE_NAPI_STATIC_FUNCTION("getFontDescriptorByFullName", JsFontDescriptor::GetFontDescriptorByFullName),
42 };
43
44 NAPI_CHECK_AND_THROW_ERROR(
45 napi_define_properties(env, exportObj, sizeof(properties) / sizeof(properties[0]), properties) == napi_ok,
46 TextErrorCode::ERROR_INVALID_PARAM, "Failed to define properties");
47 return exportObj;
48 }
49
JsFontDescriptor()50 JsFontDescriptor::JsFontDescriptor() {}
51
52
SetProperty(napi_env env,napi_value object,const char * name,napi_value value)53 bool JsFontDescriptor::SetProperty(napi_env env, napi_value object, const char* name, napi_value value)
54 {
55 TEXT_ERROR_CHECK(napi_set_named_property(env, object, name, value) == napi_ok, return false,
56 "Failed to set %{public}s", name);
57 return true;
58 }
59
ConvertFontDescWeight(napi_env env,napi_value obj,int weight)60 bool JsFontDescriptor::ConvertFontDescWeight(napi_env env, napi_value obj, int weight)
61 {
62 auto iter = g_weightMap.find(weight);
63 if (iter == g_weightMap.end()) {
64 return false;
65 }
66 TEXT_CHECK_RETURN_VALUE(SetProperty(env, obj, "weight", CreateJsValue(env, iter->second)), false);
67 return true;
68 }
69
CreateAndSetProperties(napi_env env,napi_value fontDescriptor,FontDescSharedPtr item)70 bool JsFontDescriptor::CreateAndSetProperties(napi_env env, napi_value fontDescriptor, FontDescSharedPtr item)
71 {
72 std::vector<std::pair<const char*, std::variant<int, double, bool, std::string>>> properties = {
73 {"path", item->path},
74 {"postScriptName", item->postScriptName},
75 {"fullName", item->fullName},
76 {"fontFamily", item->fontFamily},
77 {"fontSubfamily", item->fontSubfamily},
78 {"width", item->width},
79 {"italic", item->italic},
80 {"monoSpace", item->monoSpace},
81 {"symbolic", item->symbolic},
82 };
83
84 for (const auto& prop : properties) {
85 TEXT_CHECK(std::visit([&](auto& p) -> bool {
86 TEXT_CHECK(SetProperty(env, fontDescriptor, prop.first, CreateJsValue(env, p)), return false);
87 return true;
88 }, prop.second), return false);
89 }
90 return true;
91 }
92
CreateFontDescriptor(napi_env env,FontDescSharedPtr & result)93 napi_value JsFontDescriptor::CreateFontDescriptor(napi_env env, FontDescSharedPtr& result)
94 {
95 TEXT_ERROR_CHECK(env != nullptr, return nullptr, "Env is nullptr");
96 TEXT_ERROR_CHECK(result != nullptr, return nullptr, "FontDescSharedPtr is nullptr");
97 napi_value fontDescriptor = nullptr;
98 TEXT_ERROR_CHECK(napi_create_object(env, &fontDescriptor) == napi_ok, return nullptr,
99 "Failed to create fontDescriptor");
100 TEXT_CHECK(CreateAndSetProperties(env, fontDescriptor, result), return nullptr);
101 TEXT_CHECK(ConvertFontDescWeight(env, fontDescriptor, result->weight), return nullptr);
102 return fontDescriptor;
103 }
104
GetSystemFontFullNamesByType(napi_env env,napi_callback_info info)105 napi_value JsFontDescriptor::GetSystemFontFullNamesByType(napi_env env, napi_callback_info info)
106 {
107 struct SystemFontListContext : public ContextBase {
108 TextEngine::FontParser::SystemFontType systemFontType;
109 std::unordered_set<std::string> fontList;
110 };
111
112 sptr<SystemFontListContext> context = sptr<SystemFontListContext>::MakeSptr();
113
114 NAPI_CHECK_AND_THROW_ERROR(context != nullptr, TextErrorCode::ERROR_NO_MEMORY,
115 "Failed to get systemFont fullName list by type, no memory");
116
117 auto inputParser = [env, context](size_t argc, napi_value *argv) {
118 TEXT_ERROR_CHECK(argv != nullptr, return, "Argv is nullptr");
119 NAPI_CHECK_ARGS(context, context->status == napi_ok, napi_invalid_arg,
120 TextErrorCode::ERROR_INVALID_PARAM, return, "Status error, status=%d", static_cast<int>(context->status));
121 NAPI_CHECK_ARGS(context, argc == ARGC_ONE, napi_invalid_arg, TextErrorCode::ERROR_INVALID_PARAM,
122 return, "Argc is invalid %zu", argc);
123 NAPI_CHECK_ARGS(context, ConvertFromJsValue(env, argv[0], context->systemFontType), napi_invalid_arg,
124 TextErrorCode::ERROR_INVALID_PARAM, return, "Parameter systemFontType is invalid");
125 };
126
127 context->GetCbInfo(env, info, inputParser);
128
129 auto executor = [context]() {
130 FontDescriptorMgrInstance.GetSystemFontFullNamesByType(context->systemFontType, context->fontList);
131 };
132
133 auto complete = [env, context](napi_value& output) {
134 output = JsFontDescriptor::CreateFontList(env, context->fontList);
135 };
136
137 return NapiAsyncWork::Enqueue(env, context, "GetSystemFontFullNamesByType", executor, complete);
138 }
139
CreateFontList(napi_env env,std::unordered_set<std::string> & fontList)140 napi_value JsFontDescriptor::CreateFontList(napi_env env, std::unordered_set<std::string>& fontList)
141 {
142 TEXT_ERROR_CHECK(env != nullptr, return nullptr, "Env is nullptr");
143 napi_value fullNameArray = nullptr;
144 TEXT_ERROR_CHECK(napi_create_array(env, &fullNameArray) == napi_ok, return nullptr,
145 "Failed to create fontList");
146 uint32_t index = 0;
147 for (const auto& item : fontList) {
148 napi_value fullName = nullptr;
149 TEXT_ERROR_CHECK(napi_create_string_utf8(env, item.c_str(), NAPI_AUTO_LENGTH, &fullName) == napi_ok,
150 return nullptr, "Failed to create utf8 to string");
151 TEXT_ERROR_CHECK(napi_set_element(env, fullNameArray, index++, fullName) == napi_ok, return nullptr,
152 "Failed to set element");
153 }
154 return fullNameArray;
155 }
156
GetFontDescriptorByFullName(napi_env env,napi_callback_info info)157 napi_value JsFontDescriptor::GetFontDescriptorByFullName(napi_env env, napi_callback_info info)
158 {
159 struct FontDescriptorContext : public ContextBase {
160 std::string fullName;
161 TextEngine::FontParser::SystemFontType systemFontType;
162 FontDescSharedPtr resultDesc = nullptr;
163 };
164
165 sptr<FontDescriptorContext> context = sptr<FontDescriptorContext>::MakeSptr();
166
167 NAPI_CHECK_AND_THROW_ERROR(context != nullptr, TextErrorCode::ERROR_NO_MEMORY,
168 "Failed to get fontDescriptor by name, no memory");
169
170 auto inputParser = [env, context](size_t argc, napi_value *argv) {
171 TEXT_ERROR_CHECK(argv != nullptr, return, "Argv is nullptr");
172 NAPI_CHECK_ARGS(context, context->status == napi_ok, napi_invalid_arg,
173 TextErrorCode::ERROR_INVALID_PARAM, return, "Status error, status=%d", static_cast<int>(context->status));
174 NAPI_CHECK_ARGS(context, argc == ARGC_TWO, napi_invalid_arg, TextErrorCode::ERROR_INVALID_PARAM,
175 return, "Argc is invalid %zu", argc);
176 NAPI_CHECK_ARGS(context, ConvertFromJsValue(env, argv[0], context->fullName), napi_invalid_arg,
177 TextErrorCode::ERROR_INVALID_PARAM, return, "Parameter fullName is invalid");
178 NAPI_CHECK_ARGS(context, ConvertFromJsValue(env, argv[1], context->systemFontType), napi_invalid_arg,
179 TextErrorCode::ERROR_INVALID_PARAM, return, "Parameter systemFontType is invalid");
180 };
181
182 context->GetCbInfo(env, info, inputParser);
183
184 auto executor = [context]() {
185 FontDescriptorMgrInstance.GetFontDescSharedPtrByFullName(
186 context->fullName, context->systemFontType, context->resultDesc);
187 };
188
189 auto complete = [env, context](napi_value& output) {
190 output = JsFontDescriptor::CreateFontDescriptor(env, context->resultDesc);
191 };
192
193 return NapiAsyncWork::Enqueue(env, context, "GetFontDescriptorByFullName", executor, complete);
194 }
195 }