• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_font.h"
17 #include "js_typeface.h"
18 #include "../js_drawing_utils.h"
19 #include "native_value.h"
20 
21 namespace OHOS::Rosen {
22 namespace Drawing {
23 thread_local napi_ref JsFont::constructor_ = nullptr;
24 const std::string CLASS_NAME = "Font";
Init(napi_env env,napi_value exportObj)25 napi_value JsFont::Init(napi_env env, napi_value exportObj)
26 {
27     napi_property_descriptor properties[] = {
28         DECLARE_NAPI_FUNCTION("enableSubpixel", JsFont::EnableSubpixel),
29         DECLARE_NAPI_FUNCTION("enableEmbolden", JsFont::EnableEmbolden),
30         DECLARE_NAPI_FUNCTION("enableLinearMetrics", JsFont::EnableLinearMetrics),
31         DECLARE_NAPI_FUNCTION("setSize", JsFont::SetSize),
32         DECLARE_NAPI_FUNCTION("setTypeface", JsFont::SetTypeface),
33         DECLARE_NAPI_FUNCTION("getTypeface", JsFont::GetTypeface),
34         DECLARE_NAPI_FUNCTION("getSize", JsFont::GetSize),
35         DECLARE_NAPI_FUNCTION("getMetrics", JsFont::GetMetrics),
36         DECLARE_NAPI_FUNCTION("measureText", JsFont::MeasureText),
37     };
38 
39     napi_value constructor = nullptr;
40     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
41                                            sizeof(properties) / sizeof(properties[0]), properties, &constructor);
42     if (status != napi_ok) {
43         ROSEN_LOGE("Failed to define Font class");
44         return nullptr;
45     }
46 
47     status = napi_create_reference(env, constructor, 1, &constructor_);
48     if (status != napi_ok) {
49         ROSEN_LOGE("Failed to create reference of constructor");
50         return nullptr;
51     }
52 
53     status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
54     if (status != napi_ok) {
55         ROSEN_LOGE("Failed to set constructor");
56         return nullptr;
57     }
58 
59     napi_property_descriptor staticProperty[] = {
60         DECLARE_NAPI_STATIC_FUNCTION("createFont", JsFont::CreateFont),
61     };
62     status = napi_define_properties(env, exportObj, 1, staticProperty);
63     if (status != napi_ok) {
64         ROSEN_LOGE("Failed to define static function");
65         return nullptr;
66     }
67     return exportObj;
68 }
69 
Constructor(napi_env env,napi_callback_info info)70 napi_value JsFont::Constructor(napi_env env, napi_callback_info info)
71 {
72     size_t argCount = 0;
73     napi_value jsThis = nullptr;
74     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
75     if (status != napi_ok) {
76         ROSEN_LOGE("failed to napi_get_cb_info");
77         return nullptr;
78     }
79 
80     std::shared_ptr<Font> font = std::make_shared<Font>();
81     JsFont *jsFont = new(std::nothrow) JsFont(font);
82 
83     status = napi_wrap(env, jsThis, jsFont,
84                        JsFont::Destructor, nullptr, nullptr);
85     if (status != napi_ok) {
86         delete jsFont;
87         ROSEN_LOGE("Failed to wrap native instance");
88         return nullptr;
89     }
90     return jsThis;
91 }
92 
Destructor(napi_env env,void * nativeObject,void * finalize)93 void JsFont::Destructor(napi_env env, void *nativeObject, void *finalize)
94 {
95     (void)finalize;
96     if (nativeObject != nullptr) {
97         JsFont *napi = reinterpret_cast<JsFont *>(nativeObject);
98         delete napi;
99     }
100 }
101 
CreateFont(napi_env env,napi_callback_info info)102 napi_value JsFont::CreateFont(napi_env env, napi_callback_info info)
103 {
104     napi_value result = nullptr;
105     napi_value constructor = nullptr;
106     napi_status status = napi_get_reference_value(env, constructor_, &constructor);
107     if (status != napi_ok) {
108         ROSEN_LOGE("Failed to get the representation of constructor object");
109         return nullptr;
110     }
111 
112     status = napi_new_instance(env, constructor, 0, nullptr, &result);
113     if (status != napi_ok) {
114         ROSEN_LOGE("Failed to instantiate JavaScript font instance");
115         return nullptr;
116     }
117     return result;
118 }
119 
~JsFont()120 JsFont::~JsFont()
121 {
122     m_font = nullptr;
123 }
124 
EnableSubpixel(napi_env env,napi_callback_info info)125 napi_value JsFont::EnableSubpixel(napi_env env, napi_callback_info info)
126 {
127     JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
128     return (me != nullptr) ? me->OnEnableSubpixel(env, info) : nullptr;
129 }
130 
EnableEmbolden(napi_env env,napi_callback_info info)131 napi_value JsFont::EnableEmbolden(napi_env env, napi_callback_info info)
132 {
133     JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
134     return (me != nullptr) ? me->OnEnableEmbolden(env, info) : nullptr;
135 }
136 
EnableLinearMetrics(napi_env env,napi_callback_info info)137 napi_value JsFont::EnableLinearMetrics(napi_env env, napi_callback_info info)
138 {
139     JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
140     return (me != nullptr) ? me->OnEnableLinearMetrics(env, info) : nullptr;
141 }
142 
SetSize(napi_env env,napi_callback_info info)143 napi_value JsFont::SetSize(napi_env env, napi_callback_info info)
144 {
145     JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
146     return (me != nullptr) ? me->OnSetSize(env, info) : nullptr;
147 }
148 
SetTypeface(napi_env env,napi_callback_info info)149 napi_value JsFont::SetTypeface(napi_env env, napi_callback_info info)
150 {
151     JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
152     return (me != nullptr) ? me->OnSetTypeface(env, info) : nullptr;
153 }
154 
GetTypeface(napi_env env,napi_callback_info info)155 napi_value JsFont::GetTypeface(napi_env env, napi_callback_info info)
156 {
157     JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
158     return (me != nullptr) ? me->OnGetTypeface(env, info) : nullptr;
159 }
160 
GetSize(napi_env env,napi_callback_info info)161 napi_value JsFont::GetSize(napi_env env, napi_callback_info info)
162 {
163     JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
164     return (me != nullptr) ? me->OnGetSize(env, info) : nullptr;
165 }
166 
GetMetrics(napi_env env,napi_callback_info info)167 napi_value JsFont::GetMetrics(napi_env env, napi_callback_info info)
168 {
169     JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
170     return (me != nullptr) ? me->OnGetMetrics(env, info) : nullptr;
171 }
172 
MeasureText(napi_env env,napi_callback_info info)173 napi_value JsFont::MeasureText(napi_env env, napi_callback_info info)
174 {
175     JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
176     return (me != nullptr) ? me->OnMeasureText(env, info) : nullptr;
177 }
178 
OnEnableSubpixel(napi_env env,napi_callback_info info)179 napi_value JsFont::OnEnableSubpixel(napi_env env, napi_callback_info info)
180 {
181     if (m_font == nullptr) {
182         ROSEN_LOGE("JsFont::OnEnableSubpixel font is nullptr");
183         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
184     }
185 
186     size_t argc = ARGC_ONE;
187     napi_value argv[ARGC_ONE] = {nullptr};
188     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
189     if (status != napi_ok || argc < ARGC_ONE) {
190         ROSEN_LOGE("JsFont::OnEnableSubpixel Argc is invalid: %{public}zu", argc);
191         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
192     }
193 
194     bool isSubpixel = false;
195     if (!ConvertFromJsValue(env, argv[0], isSubpixel)) {
196         ROSEN_LOGE("JsFont::OnEnableSubpixel Argv[0] is invalid");
197         return NapiGetUndefined(env);
198     }
199 
200     m_font->SetSubpixel(isSubpixel);
201     return NapiGetUndefined(env);
202 }
203 
OnEnableEmbolden(napi_env env,napi_callback_info info)204 napi_value JsFont::OnEnableEmbolden(napi_env env, napi_callback_info info)
205 {
206     if (m_font == nullptr) {
207         ROSEN_LOGE("JsFont::OnEnableEmbolden font is nullptr");
208         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
209     }
210 
211     size_t argc = ARGC_ONE;
212     napi_value argv[ARGC_ONE] = {nullptr};
213     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
214     if (status != napi_ok || argc < ARGC_ONE) {
215         ROSEN_LOGE("JsFont::OnEnableEmbolden Argc is invalid: %{public}zu", argc);
216         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
217     }
218 
219     bool isEmbolden = false;
220     if (!ConvertFromJsValue(env, argv[0], isEmbolden)) {
221         ROSEN_LOGE("JsFont::OnEnableEmbolden Argv[0] is invalid");
222         return NapiGetUndefined(env);
223     }
224 
225     m_font->SetEmbolden(isEmbolden);
226     return NapiGetUndefined(env);
227 }
228 
OnEnableLinearMetrics(napi_env env,napi_callback_info info)229 napi_value JsFont::OnEnableLinearMetrics(napi_env env, napi_callback_info info)
230 {
231     if (m_font == nullptr) {
232         ROSEN_LOGE("JsFont::OnEnableLinearMetrics font is nullptr");
233         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
234     }
235 
236     size_t argc = ARGC_ONE;
237     napi_value argv[ARGC_ONE] = {nullptr};
238     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
239     if (status != napi_ok || argc < ARGC_ONE) {
240         ROSEN_LOGE("JsFont::OnEnableLinearMetrics Argc is invalid: %{public}zu", argc);
241         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
242     }
243 
244     bool isLinearMetrics = false;
245     if (!ConvertFromJsValue(env, argv[0], isLinearMetrics)) {
246         ROSEN_LOGE("JsFont::OnEnableLinearMetrics Argv[0] is invalid");
247         return NapiGetUndefined(env);
248     }
249 
250     m_font->SetLinearMetrics(isLinearMetrics);
251     return NapiGetUndefined(env);
252 }
253 
OnSetSize(napi_env env,napi_callback_info info)254 napi_value JsFont::OnSetSize(napi_env env, napi_callback_info info)
255 {
256     if (m_font == nullptr) {
257         ROSEN_LOGE("JsFont::OnSetSize font is nullptr");
258         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
259     }
260 
261     size_t argc = ARGC_ONE;
262     napi_value argv[ARGC_ONE] = {nullptr};
263     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
264     if (status != napi_ok || argc < ARGC_ONE) {
265         ROSEN_LOGE("JsFont::OnSetSize Argc is invalid: %{public}zu", argc);
266         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
267     }
268 
269     double textSize = 0.0;
270     if (!ConvertFromJsValue(env, argv[0], textSize)) {
271         ROSEN_LOGE("JsFont::OnSetSize Argv[0] is invalid");
272         return NapiGetUndefined(env);
273     }
274 
275     m_font->SetSize((float)textSize);
276     return NapiGetUndefined(env);
277 }
278 
OnGetSize(napi_env env,napi_callback_info info)279 napi_value JsFont::OnGetSize(napi_env env, napi_callback_info info)
280 {
281     if (m_font == nullptr) {
282         ROSEN_LOGE("JsFont::OnGetSize font is nullptr");
283         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
284     }
285 
286     double textSize = m_font->GetSize();
287     return GetDoubleAndConvertToJsValue(env, textSize);
288 }
289 
OnGetMetrics(napi_env env,napi_callback_info info)290 napi_value JsFont::OnGetMetrics(napi_env env, napi_callback_info info)
291 {
292     if (m_font == nullptr) {
293         ROSEN_LOGE("JsFont::OnGetMetrics font is nullptr");
294         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
295     }
296     FontMetrics metrics;
297     m_font->GetMetrics(&metrics);
298     return GetFontMetricsAndConvertToJsValue(env, &metrics);
299 }
300 
OnSetTypeface(napi_env env,napi_callback_info info)301 napi_value JsFont::OnSetTypeface(napi_env env, napi_callback_info info)
302 {
303     if (m_font == nullptr) {
304         ROSEN_LOGE("JsFont::OnSetTypeface font is nullptr");
305         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
306     }
307 
308     size_t argc = ARGC_ONE;
309     napi_value argv[ARGC_ONE] = {nullptr};
310     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
311     if (status != napi_ok || argc < ARGC_ONE) {
312         ROSEN_LOGE("JsFont::OnSetTypeface Argc is invalid: %{public}zu", argc);
313         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
314     }
315     JsTypeface *jsTypeface = nullptr;
316     napi_unwrap(env, argv[0], (void **)&jsTypeface);
317     if (jsTypeface == nullptr) {
318         ROSEN_LOGE("JsFont::OnSetTypeface jsTypeface is nullptr");
319         return NapiGetUndefined(env);
320     }
321 
322     m_font->SetTypeface(jsTypeface->GetTypeface());
323     return NapiGetUndefined(env);
324 }
325 
OnGetTypeface(napi_env env,napi_callback_info info)326 napi_value JsFont::OnGetTypeface(napi_env env, napi_callback_info info)
327 {
328     if (m_font == nullptr) {
329         ROSEN_LOGE("JsFont::OnGetTypeface font is nullptr");
330         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
331     }
332 
333     std::shared_ptr<Typeface> typeface = m_font->GetTypeface();
334     return JsTypeface::CreateJsTypeface(env, typeface);
335 }
336 
OnMeasureText(napi_env env,napi_callback_info info)337 napi_value JsFont::OnMeasureText(napi_env env, napi_callback_info info)
338 {
339     if (m_font == nullptr) {
340         ROSEN_LOGE("JsFont::OnMeasureText font is nullptr");
341         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
342     }
343 
344     size_t argc = ARGC_TWO;
345     napi_value argv[ARGC_TWO] = {nullptr};
346     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
347     if (status != napi_ok || argc < ARGC_TWO) {
348         ROSEN_LOGE("JsFont::OnMeasureText Argc is invalid: %{public}zu", argc);
349         return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
350     }
351 
352     std::string text = "";
353     if (!ConvertFromJsValue(env, argv[0], text)) {
354         ROSEN_LOGE("JsFont::OnMeasureText Argv[0] is invalid");
355         return NapiGetUndefined(env);
356     }
357 
358     TextEncoding TextEncoding = TextEncoding::UTF8;
359     if (!ConvertFromJsTextEncoding(env, TextEncoding, argv[1])) {
360         ROSEN_LOGE("JsFont::OnMeasureText ConvertFromJsTextEncoding failed");
361         return NapiGetUndefined(env);
362     }
363 
364     double textSize = m_font->MeasureText(text.c_str(), text.length(), TextEncoding);
365     return GetDoubleAndConvertToJsValue(env, textSize);
366 }
367 
GetFont()368 std::shared_ptr<Font> JsFont::GetFont()
369 {
370     return m_font;
371 }
372 } // namespace Drawing
373 } // namespace OHOS::Rosen