1 /*
2 * Copyright (c) 2022 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 <optional>
17 #include <string>
18
19 #include "interfaces/napi/kits/utils/napi_utils.h"
20 #include "js_native_api.h"
21 #include "js_native_api_types.h"
22 #include "napi/native_api.h"
23 #include "napi/native_engine/native_value.h"
24 #include "napi/native_node_api.h"
25
26 #include "base/geometry/dimension.h"
27 #include "base/geometry/size.h"
28 #include "bridge/common/utils/engine_helper.h"
29 #include "bridge/js_frontend/engine/common/js_engine.h"
30 #include "core/components/common/layout/constants.h"
31 #include "core/components/common/properties/text_style.h"
32 #include "frameworks/base/utils/measure_util.h"
33
34 namespace OHOS::Ace::Napi {
HandleIntStyle(napi_value fontStyleNApi,napi_env env)35 static int32_t HandleIntStyle(napi_value fontStyleNApi, napi_env env)
36 {
37 size_t ret = 0;
38 int32_t fontStyleInt = 0;
39 std::string fontStyleStr;
40 napi_valuetype valueType = napi_undefined;
41 napi_typeof(env, fontStyleNApi, &valueType);
42 if (valueType == napi_string) {
43 size_t fontStyleLen = GetParamLen(fontStyleNApi) + 1;
44 std::unique_ptr<char[]> fontStyleTemp = std::make_unique<char[]>(fontStyleLen);
45 napi_get_value_string_utf8(env, fontStyleNApi, fontStyleTemp.get(), fontStyleLen, &ret);
46 fontStyleStr = fontStyleTemp.get();
47 fontStyleInt = StringUtils::StringToInt(fontStyleStr);
48 } else if (valueType == napi_number) {
49 napi_get_value_int32(env, fontStyleNApi, &fontStyleInt);
50 } else if (valueType == napi_object) {
51 int32_t id = 0;
52 int32_t type = 0;
53 std::vector<std::string> params;
54 if (!ParseResourceParam(env, fontStyleNApi, id, type, params)) {
55 LOGE("can not parse resource info from inout params.");
56 return fontStyleInt;
57 }
58 if (!ParseString(id, type, params, fontStyleStr)) {
59 LOGE("can not get message from resource manager.");
60 return fontStyleInt;
61 }
62 fontStyleInt = StringUtils::StringToInt(fontStyleStr);
63 } else {
64 LOGE("The parameter type is incorrect.");
65 return fontStyleInt;
66 }
67 return fontStyleInt;
68 }
69
HandleStringType(napi_value ParameterNApi,napi_env env)70 static std::string HandleStringType(napi_value ParameterNApi, napi_env env)
71 {
72 size_t ret = 0;
73 std::string ParameterStr;
74 int32_t ParameterInt = 0;
75 napi_valuetype valueType = napi_undefined;
76 napi_typeof(env, ParameterNApi, &valueType);
77 if (valueType == napi_string) {
78 size_t ParameterLen = GetParamLen(ParameterNApi) + 1;
79 std::unique_ptr<char[]> Parameter = std::make_unique<char[]>(ParameterLen);
80 napi_get_value_string_utf8(env, ParameterNApi, Parameter.get(), ParameterLen, &ret);
81 ParameterStr = Parameter.get();
82 } else if (valueType == napi_number) {
83 napi_get_value_int32(env, ParameterNApi, &ParameterInt);
84 ParameterStr = std::to_string(ParameterInt);
85 } else if (valueType == napi_object) {
86 int32_t id = 0;
87 int32_t type = 0;
88 std::vector<std::string> params;
89 if (!ParseResourceParam(env, ParameterNApi, id, type, params)) {
90 LOGE("can not parse resource info from inout params.");
91 return ParameterStr;
92 }
93 if (!ParseString(id, type, params, ParameterStr)) {
94 LOGE("can not get message from resource manager.");
95 return ParameterStr;
96 }
97 } else {
98 LOGE("The parameter type is incorrect.");
99 return ParameterStr;
100 }
101 return ParameterStr;
102 }
103
HandleDimensionType(napi_value ParameterNApi,napi_env env)104 static std::optional<Dimension> HandleDimensionType(napi_value ParameterNApi, napi_env env)
105 {
106 size_t ret = 0;
107 std::string ParameterStr;
108 napi_valuetype valueType = napi_undefined;
109 napi_typeof(env, ParameterNApi, &valueType);
110 Dimension Parameter;
111 if (valueType == napi_number) {
112 double ParameterValue;
113 napi_get_value_double(env, ParameterNApi, &ParameterValue);
114 Parameter.SetValue(ParameterValue);
115 Parameter.SetUnit(DimensionUnit::VP);
116 } else if (valueType == napi_string) {
117 size_t ParameterLen = GetParamLen(ParameterNApi) + 1;
118 std::unique_ptr<char[]> ParameterTemp = std::make_unique<char[]>(ParameterLen);
119 napi_get_value_string_utf8(env, ParameterNApi, ParameterTemp.get(), ParameterLen, &ret);
120 ParameterStr = ParameterTemp.get();
121 Parameter = StringUtils::StringToDimensionWithUnit(ParameterStr, DimensionUnit::VP);
122 } else if (valueType == napi_object) {
123 int32_t id = 0;
124 int32_t type = 0;
125 std::vector<std::string> params;
126 if (!ParseResourceParam(env, ParameterNApi, id, type, params)) {
127 LOGE("can not parse resource info from inout params.");
128 return std::nullopt;
129 }
130 if (!ParseString(id, type, params, ParameterStr)) {
131 LOGE("can not get message from resource manager.");
132 return std::nullopt;
133 }
134 Parameter = StringUtils::StringToDimensionWithUnit(ParameterStr, DimensionUnit::VP);
135 } else {
136 return std::nullopt;
137 }
138 return Parameter;
139 }
140
JSMeasureText(napi_env env,napi_callback_info info)141 static napi_value JSMeasureText(napi_env env, napi_callback_info info)
142 {
143 size_t argc = 1;
144 napi_value result = nullptr;
145 napi_value argv = nullptr;
146 napi_value thisvar = nullptr;
147 void* data = nullptr;
148 napi_get_cb_info(env, info, &argc, &argv, &thisvar, &data);
149
150 napi_value textContentNApi = nullptr;
151 napi_value fontSizeNApi = nullptr;
152 napi_value fontStyleNApi = nullptr;
153 napi_value fontWeightNApi = nullptr;
154 napi_value fontFamilyNApi = nullptr;
155 napi_value letterSpacingNApi = nullptr;
156
157 napi_valuetype valueType = napi_undefined;
158 napi_typeof(env, argv, &valueType);
159 if (valueType == napi_object) {
160 napi_get_named_property(env, argv, "textContent", &textContentNApi);
161 napi_get_named_property(env, argv, "fontSize", &fontSizeNApi);
162 napi_get_named_property(env, argv, "fontStyle", &fontStyleNApi);
163 napi_get_named_property(env, argv, "fontWeight", &fontWeightNApi);
164 napi_get_named_property(env, argv, "fontFamily", &fontFamilyNApi);
165 napi_get_named_property(env, argv, "letterSpacing", &letterSpacingNApi);
166 } else {
167 return nullptr;
168 }
169 std::optional<Dimension> fontSizeNum = HandleDimensionType(fontSizeNApi, env);
170 std::optional<Dimension> letterSpace = HandleDimensionType(letterSpacingNApi, env);
171 int32_t fontStyle = HandleIntStyle(fontStyleNApi, env);
172 std::string textContent = HandleStringType(textContentNApi, env);
173 std::string fontWeight = HandleStringType(fontWeightNApi, env);
174 std::string fontFamily = HandleStringType(fontFamilyNApi, env);
175 MeasureContext context;
176 context.textContent = textContent;
177 context.fontSize = fontSizeNum;
178 context.fontStyle = static_cast<FontStyle>(fontStyle);
179 context.fontWeight = fontWeight;
180 context.fontFamily = fontFamily;
181 context.letterSpacing = letterSpace;
182 auto delegate = EngineHelper::GetCurrentDelegate();
183 if (!delegate) {
184 return nullptr;
185 }
186 double textWidth = delegate->MeasureText(context);
187 napi_create_double(env, textWidth, &result);
188 return result;
189 }
190
JSMeasureTextSize(napi_env env,napi_callback_info info)191 static napi_value JSMeasureTextSize(napi_env env, napi_callback_info info)
192 {
193 size_t argc = 1;
194 napi_value result = nullptr;
195 napi_value argv = nullptr;
196 napi_value thisvar = nullptr;
197 void* data = nullptr;
198 napi_get_cb_info(env, info, &argc, &argv, &thisvar, &data);
199
200 napi_value textContentNApi = nullptr;
201 napi_value constraintWidthNApi = nullptr;
202 napi_value fontSizeNApi = nullptr;
203 napi_value fontStyleNApi = nullptr;
204 napi_value fontWeightNApi = nullptr;
205 napi_value fontFamilyNApi = nullptr;
206 napi_value letterSpacingNApi = nullptr;
207 napi_value textAlignNApi = nullptr;
208 napi_value textOverFlowNApi = nullptr;
209 napi_value maxLinesNApi = nullptr;
210 napi_value lineHeightNApi = nullptr;
211 napi_value baselineOffsetNApi = nullptr;
212 napi_value textCaseNApi = nullptr;
213
214 napi_valuetype valueType = napi_undefined;
215 napi_typeof(env, argv, &valueType);
216 MeasureContext context;
217 if (valueType == napi_object) {
218 napi_get_named_property(env, argv, "textContent", &textContentNApi);
219 napi_get_named_property(env, argv, "constraintWidth", &constraintWidthNApi);
220 napi_get_named_property(env, argv, "fontSize", &fontSizeNApi);
221 napi_get_named_property(env, argv, "fontStyle", &fontStyleNApi);
222 napi_get_named_property(env, argv, "fontWeight", &fontWeightNApi);
223 napi_get_named_property(env, argv, "fontFamily", &fontFamilyNApi);
224 napi_get_named_property(env, argv, "letterSpacing", &letterSpacingNApi);
225 napi_get_named_property(env, argv, "textAlign", &textAlignNApi);
226 napi_get_named_property(env, argv, "overflow", &textOverFlowNApi);
227 napi_get_named_property(env, argv, "maxLines", &maxLinesNApi);
228 napi_get_named_property(env, argv, "lineHeight", &lineHeightNApi);
229 napi_get_named_property(env, argv, "baselineOffset", &baselineOffsetNApi);
230 napi_get_named_property(env, argv, "textCase", &textCaseNApi);
231 } else {
232 return nullptr;
233 }
234 std::optional<Dimension> fontSizeNum = HandleDimensionType(fontSizeNApi, env);
235 std::optional<Dimension> letterSpace = HandleDimensionType(letterSpacingNApi, env);
236 std::optional<Dimension> constraintWidth = HandleDimensionType(constraintWidthNApi, env);
237 std::optional<Dimension> lineHeight = HandleDimensionType(lineHeightNApi, env);
238 std::optional<Dimension> baselineOffset = HandleDimensionType(baselineOffsetNApi, env);
239 int32_t fontStyle = HandleIntStyle(fontStyleNApi, env);
240 int32_t textAlign = HandleIntStyle(textAlignNApi, env);
241 int32_t textOverFlow = HandleIntStyle(textOverFlowNApi, env);
242 int32_t maxlines = HandleIntStyle(maxLinesNApi, env);
243 int32_t textCase = HandleIntStyle(textCaseNApi, env);
244 std::string textContent = HandleStringType(textContentNApi, env);
245 std::string fontWeight = HandleStringType(fontWeightNApi, env);
246 std::string fontFamily = HandleStringType(fontFamilyNApi, env);
247 context.textContent = textContent;
248 context.constraintWidth = constraintWidth;
249 context.fontSize = fontSizeNum;
250 context.fontStyle = static_cast<FontStyle>(fontStyle);
251 context.fontWeight = fontWeight;
252 context.fontFamily = fontFamily;
253 context.letterSpacing = letterSpace;
254 context.textAlign = static_cast<TextAlign>(textAlign);
255 context.textOverlayFlow = static_cast<TextOverflow>(textOverFlow);
256 context.maxlines = maxlines;
257 context.lineHeight = lineHeight;
258 context.baselineOffset = baselineOffset;
259 context.textCase = static_cast<TextCase>(textCase);
260 auto delegate = EngineHelper::GetCurrentDelegate();
261 if (!delegate) {
262 return nullptr;
263 }
264 Size textSize = delegate->MeasureTextSize(context);
265
266 napi_escapable_handle_scope scope = nullptr;
267 napi_open_escapable_handle_scope(env, &scope);
268 if (scope == nullptr) {
269 return result;
270 }
271
272 napi_value resultArray[2] = { 0 };
273 napi_create_double(env, textSize.Width(), &resultArray[0]);
274 napi_create_double(env, textSize.Height(), &resultArray[1]);
275
276 napi_create_object(env, &result);
277 napi_set_named_property(env, result, "width", resultArray[0]);
278 napi_set_named_property(env, result, "height", resultArray[1]);
279
280 napi_value newResult = nullptr;
281 napi_escape_handle(env, scope, result, &newResult);
282 napi_close_escapable_handle_scope(env, scope);
283 return result;
284 }
285
MeasureExport(napi_env env,napi_value exports)286 static napi_value MeasureExport(napi_env env, napi_value exports)
287 {
288 napi_property_descriptor measureDesc[] = {
289 DECLARE_NAPI_FUNCTION("measureText", JSMeasureText),
290 DECLARE_NAPI_FUNCTION("measureTextSize", JSMeasureTextSize),
291 };
292 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(measureDesc) / sizeof(measureDesc[0]), measureDesc));
293 return exports;
294 }
295
296 static napi_module measureModule = {
297 .nm_version = 1,
298 .nm_flags = 0,
299 .nm_filename = nullptr,
300 .nm_register_func = MeasureExport,
301 .nm_modname = "measure",
302 .nm_priv = ((void*)0),
303 .reserved = { 0 },
304 };
305
MeasureRegister()306 extern "C" __attribute__((constructor)) void MeasureRegister()
307 {
308 napi_module_register(&measureModule);
309 }
310 } // namespace OHOS::Ace::Napi
311
312