• 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 #ifndef OHOS_JS_TEXT_UTILS_H
17 #define OHOS_JS_TEXT_UTILS_H
18 
19 #include <codecvt>
20 #include <map>
21 
22 #include "draw/color.h"
23 #include "native_engine/native_engine.h"
24 #include "native_engine/native_value.h"
25 #include "text_style.h"
26 #include "typography.h"
27 #include "typography_create.h"
28 #include "typography_style.h"
29 #include "utils/point.h"
30 #include "utils/text_log.h"
31 
32 namespace OHOS::Rosen {
33 constexpr size_t ARGC_ONE = 1;
34 constexpr size_t ARGC_TWO = 2;
35 constexpr size_t ARGC_THREE = 3;
36 constexpr size_t ARGC_FOUR = 4;
37 constexpr size_t ARGC_FIVE = 5;
38 constexpr size_t ARGC_SIX = 6;
39 
40 struct ResourceInfo {
41     int32_t resId = 0;
42     int32_t type = 0;
43     std::vector<std::string> params;
44     std::string bundleName;
45     std::string moduleName;
46 };
47 
48 enum class ResourceType {
49     COLOR = 10001,
50     FLOAT,
51     STRING,
52     PLURAL,
53     BOOLEAN,
54     INTARRAY,
55     INTEGER,
56     PATTERN,
57     STRARRAY,
58     MEDIA = 20000,
59     RAWFILE = 30000
60 };
61 
62 enum class TextErrorCode : int32_t {
63     OK = 0,
64     ERROR_NO_PERMISSION = 201, // the value do not change. It is defined on all system
65     ERROR_INVALID_PARAM = 401, // the value do not change. It is defined on all system
66     ERROR_DEVICE_NOT_SUPPORT = 801, // the value do not change. It is defined on all system
67     ERROR_ABNORMAL_PARAM_VALUE = 18600001, // the value do not change. It is defined on color manager system
68 };
69 
70 #define GET_UNWRAP_PARAM(argc, value)                                                                                  \
71     do {                                                                                                               \
72         if ((napi_unwrap(env, argv[argc], reinterpret_cast<void**>(&value)) != napi_ok) || value == nullptr) {         \
73             return NapiThrowError(env, TextErrorCode::ERROR_INVALID_PARAM,                                          \
74                 std::string("Incorrect ") + __FUNCTION__ + " parameter" + std::to_string(argc) + " type.");            \
75         }                                                                                                              \
76     } while (0)
77 
78 
79 #define NAPI_CHECK_AND_THROW_ERROR(ret, errorCode, errorMessage)   \
80     do {                                                           \
81         if (!(ret)) {                                              \
82             TEXT_LOGE("%{public}s", #errorMessage);                \
83             return NapiThrowError(env, errorCode, errorMessage);   \
84         }                                                          \
85     } while (0)
86 
87 #define NAPI_CHECK_AND_CLOSE_SCOPE(env, statement, scope, ret)     \
88     do {                                                           \
89         if ((statement) != napi_ok) {                              \
90             TEXT_LOGE("%{public}s failed", #statement);            \
91             napi_close_handle_scope(env, scope);                   \
92             return ret;                                            \
93         }                                                          \
94     } while (0)
95 
96 template<class T>
97 T* CheckParamsAndGetThis(const napi_env env, napi_callback_info info, const char* name = nullptr)
98 {
99     if (env == nullptr || info == nullptr) {
100         return nullptr;
101     }
102     napi_value object = nullptr;
103     napi_value propertyNameValue = nullptr;
104     napi_value pointerValue = nullptr;
105     napi_get_cb_info(env, info, nullptr, nullptr, &object, nullptr);
106     if (object != nullptr && name != nullptr) {
107         napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &propertyNameValue);
108     }
109     napi_value& resObject = propertyNameValue ? propertyNameValue : object;
110     if (resObject) {
111         return napi_unwrap(env, resObject, (void **)(&pointerValue)) == napi_ok ?
112             reinterpret_cast<T*>(pointerValue) : nullptr;
113     }
114     return nullptr;
115 }
116 
117 template<typename T, size_t N>
ArraySize(T (&)[N])118 inline constexpr size_t ArraySize(T (&)[N]) noexcept
119 {
120     return N;
121 }
122 
CreateJsUndefined(napi_env env)123 inline napi_value CreateJsUndefined(napi_env env)
124 {
125     napi_value result = nullptr;
126     napi_get_undefined(env, &result);
127     return result;
128 }
129 
CreateJsNull(napi_env env)130 inline napi_value CreateJsNull(napi_env env)
131 {
132     napi_value result = nullptr;
133     napi_get_null(env, &result);
134     return result;
135 }
136 
CreateJsNumber(napi_env env,int32_t value)137 inline napi_value CreateJsNumber(napi_env env, int32_t value)
138 {
139     napi_value result = nullptr;
140     napi_create_int32(env, value, &result);
141     return result;
142 }
143 
CreateJsNumber(napi_env env,uint32_t value)144 inline napi_value CreateJsNumber(napi_env env, uint32_t value)
145 {
146     napi_value result = nullptr;
147     napi_create_uint32(env, value, &result);
148     return result;
149 }
150 
CreateJsNumber(napi_env env,int64_t value)151 inline napi_value CreateJsNumber(napi_env env, int64_t value)
152 {
153     napi_value result = nullptr;
154     napi_create_int64(env, value, &result);
155     return result;
156 }
157 
CreateJsNumber(napi_env env,uint64_t value)158 inline napi_value CreateJsNumber(napi_env env, uint64_t value)
159 {
160     napi_value result = nullptr;
161     napi_create_int64(env, value, &result);
162     return result;
163 }
164 
CreateJsNumber(napi_env env,double value)165 inline napi_value CreateJsNumber(napi_env env, double value)
166 {
167     napi_value result = nullptr;
168     napi_create_double(env, value, &result);
169     return result;
170 }
171 
172 template<class T>
CreateJsValue(napi_env env,const T & value)173 napi_value CreateJsValue(napi_env env, const T& value)
174 {
175     using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
176     napi_value result = nullptr;
177     if constexpr (std::is_same_v<ValueType, bool>) {
178         napi_get_boolean(env, value, &result);
179         return result;
180     } else if constexpr (std::is_arithmetic_v<ValueType>) {
181         return CreateJsNumber(env, value);
182     } else if constexpr (std::is_same_v<ValueType, std::string>) {
183         napi_create_string_utf8(env, value.c_str(), value.length(), &result);
184         return result;
185     } else if constexpr (std::is_enum_v<ValueType>) {
186         return CreateJsNumber(env, static_cast<std::make_signed_t<ValueType>>(value));
187     } else if constexpr (std::is_same_v<ValueType, const char*>) {
188         (value != nullptr) ? napi_create_string_utf8(env, value, strlen(value), &result) :
189             napi_get_undefined(env, &result);
190         return result;
191     } else {
192         return result;
193     }
194 }
195 
ConvertFromJsNumber(napi_env env,napi_value jsValue,int32_t & value)196 inline bool ConvertFromJsNumber(napi_env env, napi_value jsValue, int32_t& value)
197 {
198     return napi_get_value_int32(env, jsValue, &value) == napi_ok;
199 }
200 
ConvertFromJsNumber(napi_env env,napi_value jsValue,uint32_t & value)201 inline bool ConvertFromJsNumber(napi_env env, napi_value jsValue, uint32_t& value)
202 {
203     return napi_get_value_uint32(env, jsValue, &value) == napi_ok;
204 }
205 
ConvertFromJsNumber(napi_env env,napi_value jsValue,int64_t & value)206 inline bool ConvertFromJsNumber(napi_env env, napi_value jsValue, int64_t& value)
207 {
208     return napi_get_value_int64(env, jsValue, &value) == napi_ok;
209 }
210 
ConvertFromJsNumber(napi_env env,napi_value jsValue,uint64_t & value)211 inline bool ConvertFromJsNumber(napi_env env, napi_value jsValue, uint64_t& value)
212 {
213     int64_t num;
214     auto res = napi_get_value_int64(env, jsValue, &num);
215     if (res == napi_ok) {
216         value = static_cast<uint64_t>(num);
217     }
218     return res == napi_ok;
219 }
220 
ConvertFromJsNumber(napi_env env,napi_value jsValue,double & value)221 inline bool ConvertFromJsNumber(napi_env env, napi_value jsValue, double& value)
222 {
223     return napi_get_value_double(env, jsValue, &value) == napi_ok;
224 }
225 
ConvertFromJsNumber(napi_env env,napi_value jsValue,bool & value)226 inline bool ConvertFromJsNumber(napi_env env, napi_value jsValue, bool& value)
227 {
228     return napi_get_value_bool(env, jsValue, &value) == napi_ok;
229 }
230 
231 template<class T>
ConvertFromJsValue(napi_env env,napi_value jsValue,T & value)232 bool ConvertFromJsValue(napi_env env, napi_value jsValue, T& value)
233 {
234     if (jsValue == nullptr) {
235         return false;
236     }
237 
238     using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
239     if constexpr (std::is_same_v<ValueType, bool>) {
240         return napi_get_value_bool(env, jsValue, &value) == napi_ok;
241     } else if constexpr (std::is_arithmetic_v<ValueType>) {
242         return ConvertFromJsNumber(env, jsValue, value);
243     } else if constexpr (std::is_same_v<ValueType, std::string>) {
244         size_t len = 0;
245         if (napi_get_value_string_utf8(env, jsValue, nullptr, 0, &len) != napi_ok) {
246             return false;
247         }
248         auto buffer = std::make_unique<char[]>(len + 1);
249         size_t strLength = 0;
250         if (napi_get_value_string_utf8(env, jsValue, buffer.get(), len + 1, &strLength) == napi_ok) {
251             value = buffer.get();
252             return true;
253         }
254         return false;
255     } else if constexpr (std::is_enum_v<ValueType>) {
256         std::make_signed_t<ValueType> numberValue = 0;
257         if (!ConvertFromJsNumber(env, jsValue, numberValue)) {
258             return false;
259         }
260         value = static_cast<ValueType>(numberValue);
261         return true;
262     }
263     return false;
264 }
265 
ConvertClampFromJsValue(napi_env env,napi_value jsValue,int32_t & value,int32_t lo,int32_t hi)266 inline bool ConvertClampFromJsValue(napi_env env, napi_value jsValue, int32_t& value, int32_t lo, int32_t hi)
267 {
268     if (jsValue == nullptr) {
269         return false;
270     }
271     bool ret = napi_get_value_int32(env, jsValue, &value) == napi_ok;
272     value = std::clamp(value, lo, hi);
273     return ret;
274 }
275 
GetDoubleAndConvertToJsValue(napi_env env,double d)276 inline napi_value GetDoubleAndConvertToJsValue(napi_env env, double d)
277 {
278     napi_value value = nullptr;
279     (void)napi_create_double(env, d, &value);
280     return value;
281 }
282 
GetStringAndConvertToJsValue(napi_env env,std::string str)283 inline napi_value GetStringAndConvertToJsValue(napi_env env, std::string str)
284 {
285     napi_value objValue = nullptr;
286     napi_create_string_utf8(env, str.c_str(), str.length(), &objValue);
287     return objValue;
288 }
289 
NapiGetUndefined(napi_env env)290 inline napi_value NapiGetUndefined(napi_env env)
291 {
292     napi_value result = nullptr;
293     napi_get_undefined(env, &result);
294     return result;
295 }
296 
GetPointAndConvertToJsValue(napi_env env,Drawing::Point & point)297 inline napi_value GetPointAndConvertToJsValue(napi_env env, Drawing::Point& point)
298 {
299     napi_value objValue = nullptr;
300     napi_create_object(env, &objValue);
301     if (objValue != nullptr) {
302         napi_set_named_property(env, objValue, "x", CreateJsNumber(env, point.GetX()));
303         napi_set_named_property(env, objValue, "y", CreateJsNumber(env, point.GetY()));
304     }
305     return objValue;
306 }
307 
GetPointXFromJsNumber(napi_env env,napi_value argValue,Drawing::Point & point)308 inline void GetPointXFromJsNumber(napi_env env, napi_value argValue, Drawing::Point& point)
309 {
310     napi_value objValue = nullptr;
311     double targetX = 0;
312     if (napi_get_named_property(env, argValue, "x", &objValue) != napi_ok ||
313         napi_get_value_double(env, objValue, &targetX) != napi_ok) {
314         TEXT_LOGE("The Parameter of number x about JsPoint is unvaild");
315         return;
316     }
317     point.SetX(targetX);
318     return;
319 }
320 
GetPointYFromJsNumber(napi_env env,napi_value argValue,Drawing::Point & point)321 inline void GetPointYFromJsNumber(napi_env env, napi_value argValue, Drawing::Point& point)
322 {
323     napi_value objValue = nullptr;
324     double targetY = 0;
325     if (napi_get_named_property(env, argValue, "y", &objValue) != napi_ok ||
326         napi_get_value_double(env, objValue, &targetY) != napi_ok) {
327         TEXT_LOGE("The Parameter of number y about JsPoint is unvaild");
328         return;
329     }
330     point.SetY(targetY);
331     return;
332 }
333 
GetPointFromJsValue(napi_env env,napi_value argValue,Drawing::Point & point)334 inline void GetPointFromJsValue(napi_env env, napi_value argValue, Drawing::Point& point)
335 {
336     GetPointXFromJsNumber(env, argValue, point);
337     GetPointYFromJsNumber(env, argValue, point);
338     return;
339 }
340 
341 void BindNativeFunction(napi_env env, napi_value object, const char* name, const char* moduleName, napi_callback func);
342 napi_value CreateJsError(napi_env env, int32_t errCode, const std::string& message);
343 
344 napi_value NapiThrowError(napi_env env, TextErrorCode err, const std::string& message);
345 
Str8ToStr16(const std::string & str)346 inline std::u16string Str8ToStr16(const std::string &str)
347 {
348     return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(str);
349 }
350 
SetDoubleValueFromJS(napi_env env,napi_value argValue,const std::string str,double & cValue)351 inline void SetDoubleValueFromJS(napi_env env, napi_value argValue, const std::string str, double& cValue)
352 {
353     napi_value tempValue = nullptr;
354     napi_get_named_property(env, argValue, str.c_str(), &tempValue);
355     if (tempValue == nullptr) {
356         return;
357     }
358     ConvertFromJsValue(env, tempValue, cValue);
359 }
360 
SetBoolValueFromJS(napi_env env,napi_value argValue,const std::string str,bool & cValue)361 inline void SetBoolValueFromJS(napi_env env, napi_value argValue, const std::string str, bool& cValue)
362 {
363     napi_value tempValue = nullptr;
364     napi_get_named_property(env, argValue, str.c_str(), &tempValue);
365     if (tempValue == nullptr) {
366         return;
367     }
368     ConvertFromJsValue(env, tempValue, cValue);
369 }
370 
GetPositionWithAffinityAndConvertToJsValue(napi_env env,IndexAndAffinity * positionWithAffinity)371 inline napi_value GetPositionWithAffinityAndConvertToJsValue(napi_env env,
372     IndexAndAffinity* positionWithAffinity)
373 {
374     napi_value objValue = nullptr;
375     napi_create_object(env, &objValue);
376     if (positionWithAffinity != nullptr && objValue != nullptr) {
377         napi_set_named_property(env, objValue, "position", CreateJsNumber(env, positionWithAffinity->index));
378         napi_set_named_property(env, objValue, "affinity", CreateJsNumber(env, (int)positionWithAffinity->affinity));
379     }
380     return objValue;
381 }
382 
GetRangeAndConvertToJsValue(napi_env env,Boundary * range)383 inline napi_value GetRangeAndConvertToJsValue(napi_env env, Boundary* range)
384 {
385     napi_value objValue = nullptr;
386     napi_create_object(env, &objValue);
387     if (range != nullptr && objValue != nullptr) {
388         napi_set_named_property(env, objValue, "start", CreateJsNumber(env, range->leftIndex));
389         napi_set_named_property(env, objValue, "end", CreateJsNumber(env, range->rightIndex));
390     }
391     return objValue;
392 }
393 
GetRectAndConvertToJsValue(napi_env env,Drawing::Rect rect)394 inline napi_value GetRectAndConvertToJsValue(napi_env env, Drawing::Rect rect)
395 {
396     napi_value objValue = nullptr;
397     napi_create_object(env, &objValue);
398     if (objValue != nullptr) {
399         napi_set_named_property(env, objValue, "left", CreateJsNumber(env, rect.GetLeft()));
400         napi_set_named_property(env, objValue, "top", CreateJsNumber(env, rect.GetTop()));
401         napi_set_named_property(env, objValue, "right", CreateJsNumber(env, rect.GetRight()));
402         napi_set_named_property(env, objValue, "bottom", CreateJsNumber(env, rect.GetBottom()));
403     }
404     return objValue;
405 }
406 
CreateTextRectJsValue(napi_env env,TextRect textrect)407 inline napi_value CreateTextRectJsValue(napi_env env, TextRect textrect)
408 {
409     napi_value objValue = nullptr;
410     napi_create_object(env, &objValue);
411     if (objValue != nullptr) {
412         napi_set_named_property(env, objValue, "rect", GetRectAndConvertToJsValue(env, textrect.rect));
413         napi_set_named_property(env, objValue, "direction", CreateJsNumber(env, (int)textrect.direction));
414     }
415     return objValue;
416 }
417 
CreateArrayStringJsValue(napi_env env,const std::vector<std::string> & vectorString)418 inline napi_value CreateArrayStringJsValue(napi_env env, const std::vector<std::string>& vectorString)
419 {
420     napi_value jsArray = nullptr;
421     if (napi_create_array_with_length(env, vectorString.size(), &jsArray) == napi_ok) {
422         size_t index = 0;
423         for (const auto& family : vectorString) {
424             napi_value jsString;
425             napi_create_string_utf8(env, family.c_str(), family.length(), &jsString);
426             napi_set_element(env, jsArray, index++, jsString);
427         }
428     }
429     return jsArray;
430 }
431 
CreateStringJsValue(napi_env env,std::u16string & u16String)432 inline napi_value CreateStringJsValue(napi_env env, std::u16string& u16String)
433 {
434     napi_value jsStr = nullptr;
435     napi_create_string_utf16(env, reinterpret_cast<const char16_t*>(u16String.c_str()), u16String.length(), &jsStr);
436     return jsStr;
437 }
438 
439 napi_value CreateTextStyleJsValue(napi_env env, TextStyle textStyle);
440 
441 napi_value CreateFontMetricsJsValue(napi_env env, Drawing::FontMetrics& fontMetrics);
442 
CreateRunMetricsJsValue(napi_env env,RunMetrics runMetrics)443 inline napi_value CreateRunMetricsJsValue(napi_env env, RunMetrics runMetrics)
444 {
445     napi_value objValue = nullptr;
446     napi_create_object(env, &objValue);
447     if (objValue != nullptr) {
448         napi_set_named_property(env, objValue, "textStyle", CreateTextStyleJsValue(env, *(runMetrics.textStyle)));
449         napi_set_named_property(env, objValue, "fontMetrics", CreateFontMetricsJsValue(env, runMetrics.fontMetrics));
450     }
451     return objValue;
452 }
453 
454 napi_value ConvertMapToNapiMap(napi_env env, const std::map<size_t, RunMetrics>& map);
455 
456 napi_value CreateLineMetricsJsValue(napi_env env, OHOS::Rosen::LineMetrics& lineMetrics);
457 
SetFontMetricsFloatValueFromJS(napi_env env,napi_value argValue,const std::string & str,float & cValue)458 inline void SetFontMetricsFloatValueFromJS(napi_env env, napi_value argValue, const std::string& str, float& cValue)
459 {
460     napi_value tempValue = nullptr;
461     napi_get_named_property(env, argValue, str.c_str(), &tempValue);
462     if (tempValue == nullptr) {
463         return;
464     }
465     double tempValuechild = 0.0;
466 
467     ConvertFromJsValue(env, tempValue, tempValuechild);
468     cValue = static_cast<float>(tempValuechild);
469 }
470 
SetLineMetricsDoubleValueFromJS(napi_env env,napi_value argValue,const std::string str,double & cValue)471 inline void SetLineMetricsDoubleValueFromJS(napi_env env, napi_value argValue, const std::string str, double& cValue)
472 {
473     napi_value tempValue = nullptr;
474     napi_get_named_property(env, argValue, str.c_str(), &tempValue);
475     if (tempValue == nullptr) {
476         return;
477     }
478     ConvertFromJsValue(env, tempValue, cValue);
479 }
480 
SetLineMetricsSizeTValueFromJS(napi_env env,napi_value argValue,const std::string str,size_t & cValue)481 inline void SetLineMetricsSizeTValueFromJS(napi_env env, napi_value argValue, const std::string str, size_t& cValue)
482 {
483     napi_value tempValue = nullptr;
484     napi_get_named_property(env, argValue, str.c_str(), &tempValue);
485     if (tempValue == nullptr) {
486         return;
487     }
488 
489     uint32_t tempValuechild = 0;
490     ConvertFromJsValue(env, tempValue, tempValuechild);
491     cValue = static_cast<size_t>(tempValuechild);
492 }
493 
494 bool OnMakeFontFamilies(napi_env& env, napi_value jsValue, std::vector<std::string> &fontFamilies);
495 
496 bool SetColorFromJS(napi_env env, napi_value argValue, const std::string& str, Drawing::Color& colorSrc);
497 
498 bool GetDecorationFromJS(napi_env env, napi_value argValue, TextStyle& textStyle);
499 
500 bool GetTextStyleFromJS(napi_env env, napi_value argValue, TextStyle& textStyle);
501 
502 bool GetParagraphStyleFromJS(napi_env env, napi_value argValue, TypographyStyle& pographyStyle);
503 
504 bool GetPlaceholderSpanFromJS(napi_env env, napi_value argValue, PlaceholderSpan& placeholderSpan);
505 
506 void ParsePartTextStyle(napi_env env, napi_value argValue, TextStyle& textStyle);
507 
508 void SetTextStyleBaseType(napi_env env, napi_value argValue, TextStyle& textStyle);
509 
510 void ReceiveFontFeature(napi_env env, napi_value argValue, TextStyle& textStyle);
511 
512 void ReceiveFontVariation(napi_env env, napi_value argValue, TextStyle& textStyle);
513 
514 size_t GetParamLen(napi_env env, napi_value param);
515 
516 bool GetFontMetricsFromJS(napi_env env, napi_value argValue, Drawing::FontMetrics& fontMetrics);
517 
518 bool GetRunMetricsFromJS(napi_env env, napi_value argValue, RunMetrics& runMetrics);
519 
520 bool GetNamePropertyFromJS(napi_env env, napi_value argValue, const std::string& str, napi_value& propertyValue);
521 
522 template<class Type>
SetEnumValueFromJS(napi_env env,napi_value argValue,const std::string str,Type & typeValue)523 void SetEnumValueFromJS(napi_env env, napi_value argValue, const std::string str, Type& typeValue)
524 {
525     napi_value propertyValue = nullptr;
526     if (!GetNamePropertyFromJS(env, argValue, str, propertyValue)) {
527         return;
528     }
529 
530     ConvertFromJsValue(env, propertyValue, typeValue);
531 }
532 
533 void ScanShadowValue(napi_env env, napi_value allShadowValue, uint32_t arrayLength, TextStyle& textStyle);
534 
535 void SetTextShadowProperty(napi_env env, napi_value argValue, TextStyle& textStyle);
536 
537 void SetStrutStyleFromJS(napi_env env, napi_value argValue, TypographyStyle& pographyStyle);
538 
539 void SetRectStyleFromJS(napi_env env, napi_value argValue, RectStyle& rectStyle);
540 } // namespace OHOS::Rosen
541 #endif // OHOS_JS_TEXT_UTILS_H