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 "napi_common.h"
17 
18 namespace OHOS::Rosen {
BindNativeFunction(napi_env env,napi_value object,const char * name,const char * moduleName,napi_callback func)19 void BindNativeFunction(napi_env env, napi_value object, const char* name, const char* moduleName, napi_callback func)
20 {
21     std::string fullName;
22     if (moduleName) {
23         fullName = moduleName;
24         fullName += '.';
25     }
26     fullName += name;
27     napi_value funcValue = nullptr;
28     napi_create_function(env, fullName.c_str(), fullName.size(), func, nullptr, &funcValue);
29     napi_set_named_property(env, object, fullName.c_str(), funcValue);
30 }
31 
CreateJsError(napi_env env,int32_t errCode,const std::string & message)32 napi_value CreateJsError(napi_env env, int32_t errCode, const std::string& message)
33 {
34     napi_value result = nullptr;
35     napi_create_error(env, CreateJsValue(env, errCode), CreateJsValue(env, message), &result);
36     return result;
37 }
38 
NapiThrowError(napi_env env,TextErrorCode err,const std::string & message)39 napi_value NapiThrowError(napi_env env, TextErrorCode err, const std::string& message)
40 {
41     napi_throw(env, CreateJsError(env, static_cast<int32_t>(err), message));
42     return NapiGetUndefined(env);
43 }
44 
OnMakeFontFamilies(napi_env & env,napi_value jsValue,std::vector<std::string> & fontFamilies)45 bool OnMakeFontFamilies(napi_env& env, napi_value jsValue, std::vector<std::string> &fontFamilies)
46 {
47     if (jsValue == nullptr) {
48         return false;
49     }
50     uint32_t size = 0;
51     napi_get_array_length(env, jsValue, &size);
52     if (size == 0) {
53         return false;
54     }
55     for (uint32_t i = 0; i < size; i++) {
56         napi_value tempStr = nullptr;
57         napi_get_element(env, jsValue, i, &tempStr);
58         std::string text = "";
59         if (ConvertFromJsValue(env, tempStr, text)) {
60             fontFamilies.push_back(text);
61         }
62     }
63     return true;
64 }
65 
SetColorFromJS(napi_env env,napi_value argValue,const std::string & str,Drawing::Color & colorSrc)66 bool SetColorFromJS(napi_env env, napi_value argValue, const std::string& str, Drawing::Color& colorSrc)
67 {
68     napi_value tempValue = nullptr;
69     napi_value tempValueChild = nullptr;
70     napi_get_named_property(env, argValue, str.c_str(), &tempValue);
71     if (tempValue == nullptr) {
72         return false;
73     }
74     int32_t alpha = 0;
75     int32_t red = 0;
76     int32_t green = 0;
77     int32_t blue = 0;
78     napi_get_named_property(env, tempValue, "alpha", &tempValueChild);
79     bool isAlphaOk = ConvertClampFromJsValue(env, tempValueChild, alpha, 0, Drawing::Color::RGB_MAX);
80     napi_get_named_property(env, tempValue, "red", &tempValueChild);
81     bool isRedOk = ConvertClampFromJsValue(env, tempValueChild, red, 0, Drawing::Color::RGB_MAX);
82     napi_get_named_property(env, tempValue, "green", &tempValueChild);
83     bool isGreenOk = ConvertClampFromJsValue(env, tempValueChild, green, 0, Drawing::Color::RGB_MAX);
84     napi_get_named_property(env, tempValue, "blue", &tempValueChild);
85     bool isBlueOk = ConvertClampFromJsValue(env, tempValueChild, blue, 0, Drawing::Color::RGB_MAX);
86     if (isAlphaOk && isRedOk && isGreenOk && isBlueOk) {
87         Drawing::Color color(Drawing::Color::ColorQuadSetARGB(alpha, red, green, blue));
88         colorSrc = color;
89         return true;
90     }
91     return false;
92 }
93 
GetDecorationFromJS(napi_env env,napi_value argValue,const std::string & str,TextStyle & textStyle)94 bool GetDecorationFromJS(napi_env env, napi_value argValue, const std::string& str, TextStyle& textStyle)
95 {
96     if (argValue == nullptr) {
97         return false;
98     }
99     napi_value tempValue = nullptr;
100     napi_get_named_property(env, argValue, str.c_str(), &tempValue);
101     if (tempValue == nullptr) {
102         return false;
103     }
104 
105     napi_value tempValueChild = nullptr;
106     napi_get_named_property(env, tempValue, "textDecoration", &tempValueChild);
107     uint32_t textDecoration = 0;
108     if (tempValueChild != nullptr && napi_get_value_uint32(env, tempValueChild, &textDecoration) == napi_ok) {
109         textStyle.decoration = TextDecoration(textDecoration);
110     }
111 
112     SetColorFromJS(env, tempValue, "color", textStyle.decorationColor);
113 
114     tempValueChild = nullptr;
115     napi_get_named_property(env, tempValue, "decorationStyle", &tempValueChild);
116     uint32_t decorationStyle = 0;
117     if (tempValueChild != nullptr && napi_get_value_uint32(env, tempValueChild, &decorationStyle) == napi_ok) {
118         textStyle.decorationStyle = TextDecorationStyle(decorationStyle);
119     }
120     SetDoubleValueFromJS(env, tempValue, "decorationThicknessScale", textStyle.decorationThicknessScale);
121     return true;
122 }
123 
GetNamePropertyFromJS(napi_env env,napi_value argValue,const std::string & str,napi_value & propertyValue)124 bool GetNamePropertyFromJS(napi_env env, napi_value argValue, const std::string& str, napi_value& propertyValue)
125 {
126     bool result = false;
127     if (napi_has_named_property(env, argValue, str.c_str(), &result) != napi_ok || (!result)) {
128         return false;
129     }
130 
131     if (napi_get_named_property(env, argValue, str.c_str(), &propertyValue) != napi_ok) {
132         return false;
133     }
134 
135     return true;
136 }
137 
ReceiveFontFeature(napi_env env,napi_value argValue,TextStyle & textStyle)138 void ReceiveFontFeature(napi_env env, napi_value argValue, TextStyle& textStyle)
139 {
140     napi_value allFeatureValue = nullptr;
141     napi_get_named_property(env, argValue, "fontFeatures", &allFeatureValue);
142     uint32_t arrayLength = 0;
143     if (napi_get_array_length(env, allFeatureValue, &arrayLength) != napi_ok ||
144         !arrayLength) {
145         TEXT_LOGE("The parameter of font features is unvaild");
146         return;
147     }
148 
149     for (uint32_t further = 0; further < arrayLength; further++) {
150         napi_value singleElementValue;
151         if (napi_get_element(env, allFeatureValue, further, &singleElementValue) != napi_ok) {
152             TEXT_LOGE("This parameter of the font features is unvaild");
153             break;
154         }
155         napi_value featureElement;
156         std::string name;
157         if (napi_get_named_property(env, singleElementValue, "name", &featureElement) != napi_ok ||
158             !ConvertFromJsValue(env, featureElement, name)) {
159             TEXT_LOGE("This time that the name of parameter in font features is unvaild");
160             break;
161         }
162 
163         int value = 0;
164         if (napi_get_named_property(env, singleElementValue, "value", &featureElement) != napi_ok ||
165             !ConvertFromJsValue(env, featureElement, value)) {
166             TEXT_LOGE("This time that the value of parameter in font features is unvaild");
167             break;
168         }
169         textStyle.fontFeatures.SetFeature(name, value);
170     }
171     return;
172 }
173 
ReceiveFontVariation(napi_env env,napi_value argValue,TextStyle & textStyle)174 void ReceiveFontVariation(napi_env env, napi_value argValue, TextStyle& textStyle)
175 {
176     napi_value allVariationValue = nullptr;
177     napi_get_named_property(env, argValue, "fontVariations", &allVariationValue);
178     uint32_t arrayLength = 0;
179     if (napi_get_array_length(env, allVariationValue, &arrayLength) != napi_ok ||
180         !arrayLength) {
181         TEXT_LOGE("The parameter of font variations is unvaild");
182         return;
183     }
184 
185     for (uint32_t further = 0; further < arrayLength; further++) {
186         napi_value singleElementValue;
187         if (napi_get_element(env, allVariationValue, further, &singleElementValue) != napi_ok) {
188             TEXT_LOGE("This parameter of the font variations is unvaild");
189             break;
190         }
191         napi_value variationElement;
192         std::string axis;
193         if (napi_get_named_property(env, singleElementValue, "axis", &variationElement) != napi_ok ||
194             !ConvertFromJsValue(env, variationElement, axis)) {
195             TEXT_LOGE("This time that the axis of parameter in font variations is unvaild");
196             break;
197         }
198 
199         int value = 0;
200         if (napi_get_named_property(env, singleElementValue, "value", &variationElement) != napi_ok ||
201             !ConvertFromJsValue(env, variationElement, value)) {
202             TEXT_LOGE("This time that the value of parameter in font variations is unvaild");
203             break;
204         }
205         textStyle.fontVariations.SetAxisValue(axis, value);
206     }
207     return;
208 }
209 
SetTextStyleBaseType(napi_env env,napi_value argValue,TextStyle & textStyle)210 void SetTextStyleBaseType(napi_env env, napi_value argValue, TextStyle& textStyle)
211 {
212     SetDoubleValueFromJS(env, argValue, "letterSpacing", textStyle.letterSpacing);
213     SetDoubleValueFromJS(env, argValue, "wordSpacing", textStyle.wordSpacing);
214     SetDoubleValueFromJS(env, argValue, "baselineShift", textStyle.baseLineShift);
215     SetDoubleValueFromJS(env, argValue, "heightScale", textStyle.heightScale);
216     SetBoolValueFromJS(env, argValue, "halfLeading", textStyle.halfLeading);
217     SetBoolValueFromJS(env, argValue, "heightOnly", textStyle.heightOnly);
218 
219     textStyle.heightScale = textStyle.heightScale < 0 ? 0 : textStyle.heightScale;
220 }
221 
ScanShadowValue(napi_env env,napi_value allShadowValue,uint32_t arrayLength,TextStyle & textStyle)222 void ScanShadowValue(napi_env env, napi_value allShadowValue, uint32_t arrayLength, TextStyle& textStyle)
223 {
224     textStyle.shadows.clear();
225     for (uint32_t further = 0; further < arrayLength; further++) {
226         napi_value element;
227         Drawing::Color colorSrc = OHOS::Rosen::Drawing::Color::COLOR_BLACK;
228         Drawing::Point offset(0, 0);
229         double runTimeRadius = 0;
230         if (napi_get_element(env, allShadowValue, further, &element) != napi_ok) {
231             TEXT_LOGE("The parameter of as private text-shadow is unvaild");
232             return;
233         }
234         SetColorFromJS(env, element, "color", colorSrc);
235 
236         napi_value pointValue = nullptr;
237         if (napi_get_named_property(env, element, "point", &pointValue) != napi_ok) {
238             TEXT_LOGE("The parameter of as private point is unvaild");
239             return;
240         }
241         GetPointFromJsValue(env, pointValue, offset);
242 
243         napi_value radius = nullptr;
244         if (napi_get_named_property(env, element, "blurRadius", &radius) != napi_ok ||
245             napi_get_value_double(env, radius, &runTimeRadius) != napi_ok) {
246             TEXT_LOGE("The parameter of as private blur radius is unvaild");
247             return;
248         }
249         textStyle.shadows.emplace_back(TextShadow(colorSrc, offset, runTimeRadius));
250     }
251     return;
252 }
253 
SetTextShadowProperty(napi_env env,napi_value argValue,TextStyle & textStyle)254 void SetTextShadowProperty(napi_env env, napi_value argValue, TextStyle& textStyle)
255 {
256     napi_value allShadowValue = nullptr;
257     if (!GetNamePropertyFromJS(env, argValue, "textShadows", allShadowValue)) {
258         return;
259     }
260 
261     uint32_t arrayLength = 0;
262     if (napi_get_array_length(env, allShadowValue, &arrayLength) != napi_ok) {
263         TEXT_LOGE("The parameter of text shadow is not array");
264         return;
265     }
266     ScanShadowValue(env, allShadowValue, arrayLength, textStyle);
267     return;
268 }
269 
ParsePartTextStyle(napi_env env,napi_value argValue,TextStyle & textStyle)270 void ParsePartTextStyle(napi_env env, napi_value argValue, TextStyle& textStyle)
271 {
272     napi_value tempValue = nullptr;
273     napi_get_named_property(env, argValue, "fontWeight", &tempValue);
274     uint32_t fontWeight = 0;
275     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &fontWeight) == napi_ok) {
276         textStyle.fontWeight = FontWeight(fontWeight);
277     }
278     napi_get_named_property(env, argValue, "fontStyle", &tempValue);
279     uint32_t fontStyle = 0;
280     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &fontStyle) == napi_ok) {
281         textStyle.fontStyle = FontStyle(fontStyle);
282 
283         // Let OBLIQUE be equal to ITALIC, it's a temp modify.
284         if (textStyle.fontStyle == FontStyle::OBLIQUE) {
285             textStyle.fontStyle = FontStyle::ITALIC;
286         }
287     }
288     napi_get_named_property(env, argValue, "baseline", &tempValue);
289     uint32_t baseline = 0;
290     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &baseline) == napi_ok) {
291         textStyle.baseline = TextBaseline(baseline);
292     }
293     SetDoubleValueFromJS(env, argValue, "fontSize", textStyle.fontSize);
294 
295     std::vector<std::string> fontFamilies;
296     napi_get_named_property(env, argValue, "fontFamilies", &tempValue);
297     if (tempValue != nullptr && OnMakeFontFamilies(env, tempValue, fontFamilies)) {
298         textStyle.fontFamilies = fontFamilies;
299     }
300     GetDecorationFromJS(env, argValue, "decoration", textStyle);
301     SetTextStyleBaseType(env, argValue, textStyle);
302     ReceiveFontFeature(env, argValue, textStyle);
303     ReceiveFontVariation(env, argValue, textStyle);
304     napi_get_named_property(env, argValue, "ellipsis", &tempValue);
305     std::string text = "";
306     if (tempValue != nullptr && ConvertFromJsValue(env, tempValue, text)) {
307         textStyle.ellipsis = Str8ToStr16(text);
308     }
309     napi_get_named_property(env, argValue, "ellipsisMode", &tempValue);
310     uint32_t ellipsisModal = 0;
311     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &ellipsisModal)== napi_ok) {
312         textStyle.ellipsisModal = EllipsisModal(ellipsisModal);
313     }
314     napi_get_named_property(env, argValue, "locale", &tempValue);
315     std::string textLocale = "";
316     if (tempValue != nullptr && ConvertFromJsValue(env, tempValue, textLocale)) {
317         textStyle.locale = textLocale;
318     }
319 }
320 
GetTextStyleFromJS(napi_env env,napi_value argValue,TextStyle & textStyle)321 bool GetTextStyleFromJS(napi_env env, napi_value argValue, TextStyle& textStyle)
322 {
323     napi_valuetype valueType = napi_undefined;
324     if (argValue == nullptr || napi_typeof(env, argValue, &valueType) != napi_ok || valueType != napi_object) {
325         return false;
326     }
327     SetColorFromJS(env, argValue, "color", textStyle.color);
328     ParsePartTextStyle(env, argValue, textStyle);
329     SetTextShadowProperty(env, argValue, textStyle);
330     SetRectStyleFromJS(env, argValue, textStyle.backgroundRect);
331     return true;
332 }
333 
GetParagraphStyleFromJS(napi_env env,napi_value argValue,TypographyStyle & pographyStyle)334 bool GetParagraphStyleFromJS(napi_env env, napi_value argValue, TypographyStyle& pographyStyle)
335 {
336     if (argValue == nullptr) {
337         return false;
338     }
339     napi_value tempValue = nullptr;
340     napi_get_named_property(env, argValue, "textStyle", &tempValue);
341     TextStyle textStyle;
342     if (tempValue != nullptr && GetTextStyleFromJS(env, tempValue, textStyle)) {
343         pographyStyle.SetTextStyle(textStyle);
344     }
345     tempValue = nullptr;
346     napi_get_named_property(env, argValue, "textDirection", &tempValue);
347     uint32_t textDirection = 0;
348     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &textDirection) == napi_ok) {
349         pographyStyle.textDirection = TextDirection(textDirection);
350     }
351     tempValue = nullptr;
352     napi_get_named_property(env, argValue, "align", &tempValue);
353     uint32_t align = 0;
354     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &align) == napi_ok) {
355         pographyStyle.textAlign = TextAlign(align);
356     }
357     tempValue = nullptr;
358     napi_get_named_property(env, argValue, "wordBreak", &tempValue);
359     uint32_t wordBreak = 0;
360     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &wordBreak) == napi_ok) {
361         pographyStyle.wordBreakType = WordBreakType(wordBreak);
362     }
363     tempValue = nullptr;
364     napi_get_named_property(env, argValue, "maxLines", &tempValue);
365     int64_t maxLines = 0;
366     if (tempValue != nullptr && napi_get_value_int64(env, tempValue, &maxLines) == napi_ok) {
367         pographyStyle.maxLines = maxLines < 0 ? 0 : maxLines;
368     }
369     tempValue = nullptr;
370     napi_get_named_property(env, argValue, "breakStrategy", &tempValue);
371     uint32_t breakStrategy = 0;
372     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &breakStrategy) == napi_ok) {
373         pographyStyle.breakStrategy = BreakStrategy(breakStrategy);
374     }
375 
376     napi_value strutStyleValue = nullptr;
377     if (GetNamePropertyFromJS(env, argValue, "strutStyle", strutStyleValue)) {
378         SetStrutStyleFromJS(env, strutStyleValue, pographyStyle);
379     }
380 
381     pographyStyle.ellipsis = textStyle.ellipsis;
382     pographyStyle.ellipsisModal = textStyle.ellipsisModal;
383 
384     SetEnumValueFromJS(env, argValue, "textHeightBehavior", pographyStyle.textHeightBehavior);
385 
386     return true;
387 }
388 
GetPlaceholderSpanFromJS(napi_env env,napi_value argValue,PlaceholderSpan & placeholderSpan)389 bool GetPlaceholderSpanFromJS(napi_env env, napi_value argValue, PlaceholderSpan& placeholderSpan)
390 {
391     if (argValue == nullptr) {
392         return false;
393     }
394     napi_value tempValue = nullptr;
395     napi_get_named_property(env, argValue, "width", &tempValue);
396     double width = 0;
397     if (tempValue != nullptr && napi_get_value_double(env, tempValue, &width) == napi_ok) {
398         placeholderSpan.width = width;
399     } else {
400         return false;
401     }
402     tempValue = nullptr;
403     napi_get_named_property(env, argValue, "height", &tempValue);
404     double height = 0;
405     if (tempValue != nullptr && napi_get_value_double(env, tempValue, &height) == napi_ok) {
406         placeholderSpan.height = height;
407     } else {
408         return false;
409     }
410     tempValue = nullptr;
411     napi_get_named_property(env, argValue, "align", &tempValue);
412     uint32_t align = 0;
413     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &align) == napi_ok) {
414         placeholderSpan.alignment = PlaceholderVerticalAlignment(align);
415     } else {
416         return false;
417     }
418     tempValue = nullptr;
419     napi_get_named_property(env, argValue, "baseline", &tempValue);
420     uint32_t baseline = 0;
421     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &baseline) == napi_ok) {
422         placeholderSpan.baseline = TextBaseline(baseline);
423     } else {
424         return false;
425     }
426     tempValue = nullptr;
427     napi_get_named_property(env, argValue, "baselineOffset", &tempValue);
428     double baselineOffset = 0;
429     if (tempValue != nullptr && napi_get_value_double(env, tempValue, &baselineOffset) == napi_ok) {
430         placeholderSpan.baselineOffset = baselineOffset;
431     } else {
432         return false;
433     }
434     return true;
435 }
436 
GetParamLen(napi_env env,napi_value param)437 size_t GetParamLen(napi_env env, napi_value param)
438 {
439     size_t buffSize = 0;
440     napi_status status = napi_get_value_string_utf8(env, param, nullptr, 0, &buffSize);
441     if (status != napi_ok || buffSize == 0) {
442         return 0;
443     }
444     return buffSize;
445 }
446 
GetFontMetricsFromJS(napi_env env,napi_value argValue,Drawing::FontMetrics & fontMetrics)447 bool GetFontMetricsFromJS(napi_env env, napi_value argValue, Drawing::FontMetrics& fontMetrics)
448 {
449     if (argValue == nullptr) {
450         return false;
451     }
452     napi_value tempValue = nullptr;
453     napi_get_named_property(env, argValue, "flags", &tempValue);
454     uint32_t flags = 0;
455     if (tempValue != nullptr && napi_get_value_uint32(env, tempValue, &flags) == napi_ok) {
456         fontMetrics.fFlags = Drawing::FontMetrics::FontMetricsFlags(flags);
457     }
458     SetFontMetricsFloatValueFromJS(env, argValue, "top", fontMetrics.fTop);
459     SetFontMetricsFloatValueFromJS(env, argValue, "ascent", fontMetrics.fAscent);
460     SetFontMetricsFloatValueFromJS(env, argValue, "descent", fontMetrics.fDescent);
461     SetFontMetricsFloatValueFromJS(env, argValue, "bottom", fontMetrics.fBottom);
462     SetFontMetricsFloatValueFromJS(env, argValue, "leading", fontMetrics.fLeading);
463     SetFontMetricsFloatValueFromJS(env, argValue, "avgCharWidth", fontMetrics.fAvgCharWidth);
464     SetFontMetricsFloatValueFromJS(env, argValue, "maxCharWidth", fontMetrics.fMaxCharWidth);
465     SetFontMetricsFloatValueFromJS(env, argValue, "xMin", fontMetrics.fXMin);
466     SetFontMetricsFloatValueFromJS(env, argValue, "xMax", fontMetrics.fXMax);
467     SetFontMetricsFloatValueFromJS(env, argValue, "xHeight", fontMetrics.fXHeight);
468     SetFontMetricsFloatValueFromJS(env, argValue, "capHeight", fontMetrics.fCapHeight);
469     SetFontMetricsFloatValueFromJS(env, argValue, "underlineThickness", fontMetrics.fUnderlineThickness);
470     SetFontMetricsFloatValueFromJS(env, argValue, "underlinePosition", fontMetrics.fUnderlinePosition);
471     SetFontMetricsFloatValueFromJS(env, argValue, "strikethroughThickness", fontMetrics.fStrikeoutThickness);
472     SetFontMetricsFloatValueFromJS(env, argValue, "strikethroughPosition", fontMetrics.fStrikeoutPosition);
473     return true;
474 }
475 
GetRunMetricsFromJS(napi_env env,napi_value argValue,RunMetrics & runMetrics)476 bool GetRunMetricsFromJS(napi_env env, napi_value argValue, RunMetrics& runMetrics)
477 {
478     if (argValue == nullptr) {
479         return false;
480     }
481     napi_value tempValue = nullptr;
482     napi_get_named_property(env, argValue, "textStyle", &tempValue);
483     OHOS::Rosen::TextStyle tempTextStyle;
484     if (tempValue != nullptr && GetTextStyleFromJS(env, tempValue, tempTextStyle)) {
485         runMetrics.textStyle = &tempTextStyle;
486     }
487 
488     napi_get_named_property(env, argValue, "fontMetrics", &tempValue);
489     Drawing::FontMetrics tempFontMetrics;
490     if (tempValue != nullptr && GetFontMetricsFromJS(env, tempValue, tempFontMetrics)) {
491         runMetrics.fontMetrics = tempFontMetrics;
492     }
493     return true;
494 }
495 
SetStrutStyleFromJS(napi_env env,napi_value strutStyleValue,TypographyStyle & typographyStyle)496 bool SetStrutStyleFromJS(napi_env env, napi_value strutStyleValue, TypographyStyle& typographyStyle)
497 {
498     napi_valuetype valueType = napi_undefined;
499     if (strutStyleValue == nullptr || napi_typeof(env, strutStyleValue, &valueType) != napi_ok ||
500         valueType != napi_object) {
501         TEXT_LOGE("Invalid strut style value");
502         return false;
503     }
504 
505     napi_value tempValue = nullptr;
506     if (GetNamePropertyFromJS(env, strutStyleValue, "fontFamilies", tempValue)) {
507         std::vector<std::string> fontFamilies;
508         if (tempValue != nullptr && OnMakeFontFamilies(env, tempValue, fontFamilies)) {
509             typographyStyle.lineStyleFontFamilies = fontFamilies;
510         }
511     }
512 
513     SetEnumValueFromJS(env, strutStyleValue, "fontStyle", typographyStyle.lineStyleFontStyle);
514     SetEnumValueFromJS(env, strutStyleValue, "fontWidth", typographyStyle.lineStyleFontWidth);
515     SetEnumValueFromJS(env, strutStyleValue, "fontWeight", typographyStyle.lineStyleFontWeight);
516 
517     SetDoubleValueFromJS(env, strutStyleValue, "fontSize", typographyStyle.lineStyleFontSize);
518     SetDoubleValueFromJS(env, strutStyleValue, "height", typographyStyle.lineStyleHeightScale);
519     SetDoubleValueFromJS(env, strutStyleValue, "leading", typographyStyle.lineStyleSpacingScale);
520 
521     SetBoolValueFromJS(env, strutStyleValue, "forceHeight", typographyStyle.lineStyleOnly);
522     SetBoolValueFromJS(env, strutStyleValue, "enabled", typographyStyle.useLineStyle);
523     SetBoolValueFromJS(env, strutStyleValue, "heightOverride", typographyStyle.lineStyleHeightOnly);
524     SetBoolValueFromJS(env, strutStyleValue, "halfLeading", typographyStyle.lineStyleHalfLeading);
525     return true;
526 }
527 
SetRectStyleFromJS(napi_env env,napi_value argValue,RectStyle & rectStyle)528 void SetRectStyleFromJS(napi_env env, napi_value argValue, RectStyle& rectStyle)
529 {
530     if (!argValue) {
531         return;
532     }
533 
534     napi_value tempValue = nullptr;
535     if (!GetNamePropertyFromJS(env, argValue, "backgroundRect", tempValue)) {
536         return;
537     }
538 
539     Drawing::Color color;
540     SetColorFromJS(env, tempValue, "color", color);
541     rectStyle.color = color.CastToColorQuad();
542     SetDoubleValueFromJS(env, tempValue, "leftTopRadius", rectStyle.leftTopRadius);
543     SetDoubleValueFromJS(env, tempValue, "rightTopRadius", rectStyle.rightTopRadius);
544     SetDoubleValueFromJS(env, tempValue, "rightBottomRadius", rectStyle.rightBottomRadius);
545     SetDoubleValueFromJS(env, tempValue, "leftBottomRadius", rectStyle.leftBottomRadius);
546 }
547 
CreateLineMetricsJsValue(napi_env env,OHOS::Rosen::LineMetrics & lineMetrics)548 napi_value CreateLineMetricsJsValue(napi_env env, OHOS::Rosen::LineMetrics& lineMetrics)
549 {
550     napi_value objValue = nullptr;
551     napi_create_object(env, &objValue);
552     if (objValue != nullptr) {
553         napi_set_named_property(env, objValue, "startIndex", CreateJsNumber(env, (uint32_t)lineMetrics.startIndex));
554         napi_set_named_property(env, objValue, "endIndex", CreateJsNumber(env, (uint32_t)lineMetrics.endIndex));
555         napi_set_named_property(env, objValue, "ascent", CreateJsNumber(env, lineMetrics.ascender));
556         napi_set_named_property(env, objValue, "descent", CreateJsNumber(env, lineMetrics.descender));
557         napi_set_named_property(env, objValue, "height", CreateJsNumber(env, lineMetrics.height));
558         napi_set_named_property(env, objValue, "width", CreateJsNumber(env, lineMetrics.width));
559         napi_set_named_property(env, objValue, "left", CreateJsNumber(env, lineMetrics.x));
560         napi_set_named_property(env, objValue, "baseline", CreateJsNumber(env, lineMetrics.baseline));
561         napi_set_named_property(env, objValue, "lineNumber", CreateJsNumber(env, lineMetrics.lineNumber));
562         napi_set_named_property(env, objValue, "topHeight", CreateJsNumber(env, lineMetrics.y));
563         napi_set_named_property(env, objValue, "runMetrics", ConvertMapToNapiMap(env, lineMetrics.runMetrics));
564     }
565     return objValue;
566 }
567 
CreateTextStyleJsValue(napi_env env,TextStyle textStyle)568 napi_value CreateTextStyleJsValue(napi_env env, TextStyle textStyle)
569 {
570     napi_value objValue = nullptr;
571     napi_create_object(env, &objValue);
572     if (objValue != nullptr) {
573         napi_set_named_property(env, objValue, "decoration", CreateJsNumber(
574             env, static_cast<uint32_t>(textStyle.decoration)));
575         napi_set_named_property(env, objValue, "color", CreateJsNumber(env,
576             (uint32_t)textStyle.color.CastToColorQuad()));
577         napi_set_named_property(env, objValue, "fontWeight", CreateJsNumber(
578             env, static_cast<uint32_t>(textStyle.fontWeight)));
579         napi_set_named_property(env, objValue, "fontStyle", CreateJsNumber(
580             env, static_cast<uint32_t>(textStyle.fontStyle)));
581         napi_set_named_property(env, objValue, "baseline", CreateJsNumber(
582             env, static_cast<uint32_t>(textStyle.baseline)));
583         napi_set_named_property(env, objValue, "fontFamilies", CreateArrayStringJsValue(env, textStyle.fontFamilies));
584         napi_set_named_property(env, objValue, "fontSize", CreateJsNumber(env, textStyle.fontSize));
585         napi_set_named_property(env, objValue, "letterSpacing", CreateJsNumber(env, textStyle.letterSpacing));
586         napi_set_named_property(env, objValue, "wordSpacing", CreateJsNumber(env, textStyle.wordSpacing));
587         napi_set_named_property(env, objValue, "heightScale", CreateJsNumber(env, textStyle.heightScale));
588         napi_set_named_property(env, objValue, "halfLeading", CreateJsValue(env, textStyle.halfLeading));
589         napi_set_named_property(env, objValue, "heightOnly", CreateJsValue(env, textStyle.heightOnly));
590         napi_set_named_property(env, objValue, "ellipsis", CreateStringJsValue(env, textStyle.ellipsis));
591         napi_set_named_property(env, objValue, "ellipsisMode", CreateJsNumber(
592             env, static_cast<uint32_t>(textStyle.ellipsisModal)));
593         napi_set_named_property(env, objValue, "locale", CreateJsValue(env, textStyle.locale));
594     }
595     return objValue;
596 }
597 
598 struct NapiMap {
599     napi_value instance;
600     napi_value set_function;
601 };
602 
CreateNapiMap(napi_env env)603 static NapiMap CreateNapiMap(napi_env env)
604 {
605     NapiMap res = {nullptr, nullptr};
606     napi_valuetype value_type;
607 
608     napi_value global = nullptr;
609     if (napi_get_global(env, &global) != napi_ok || !global) {
610         return res;
611     }
612 
613     napi_value constructor = nullptr;
614     if (napi_get_named_property(env, global, "Map", &constructor) != napi_ok || !constructor) {
615         return res;
616     }
617 
618     if (napi_typeof(env, constructor, &value_type) != napi_ok || value_type != napi_valuetype::napi_function) {
619         return res;
620     }
621 
622     napi_value map_instance = nullptr;
623     if (napi_new_instance(env, constructor, 0, nullptr, &map_instance) != napi_ok || !map_instance) {
624         return res;
625     }
626 
627     napi_value map_set = nullptr;
628     if (napi_get_named_property(env, map_instance, "set", &map_set) != napi_ok || !map_set) {
629         return res;
630     }
631     if (napi_typeof(env, map_set, &value_type) != napi_ok || value_type != napi_valuetype::napi_function) {
632         return res;
633     }
634 
635     res.instance = map_instance;
636     res.set_function = map_set;
637 
638     return res;
639 }
640 
NapiMapSet(napi_env env,NapiMap & map,uint32_t key,const RunMetrics & runMetrics)641 static bool NapiMapSet(napi_env env, NapiMap& map, uint32_t key, const RunMetrics& runMetrics)
642 {
643     napi_value keyValue = nullptr;
644     keyValue = CreateJsNumber(env, key);
645     napi_value runMetricsValue = nullptr;
646     runMetricsValue = CreateRunMetricsJsValue(env, runMetrics);
647     if (!keyValue || !runMetricsValue) {
648         return false;
649     }
650     napi_value args[2] = {keyValue, runMetricsValue};
651     napi_status status = napi_call_function(env, map.instance, map.set_function, 2, args, nullptr);
652     if (status != napi_ok) {
653         return false;
654     }
655     return true;
656 }
657 
ConvertMapToNapiMap(napi_env env,const std::map<size_t,RunMetrics> & map)658 napi_value ConvertMapToNapiMap(napi_env env, const std::map<size_t, RunMetrics>& map)
659 {
660     auto mapReturn = CreateNapiMap(env);
661     for (const auto &[key, val] : map) {
662         NapiMapSet(env, mapReturn, static_cast<uint32_t>(key), val);
663     }
664     return mapReturn.instance;
665 }
666 
CreateFontMetricsJsValue(napi_env env,Drawing::FontMetrics & fontMetrics)667 napi_value CreateFontMetricsJsValue(napi_env env, Drawing::FontMetrics& fontMetrics)
668 {
669     napi_value objValue = nullptr;
670     napi_create_object(env, &objValue);
671     if (objValue != nullptr) {
672         napi_set_named_property(env, objValue, "flags", CreateJsNumber(env, fontMetrics.fFlags));
673         napi_set_named_property(env, objValue, "top", CreateJsNumber(env, fontMetrics.fTop)); // float type
674         napi_set_named_property(env, objValue, "ascent", CreateJsNumber(env, fontMetrics.fAscent));
675         napi_set_named_property(env, objValue, "descent", CreateJsNumber(env, fontMetrics.fDescent));
676         napi_set_named_property(env, objValue, "bottom", CreateJsNumber(env, fontMetrics.fBottom));
677         napi_set_named_property(env, objValue, "leading", CreateJsNumber(env, fontMetrics.fLeading));
678         napi_set_named_property(env, objValue, "avgCharWidth", CreateJsNumber(env, fontMetrics.fAvgCharWidth));
679         napi_set_named_property(env, objValue, "maxCharWidth", CreateJsNumber(env, fontMetrics.fMaxCharWidth));
680         napi_set_named_property(env, objValue, "xMin", CreateJsNumber(env, fontMetrics.fXMin));
681         napi_set_named_property(env, objValue, "xMax", CreateJsNumber(env, fontMetrics.fXMax));
682         napi_set_named_property(env, objValue, "xHeight", CreateJsNumber(env, fontMetrics.fXHeight));
683         napi_set_named_property(env, objValue, "capHeight", CreateJsNumber(env, fontMetrics.fCapHeight));
684         napi_set_named_property(env, objValue, "underlineThickness", CreateJsNumber(env,
685             fontMetrics.fUnderlineThickness));
686         napi_set_named_property(env, objValue, "underlinePosition", CreateJsNumber(env,
687             fontMetrics.fUnderlinePosition));
688         napi_set_named_property(env, objValue, "strikethroughThickness", CreateJsNumber(env,
689             fontMetrics.fStrikeoutThickness));
690         napi_set_named_property(env, objValue, "strikethroughPosition", CreateJsNumber(env,
691             fontMetrics.fStrikeoutPosition));
692     }
693     return objValue;
694 }
695 } // namespace OHOS::Rosen
696