• 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         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