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