• 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 #include "frameworks/bridge/declarative_frontend/style_string/js_span_object.h"
17 
18 #include <numeric>
19 #include <string>
20 
21 #include "canvas_napi/js_canvas.h"
22 
23 #include "base/geometry/calc_dimension.h"
24 #include "base/geometry/dimension.h"
25 #include "base/log/ace_scoring_log.h"
26 #include "base/memory/ace_type.h"
27 #include "bridge/common/utils/engine_helper.h"
28 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
29 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_frame_node_bridge.h"
30 #include "bridge/declarative_frontend/engine/js_converter.h"
31 #include "bridge/declarative_frontend/engine/js_types.h"
32 #include "bridge/declarative_frontend/jsview/js_richeditor.h"
33 #include "bridge/declarative_frontend/jsview/js_utils.h"
34 #include "core/components/common/layout/constants.h"
35 #include "core/components/common/properties/text_style.h"
36 #include "core/components/text/text_theme.h"
37 #include "core/components/text_field/textfield_theme.h"
38 #include "core/components_ng/pattern/text/span/span_object.h"
39 #include "core/components_ng/pattern/text/span/span_string.h"
40 #include "core/components_ng/render/paragraph.h"
41 #include "frameworks/bridge/common/utils/utils.h"
42 #include "frameworks/bridge/declarative_frontend/jsview/js_container_span.h"
43 #include "frameworks/bridge/declarative_frontend/jsview/js_image.h"
44 #include "frameworks/bridge/declarative_frontend/jsview/js_container_span.h"
45 #include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h"
46 
47 namespace OHOS::Ace::Framework {
48 namespace {
49 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END, TextAlign::JUSTIFY };
50 const std::vector<TextVerticalAlign> TEXT_VERTICAL_ALIGNS = {
51     TextVerticalAlign::BASELINE, TextVerticalAlign::BOTTOM, TextVerticalAlign::CENTER, TextVerticalAlign::TOP };
52 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
53     TextOverflow::MARQUEE };
54 const int32_t WORD_BREAK_TYPES_DEFAULT = 2;
55 const std::vector<float> DEFAULT_COLORFILTER_MATRIX = {
56     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
57     0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f
58 };
59 } // namespace
60 
ParseLengthMetrics(const JSRef<JSObject> & obj,bool withoutPercent=true)61 CalcDimension ParseLengthMetrics(const JSRef<JSObject>& obj, bool withoutPercent = true)
62 {
63     auto value = 0.0;
64     auto valueObj = obj->GetProperty("value");
65     if (!valueObj->IsNull() && valueObj->IsNumber()) {
66         value = valueObj->ToNumber<float>();
67     }
68     auto unit = DimensionUnit::VP;
69     auto unitObj = obj->GetProperty("unit");
70     if (!unitObj->IsNull() && unitObj->IsNumber()) {
71         unit = static_cast<DimensionUnit>(unitObj->ToNumber<int32_t>());
72     }
73     CalcDimension size = CalcDimension(value, unit);
74     if (withoutPercent && unit == DimensionUnit::PERCENT) {
75         size = CalcDimension(0, DimensionUnit::VP);
76     }
77     return size;
78 }
79 
JSBind(BindingTarget globalObj)80 void JSFontSpan::JSBind(BindingTarget globalObj)
81 {
82     JSClass<JSFontSpan>::Declare("TextStyle");
83     JSClass<JSFontSpan>::CustomProperty("fontColor", &JSFontSpan::GetFontColor, &JSFontSpan::SetFontColor);
84     JSClass<JSFontSpan>::CustomProperty("fontSize", &JSFontSpan::GetFontSize, &JSFontSpan::SetFontSize);
85     JSClass<JSFontSpan>::CustomProperty("fontStyle", &JSFontSpan::GetFontStyle, &JSFontSpan::SetFontStyle);
86     JSClass<JSFontSpan>::CustomProperty("fontWeight", &JSFontSpan::GetFontWeight, &JSFontSpan::SetFontWeight);
87     JSClass<JSFontSpan>::CustomProperty("fontFamily", &JSFontSpan::GetFontFamily, &JSFontSpan::SetFontFamily);
88     JSClass<JSFontSpan>::CustomProperty("strokeWidth", &JSFontSpan::GetStrokeWidth, &JSFontSpan::SetStrokeWidth);
89     JSClass<JSFontSpan>::CustomProperty("strokeColor", &JSFontSpan::GetStrokeColor, &JSFontSpan::SetStrokeColor);
90     JSClass<JSFontSpan>::CustomProperty("superscript", &JSFontSpan::GetSuperscript, &JSFontSpan::SetSuperscript);
91     JSClass<JSFontSpan>::Bind(globalObj, JSFontSpan::Constructor, JSFontSpan::Destructor);
92 }
93 
Constructor(const JSCallbackInfo & args)94 void JSFontSpan::Constructor(const JSCallbackInfo& args)
95 {
96     auto fontSpan = Referenced::MakeRefPtr<JSFontSpan>();
97     fontSpan->IncRefCount();
98 
99     RefPtr<FontSpan> span;
100     if (args.Length() <= 0) {
101         Font font;
102         span = AceType::MakeRefPtr<FontSpan>(font);
103     } else {
104         if (!args[0]->IsObject()) {
105             return;
106         }
107         span = JSFontSpan::ParseJsFontSpan(JSRef<JSObject>::Cast(args[0]));
108     }
109     fontSpan->fontSpan_ = span;
110     args.SetReturnValue(Referenced::RawPtr(fontSpan));
111 }
112 
Destructor(JSFontSpan * fontSpan)113 void JSFontSpan::Destructor(JSFontSpan* fontSpan)
114 {
115     if (fontSpan != nullptr) {
116         fontSpan->DecRefCount();
117     }
118 }
119 
ParseJsFontSpan(const JSRef<JSObject> & obj)120 RefPtr<FontSpan> JSFontSpan::ParseJsFontSpan(const JSRef<JSObject>& obj)
121 {
122     Font font;
123     ParseJsFontColor(obj, font);
124     ParseJsFontSize(obj, font);
125     ParseJsFontWeight(obj, font);
126     ParseJsFontFamily(obj, font);
127     ParseJsFontStyle(obj, font);
128     ParseJsStrokeWidth(obj, font);
129     ParseJsStrokeColor(obj, font);
130     ParseJsSuperscript(obj, font);
131     return AceType::MakeRefPtr<FontSpan>(font);
132 }
133 
ParseJsFontColor(const JSRef<JSObject> & obj,Font & font)134 void JSFontSpan::ParseJsFontColor(const JSRef<JSObject>& obj, Font& font)
135 {
136     if (obj->HasProperty("fontColor")) {
137         JSRef<JSVal> colorObj = JSRef<JSVal>::Cast(obj->GetProperty("fontColor"));
138         Color color;
139         if (!colorObj->IsNull() && !JSViewAbstract::ParseJsColor(colorObj, color)) {
140             auto context = PipelineBase::GetCurrentContextSafely();
141             CHECK_NULL_VOID(context);
142             auto theme = context->GetTheme<TextTheme>();
143             CHECK_NULL_VOID(theme);
144             color = theme->GetTextStyle().GetTextColor();
145         }
146         font.fontColor = color;
147     }
148 }
149 
ParseJsFontSize(const JSRef<JSObject> & obj,Font & font)150 void JSFontSpan::ParseJsFontSize(const JSRef<JSObject>& obj, Font& font)
151 {
152     if (obj->HasProperty("fontSize")) {
153         auto context = PipelineBase::GetCurrentContextSafely();
154         CHECK_NULL_VOID(context);
155         auto theme = context->GetTheme<TextTheme>();
156         CHECK_NULL_VOID(theme);
157         auto fontSize = obj->GetProperty("fontSize");
158         CalcDimension size = theme->GetTextStyle().GetFontSize();
159         if (!fontSize->IsNull() && fontSize->IsObject()) {
160             auto sizeTmp = ParseLengthMetrics(fontSize, false);
161             if (sizeTmp.Value() >= 0 && sizeTmp.Unit() != DimensionUnit::PERCENT) {
162                 size = sizeTmp;
163             }
164         }
165         font.fontSize = size;
166     }
167 }
168 
ParseJsFontWeight(const JSRef<JSObject> & obj,Font & font)169 void JSFontSpan::ParseJsFontWeight(const JSRef<JSObject>& obj, Font& font)
170 {
171     if (obj->HasProperty("fontWeight")) {
172         auto fontWeight = obj->GetProperty("fontWeight");
173         std::string weight = "";
174         if (fontWeight->IsNumber()) {
175             weight = std::to_string(fontWeight->ToNumber<int32_t>());
176         } else {
177             JSViewAbstract::ParseJsString(fontWeight, weight);
178         }
179         if (weight != "") {
180             font.fontWeight = ConvertStrToFontWeight(weight);
181         } else {
182             auto context = PipelineBase::GetCurrentContextSafely();
183             CHECK_NULL_VOID(context);
184             auto theme = context->GetTheme<TextTheme>();
185             CHECK_NULL_VOID(theme);
186             font.fontWeight = theme->GetTextStyle().GetFontWeight();
187         }
188     }
189 }
190 
ParseJsFontFamily(const JSRef<JSObject> & obj,Font & font)191 void JSFontSpan::ParseJsFontFamily(const JSRef<JSObject>& obj, Font& font)
192 {
193     if (obj->HasProperty("fontFamily")) {
194         auto fontFamily = obj->GetProperty("fontFamily");
195         std::vector<std::string> fontFamilies;
196         if (JSViewAbstract::ParseJsFontFamilies(fontFamily, fontFamilies)) {
197             font.fontFamiliesNG = fontFamilies;
198         } else {
199             auto context = PipelineBase::GetCurrentContextSafely();
200             CHECK_NULL_VOID(context);
201             auto theme = context->GetTheme<TextTheme>();
202             CHECK_NULL_VOID(theme);
203             font.fontFamiliesNG = theme->GetTextStyle().GetFontFamilies();
204         }
205     }
206 }
207 
ParseJsFontStyle(const JSRef<JSObject> & obj,Font & font)208 void JSFontSpan::ParseJsFontStyle(const JSRef<JSObject>& obj, Font& font)
209 {
210     if (obj->HasProperty("fontStyle")) {
211         auto style = obj->GetProperty("fontStyle");
212         OHOS::Ace::FontStyle fontStyle = FontStyle::NORMAL;
213         if (!style->IsNull() && style->IsNumber()) {
214             auto value = style->ToNumber<int32_t>();
215             if (value >= 0 && value < static_cast<int32_t>(FontStyle::NONE)) {
216                 fontStyle = static_cast<FontStyle>(value);
217             }
218         }
219         font.fontStyle = fontStyle;
220     }
221 }
222 
ParseJsStrokeWidth(const JSRef<JSObject> & obj,Font & font)223 void JSFontSpan::ParseJsStrokeWidth(const JSRef<JSObject>& obj, Font& font)
224 {
225     auto context = PipelineBase::GetCurrentContextSafelyWithCheck();
226     CHECK_NULL_VOID(context);
227     auto theme = context->GetTheme<TextTheme>();
228     CHECK_NULL_VOID(theme);
229     CalcDimension width = theme->GetTextStyle().GetStrokeWidth();
230     if (obj->HasProperty("strokeWidth")) {
231         auto strokeWidth = obj->GetProperty("strokeWidth");
232         if (!strokeWidth->IsNull() && strokeWidth->IsObject()) {
233             auto strokeWidthTmp = ParseLengthMetrics(strokeWidth, false);
234             if (strokeWidthTmp.Unit() != DimensionUnit::PERCENT) {
235                 width = strokeWidthTmp;
236             }
237         }
238     }
239     font.strokeWidth = width;
240 }
241 
GetStrokeColorFallback(const JSRef<JSObject> & obj,const RefPtr<TextTheme> & theme,Color & color)242 void JSFontSpan::GetStrokeColorFallback(const JSRef<JSObject>& obj, const RefPtr<TextTheme>& theme, Color& color)
243 {
244     if (obj->HasProperty("fontColor")) {
245         JSRef<JSVal> colorObj = JSRef<JSVal>::Cast(obj->GetProperty("fontColor"));
246         if (!colorObj->IsNull() && !JSViewAbstract::ParseJsColor(colorObj, color)) {
247             color = theme->GetTextStyle().GetTextColor();
248         }
249     } else {
250         color = theme->GetTextStyle().GetTextColor();
251     }
252 }
253 
ParseJsStrokeColor(const JSRef<JSObject> & obj,Font & font)254 void JSFontSpan::ParseJsStrokeColor(const JSRef<JSObject>& obj, Font& font)
255 {
256     Color color;
257     auto context = PipelineBase::GetCurrentContextSafelyWithCheck();
258     CHECK_NULL_VOID(context);
259     auto theme = context->GetTheme<TextTheme>();
260     CHECK_NULL_VOID(theme);
261     if (obj->HasProperty("strokeColor")) {
262         JSRef<JSVal> strokeColorObj = JSRef<JSVal>::Cast(obj->GetProperty("strokeColor"));
263         if (!strokeColorObj->IsNull() && !JSViewAbstract::ParseJsColor(strokeColorObj, color)) {
264             GetStrokeColorFallback(obj, theme, color);
265         }
266         font.strokeColor = color;
267     } else if (obj->HasProperty("fontColor")) {
268         JSRef<JSVal> colorObj = JSRef<JSVal>::Cast(obj->GetProperty("fontColor"));
269         if (!colorObj->IsNull() && !JSViewAbstract::ParseJsColor(colorObj, color)) {
270             color = theme->GetTextStyle().GetTextColor();
271         }
272         font.strokeColor = color;
273     } else {
274         font.strokeColor = theme->GetTextStyle().GetTextColor();
275     }
276 }
277 
ParseJsSuperscript(const JSRef<JSObject> & obj,Font & font)278 void JSFontSpan::ParseJsSuperscript(const JSRef<JSObject>& obj, Font& font)
279 {
280     if (obj->HasProperty("superscript")) {
281         auto style = obj->GetProperty("superscript");
282         OHOS::Ace::SuperscriptStyle superscriptStyle = SuperscriptStyle::NORMAL;
283         if (!style->IsNull() && style->IsNumber()) {
284             auto value = style->ToNumber<int32_t>();
285             if (value >= 0 && value < static_cast<int32_t>(SuperscriptStyle::NONE)) {
286                 superscriptStyle = static_cast<SuperscriptStyle>(value);
287             }
288         }
289         font.superscript = superscriptStyle;
290     } else {
291         font.superscript = SuperscriptStyle::NORMAL;
292     }
293 }
294 
GetFontColor(const JSCallbackInfo & info)295 void JSFontSpan::GetFontColor(const JSCallbackInfo& info)
296 {
297     CHECK_NULL_VOID(fontSpan_);
298     if (!fontSpan_->GetFont().fontColor.has_value()) {
299         return;
300     }
301     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(fontSpan_->GetFont().fontColor.value().ColorToString())));
302     info.SetReturnValue(ret);
303 }
304 
SetFontColor(const JSCallbackInfo & info)305 void JSFontSpan::SetFontColor(const JSCallbackInfo& info) {}
306 
GetFontSize(const JSCallbackInfo & info)307 void JSFontSpan::GetFontSize(const JSCallbackInfo& info)
308 {
309     CHECK_NULL_VOID(fontSpan_);
310     if (!fontSpan_->GetFont().fontSize.has_value()) {
311         return;
312     }
313     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(fontSpan_->GetFont().fontSize.value().ConvertToVp())));
314     info.SetReturnValue(ret);
315 }
316 
SetFontSize(const JSCallbackInfo & info)317 void JSFontSpan::SetFontSize(const JSCallbackInfo& info) {}
318 
GetFontStyle(const JSCallbackInfo & info)319 void JSFontSpan::GetFontStyle(const JSCallbackInfo& info)
320 {
321     CHECK_NULL_VOID(fontSpan_);
322     if (!fontSpan_->GetFont().fontStyle.has_value()) {
323         return;
324     }
325     auto ret = JSRef<JSVal>::Make(
326         JSVal(ToJSValue(std::to_string(static_cast<int32_t>(fontSpan_->GetFont().fontStyle.value())))));
327     info.SetReturnValue(ret);
328 }
329 
SetFontStyle(const JSCallbackInfo & info)330 void JSFontSpan::SetFontStyle(const JSCallbackInfo& info) {}
331 
GetFontWeight(const JSCallbackInfo & info)332 void JSFontSpan::GetFontWeight(const JSCallbackInfo& info)
333 {
334     CHECK_NULL_VOID(fontSpan_);
335     if (!fontSpan_->GetFont().fontWeight.has_value()) {
336         return;
337     }
338     auto ret = JSRef<JSVal>::Make(
339         JSVal(ToJSValue(std::to_string(static_cast<int32_t>(fontSpan_->GetFont().fontWeight.value())))));
340     info.SetReturnValue(ret);
341 }
342 
SetFontWeight(const JSCallbackInfo & info)343 void JSFontSpan::SetFontWeight(const JSCallbackInfo& info) {}
344 
GetFontFamily(const JSCallbackInfo & info)345 void JSFontSpan::GetFontFamily(const JSCallbackInfo& info)
346 {
347     CHECK_NULL_VOID(fontSpan_);
348     if (!fontSpan_->GetFont().fontFamiliesNG.has_value()) {
349         return;
350     }
351     auto fontFamilies = fontSpan_->GetFont().fontFamiliesNG.value();
352     auto retStr = std::accumulate(fontFamilies.begin(), fontFamilies.end(), std::string());
353     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(retStr)));
354     info.SetReturnValue(ret);
355 }
356 
SetFontFamily(const JSCallbackInfo & info)357 void JSFontSpan::SetFontFamily(const JSCallbackInfo& info) {}
358 
GetStrokeWidth(const JSCallbackInfo & info)359 void JSFontSpan::GetStrokeWidth(const JSCallbackInfo& info)
360 {
361     CHECK_NULL_VOID(fontSpan_);
362     if (!fontSpan_->GetFont().strokeWidth.has_value()) {
363         return;
364     }
365     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(fontSpan_->GetFont().strokeWidth.value().ConvertToVp())));
366     info.SetReturnValue(ret);
367 }
368 
SetStrokeWidth(const JSCallbackInfo & info)369 void JSFontSpan::SetStrokeWidth(const JSCallbackInfo& info) {}
370 
GetStrokeColor(const JSCallbackInfo & info)371 void JSFontSpan::GetStrokeColor(const JSCallbackInfo& info)
372 {
373     CHECK_NULL_VOID(fontSpan_);
374     if (!fontSpan_->GetFont().strokeColor.has_value()) {
375         return;
376     }
377     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(fontSpan_->GetFont().strokeColor.value().ColorToString())));
378     info.SetReturnValue(ret);
379 }
380 
SetStrokeColor(const JSCallbackInfo & info)381 void JSFontSpan::SetStrokeColor(const JSCallbackInfo& info) {}
382 
GetSuperscript(const JSCallbackInfo & info)383 void JSFontSpan::GetSuperscript(const JSCallbackInfo& info)
384 {
385     CHECK_NULL_VOID(fontSpan_);
386     if (!fontSpan_->GetFont().superscript.has_value()) {
387         return;
388     }
389     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(static_cast<int32_t>(fontSpan_->GetFont().superscript.value()))));
390     info.SetReturnValue(ret);
391 }
392 
SetSuperscript(const JSCallbackInfo & info)393 void JSFontSpan::SetSuperscript(const JSCallbackInfo& info) {}
394 
GetFontSpan()395 const RefPtr<FontSpan>& JSFontSpan::GetFontSpan()
396 {
397     return fontSpan_;
398 }
399 
SetFontSpan(const RefPtr<FontSpan> & fontSpan)400 void JSFontSpan::SetFontSpan(const RefPtr<FontSpan>& fontSpan)
401 {
402     fontSpan_ = fontSpan;
403 }
404 
JSBind(BindingTarget globalObj)405 void JSDecorationSpan::JSBind(BindingTarget globalObj)
406 {
407     JSClass<JSDecorationSpan>::Declare("DecorationStyle");
408     JSClass<JSDecorationSpan>::CustomProperty(
409         "type", &JSDecorationSpan::GetTextDecorationType, &JSDecorationSpan::SetTextDecorationType);
410     JSClass<JSDecorationSpan>::CustomProperty(
411         "color", &JSDecorationSpan::GetTextDecorationColor, &JSDecorationSpan::SetTextDecorationColor);
412     JSClass<JSDecorationSpan>::CustomProperty(
413         "style", &JSDecorationSpan::GetTextDecorationStyle, &JSDecorationSpan::SetTextDecorationStyle);
414     JSClass<JSDecorationSpan>::CustomProperty(
415         "thicknessScale", &JSDecorationSpan::GetLineThicknessScale, &JSDecorationSpan::SetLineThicknessScale);
416     JSClass<JSDecorationSpan>::CustomProperty(
417         "options", &JSDecorationSpan::GetTextDecorationOptions, &JSDecorationSpan::SetTextDecorationOptions);
418     JSClass<JSDecorationSpan>::Bind(globalObj, JSDecorationSpan::Constructor, JSDecorationSpan::Destructor);
419 }
420 
Constructor(const JSCallbackInfo & args)421 void JSDecorationSpan::Constructor(const JSCallbackInfo& args)
422 {
423     auto decorationSpan = Referenced::MakeRefPtr<JSDecorationSpan>();
424     decorationSpan->IncRefCount();
425 
426     RefPtr<DecorationSpan> span = JSDecorationSpan::ParseJsDecorationSpan(args);
427     decorationSpan->decorationSpan_ = span;
428     args.SetReturnValue(Referenced::RawPtr(decorationSpan));
429 }
430 
Destructor(JSDecorationSpan * decorationSpan)431 void JSDecorationSpan::Destructor(JSDecorationSpan* decorationSpan)
432 {
433     if (decorationSpan != nullptr) {
434         decorationSpan->DecRefCount();
435     }
436 }
437 
ParseJsDecorationSpan(const JSCallbackInfo & args)438 RefPtr<DecorationSpan> JSDecorationSpan::ParseJsDecorationSpan(const JSCallbackInfo& args)
439 {
440     if (args.Length() <= 0 || !args[0]->IsObject()) {
441         return AceType::MakeRefPtr<DecorationSpan>();
442     }
443     auto obj = JSRef<JSObject>::Cast(args[0]);
444     std::optional<Color> colorOption;
445     Color color;
446     JSRef<JSVal> colorObj = JSRef<JSVal>::Cast(obj->GetProperty("color"));
447     if (!colorObj->IsNull() && JSViewAbstract::ParseJsColor(colorObj, color)) {
448         colorOption = color;
449     }
450     std::optional<TextDecorationStyle> styleOption;
451     JSRef<JSVal> styleObj = JSRef<JSVal>::Cast(obj->GetProperty("style"));
452     if (!styleObj->IsNull() && styleObj->IsNumber()) {
453         styleOption = static_cast<TextDecorationStyle>(styleObj->ToNumber<int32_t>());
454     }
455     TextDecoration type = TextDecoration::NONE;
456     JSRef<JSVal> typeObj = JSRef<JSVal>::Cast(obj->GetProperty("type"));
457     if (!typeObj->IsNull() && typeObj->IsNumber()) {
458         type = static_cast<TextDecoration>(typeObj->ToNumber<int32_t>());
459     }
460     std::optional<float> lineThicknessScale;
461     JSRef<JSVal> thicknessScaleValue = obj->GetProperty("thicknessScale");
462     if (thicknessScaleValue->IsNumber()) {
463         lineThicknessScale = thicknessScaleValue->ToNumber<float>();
464         lineThicknessScale = LessNotEqual(lineThicknessScale.value_or(-1.0f), 0) ? 1.0f : lineThicknessScale;
465     }
466     std::optional<TextDecorationOptions> options;
467     if (args.Length() > 1 && args[1]->IsObject()) {
468         options = JSDecorationSpan::ParseJsDecorationOptions(JSRef<JSObject>::Cast(args[1]));
469     }
470     return AceType::MakeRefPtr<DecorationSpan>(
471         std::vector<TextDecoration>({type}), colorOption, styleOption, lineThicknessScale, options);
472 }
473 
ParseJsDecorationOptions(const JSRef<JSObject> & obj)474 TextDecorationOptions JSDecorationSpan::ParseJsDecorationOptions(const JSRef<JSObject>& obj)
475 {
476     TextDecorationOptions options;
477     JSRef<JSVal> enableMultiTypeObj = JSRef<JSVal>::Cast(obj->GetProperty("enableMultiType"));
478     if (!enableMultiTypeObj->IsNull() && enableMultiTypeObj->IsBoolean()) {
479         options.enableMultiType = enableMultiTypeObj->ToBoolean();
480     }
481     return options;
482 }
483 
GetTextDecorationType(const JSCallbackInfo & info)484 void JSDecorationSpan::GetTextDecorationType(const JSCallbackInfo& info)
485 {
486     CHECK_NULL_VOID(decorationSpan_);
487     auto ret = JSRef<JSVal>::Make(
488         JSVal(ToJSValue(static_cast<int32_t>(decorationSpan_->GetTextDecorationFirst()))));
489     info.SetReturnValue(ret);
490 }
491 
SetTextDecorationType(const JSCallbackInfo & info)492 void JSDecorationSpan::SetTextDecorationType(const JSCallbackInfo& info) {}
493 
GetTextDecorationColor(const JSCallbackInfo & info)494 void JSDecorationSpan::GetTextDecorationColor(const JSCallbackInfo& info)
495 {
496     CHECK_NULL_VOID(decorationSpan_);
497     if (!decorationSpan_->GetColor().has_value()) {
498         return;
499     }
500     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(decorationSpan_->GetColor()->ColorToString())));
501     info.SetReturnValue(ret);
502 }
503 
SetTextDecorationColor(const JSCallbackInfo & info)504 void JSDecorationSpan::SetTextDecorationColor(const JSCallbackInfo& info) {}
505 
GetTextDecorationStyle(const JSCallbackInfo & info)506 void JSDecorationSpan::GetTextDecorationStyle(const JSCallbackInfo& info)
507 {
508     CHECK_NULL_VOID(decorationSpan_);
509     if (!decorationSpan_->GetTextDecorationStyle().has_value()) {
510         return;
511     }
512     auto ret =
513         JSRef<JSVal>::Make(JSVal(ToJSValue(static_cast<int32_t>(decorationSpan_->GetTextDecorationStyle().value()))));
514     info.SetReturnValue(ret);
515 }
516 
SetTextDecorationStyle(const JSCallbackInfo & info)517 void JSDecorationSpan::SetTextDecorationStyle(const JSCallbackInfo& info) {}
518 
GetLineThicknessScale(const JSCallbackInfo & info)519 void JSDecorationSpan::GetLineThicknessScale(const JSCallbackInfo& info)
520 {
521     CHECK_NULL_VOID(decorationSpan_);
522     if (!decorationSpan_->GetLineThicknessScale().has_value()) {
523         return;
524     }
525     auto ret =
526         JSRef<JSVal>::Make(JSVal(ToJSValue(decorationSpan_->GetLineThicknessScale().value())));
527     info.SetReturnValue(ret);
528 }
529 
SetLineThicknessScale(const JSCallbackInfo & info)530 void JSDecorationSpan::SetLineThicknessScale(const JSCallbackInfo& info) {}
531 
GetTextDecorationOptions(const JSCallbackInfo & info)532 void JSDecorationSpan::GetTextDecorationOptions(const JSCallbackInfo& info)
533 {
534     CHECK_NULL_VOID(decorationSpan_);
535     if (!decorationSpan_->GetTextDecorationOptions().has_value()) {
536         return;
537     }
538     auto options = decorationSpan_->GetTextDecorationOptions().value();
539     JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
540     objectTemplate->SetInternalFieldCount(1);
541     JSRef<JSObject> retObj = objectTemplate->NewInstance();
542     if (options.enableMultiType.has_value()) {
543         bool enableMultiType = options.enableMultiType.value_or(false);
544         retObj->SetProperty<bool>("enableMultiType", enableMultiType);
545     }
546     info.SetReturnValue(retObj);
547 }
548 
SetTextDecorationOptions(const JSCallbackInfo & info)549 void JSDecorationSpan::SetTextDecorationOptions(const JSCallbackInfo& info) {}
550 
GetDecorationSpan()551 RefPtr<DecorationSpan>& JSDecorationSpan::GetDecorationSpan()
552 {
553     return decorationSpan_;
554 }
555 
SetDecorationSpan(const RefPtr<DecorationSpan> & decorationSpan)556 void JSDecorationSpan::SetDecorationSpan(const RefPtr<DecorationSpan>& decorationSpan)
557 {
558     decorationSpan_ = decorationSpan;
559 }
560 
JSBind(BindingTarget globalObj)561 void JSBaselineOffsetSpan::JSBind(BindingTarget globalObj)
562 {
563     JSClass<JSBaselineOffsetSpan>::Declare("BaselineOffsetStyle");
564     JSClass<JSBaselineOffsetSpan>::CustomProperty(
565         "baselineOffset", &JSBaselineOffsetSpan::GetBaselineOffset, &JSBaselineOffsetSpan::SetBaselineOffset);
566     JSClass<JSBaselineOffsetSpan>::Bind(globalObj, JSBaselineOffsetSpan::Constructor, JSBaselineOffsetSpan::Destructor);
567 }
568 
Constructor(const JSCallbackInfo & args)569 void JSBaselineOffsetSpan::Constructor(const JSCallbackInfo& args)
570 {
571     auto baselineOffsetSpan = Referenced::MakeRefPtr<JSBaselineOffsetSpan>();
572     baselineOffsetSpan->IncRefCount();
573     RefPtr<BaselineOffsetSpan> span;
574     if (args.Length() <= 0 || !args[0]->IsObject()) {
575         span = AceType::MakeRefPtr<BaselineOffsetSpan>();
576     } else {
577         span = JSBaselineOffsetSpan::ParseJSBaselineOffsetSpan(JSRef<JSObject>::Cast(args[0]));
578     }
579     baselineOffsetSpan->baselineOffsetSpan_ = span;
580     args.SetReturnValue(Referenced::RawPtr(baselineOffsetSpan));
581 }
582 
Destructor(JSBaselineOffsetSpan * baselineOffsetSpan)583 void JSBaselineOffsetSpan::Destructor(JSBaselineOffsetSpan* baselineOffsetSpan)
584 {
585     if (baselineOffsetSpan != nullptr) {
586         baselineOffsetSpan->DecRefCount();
587     }
588 }
589 
ParseJSBaselineOffsetSpan(const JSRef<JSObject> & obj)590 RefPtr<BaselineOffsetSpan> JSBaselineOffsetSpan::ParseJSBaselineOffsetSpan(const JSRef<JSObject>& obj)
591 {
592     if (obj->IsUndefined()) {
593         return AceType::MakeRefPtr<BaselineOffsetSpan>(CalcDimension(0, DimensionUnit::VP));
594     }
595     return AceType::MakeRefPtr<BaselineOffsetSpan>(ParseLengthMetrics(obj));
596 }
597 
GetBaselineOffset(const JSCallbackInfo & info)598 void JSBaselineOffsetSpan::GetBaselineOffset(const JSCallbackInfo& info)
599 {
600     CHECK_NULL_VOID(baselineOffsetSpan_);
601     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(baselineOffsetSpan_->GetBaselineOffset().ConvertToVp())));
602     info.SetReturnValue(ret);
603 }
604 
SetBaselineOffset(const JSCallbackInfo & info)605 void JSBaselineOffsetSpan::SetBaselineOffset(const JSCallbackInfo& info) {}
606 
GetBaselineOffsetSpan()607 RefPtr<BaselineOffsetSpan>& JSBaselineOffsetSpan::GetBaselineOffsetSpan()
608 {
609     return baselineOffsetSpan_;
610 }
611 
SetBaselineOffsetSpan(const RefPtr<BaselineOffsetSpan> & baselineOffsetSpan)612 void JSBaselineOffsetSpan::SetBaselineOffsetSpan(const RefPtr<BaselineOffsetSpan>& baselineOffsetSpan)
613 {
614     baselineOffsetSpan_ = baselineOffsetSpan;
615 }
616 
JSBind(BindingTarget globalObj)617 void JSLetterSpacingSpan::JSBind(BindingTarget globalObj)
618 {
619     JSClass<JSLetterSpacingSpan>::Declare("LetterSpacingStyle");
620     JSClass<JSLetterSpacingSpan>::CustomProperty(
621         "letterSpacing", &JSLetterSpacingSpan::GetLetterSpacing, &JSLetterSpacingSpan::SetLetterSpacing);
622     JSClass<JSLetterSpacingSpan>::Bind(globalObj, JSLetterSpacingSpan::Constructor, JSLetterSpacingSpan::Destructor);
623 }
624 
Constructor(const JSCallbackInfo & args)625 void JSLetterSpacingSpan::Constructor(const JSCallbackInfo& args)
626 {
627     auto letterSpacingSpan = Referenced::MakeRefPtr<JSLetterSpacingSpan>();
628     letterSpacingSpan->IncRefCount();
629 
630     RefPtr<LetterSpacingSpan> span;
631     if (args.Length() <= 0 || !args[0]->IsObject()) {
632         span = AceType::MakeRefPtr<LetterSpacingSpan>();
633     } else {
634         span = JSLetterSpacingSpan::ParseJSLetterSpacingSpan(JSRef<JSObject>::Cast(args[0]));
635     }
636     letterSpacingSpan->letterSpacingSpan_ = span;
637     args.SetReturnValue(Referenced::RawPtr(letterSpacingSpan));
638 }
639 
Destructor(JSLetterSpacingSpan * letterSpacingSpan)640 void JSLetterSpacingSpan::Destructor(JSLetterSpacingSpan* letterSpacingSpan)
641 {
642     if (letterSpacingSpan != nullptr) {
643         letterSpacingSpan->DecRefCount();
644     }
645 }
646 
ParseJSLetterSpacingSpan(const JSRef<JSObject> & obj)647 RefPtr<LetterSpacingSpan> JSLetterSpacingSpan::ParseJSLetterSpacingSpan(const JSRef<JSObject>& obj)
648 {
649     if (obj->IsUndefined()) {
650         return AceType::MakeRefPtr<LetterSpacingSpan>(CalcDimension(0, DimensionUnit::VP));
651     }
652     return AceType::MakeRefPtr<LetterSpacingSpan>(ParseLengthMetrics(obj));
653 }
654 
GetLetterSpacing(const JSCallbackInfo & info)655 void JSLetterSpacingSpan::GetLetterSpacing(const JSCallbackInfo& info)
656 {
657     CHECK_NULL_VOID(letterSpacingSpan_);
658     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(letterSpacingSpan_->GetLetterSpacing().ConvertToVp())));
659     info.SetReturnValue(ret);
660 }
661 
SetLetterSpacing(const JSCallbackInfo & info)662 void JSLetterSpacingSpan::SetLetterSpacing(const JSCallbackInfo& info) {}
663 
GetLetterSpacingSpan()664 RefPtr<LetterSpacingSpan>& JSLetterSpacingSpan::GetLetterSpacingSpan()
665 {
666     return letterSpacingSpan_;
667 }
668 
SetLetterSpacingSpan(const RefPtr<LetterSpacingSpan> & letterSpacingSpan)669 void JSLetterSpacingSpan::SetLetterSpacingSpan(const RefPtr<LetterSpacingSpan>& letterSpacingSpan)
670 {
671     letterSpacingSpan_ = letterSpacingSpan;
672 }
673 
Constructor(const JSCallbackInfo & args)674 void JSGestureSpan::Constructor(const JSCallbackInfo& args)
675 {
676     auto gestureSpan = Referenced::MakeRefPtr<JSGestureSpan>();
677     gestureSpan->IncRefCount();
678 
679     RefPtr<GestureSpan> span;
680     if (args.Length() <= 0) {
681         GestureStyle gestureInfo;
682         span = AceType::MakeRefPtr<GestureSpan>(gestureInfo);
683     } else {
684         span = JSGestureSpan::ParseJSGestureSpan(args);
685     }
686     gestureSpan->gestureSpan_ = span;
687     args.SetReturnValue(Referenced::RawPtr(gestureSpan));
688 }
689 
Destructor(JSGestureSpan * gestureSpan)690 void JSGestureSpan::Destructor(JSGestureSpan* gestureSpan)
691 {
692     if (gestureSpan != nullptr) {
693         gestureSpan->DecRefCount();
694     }
695 }
696 
JSBind(BindingTarget globalObj)697 void JSGestureSpan::JSBind(BindingTarget globalObj)
698 {
699     JSClass<JSGestureSpan>::Declare("NativeGestureStyle");
700     JSClass<JSGestureSpan>::Bind(globalObj, JSGestureSpan::Constructor, JSGestureSpan::Destructor);
701 }
702 
ParseJSGestureSpan(const JSCallbackInfo & args)703 RefPtr<GestureSpan> JSGestureSpan::ParseJSGestureSpan(const JSCallbackInfo& args)
704 {
705     GestureStyle gestureInfo;
706     if (args.Length() <= 0 || !args[0]->IsObject()) {
707         gestureInfo = { std::nullopt, std::nullopt, std::nullopt };
708         return AceType::MakeRefPtr<GestureSpan>(gestureInfo);
709     }
710     JSRef<JSObject> object = JSRef<JSObject>::Cast(args[0]);
711 
712     auto clickFunc = object->GetProperty("onClick");
713     if (clickFunc->IsUndefined() || !clickFunc->IsFunction()) {
714         gestureInfo.onClick = std::nullopt;
715     } else {
716         auto jsOnClickFunc = AceType::MakeRefPtr<JsWeakClickFunction>(JSRef<JSFunc>::Cast(clickFunc));
717         auto onClick = [execCtx = args.GetExecutionContext(), func = jsOnClickFunc](BaseEventInfo* info) {
718             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
719             auto* clickInfo = TypeInfoHelper::DynamicCast<GestureEvent>(info);
720             ACE_SCORING_EVENT("SpanString.onClick");
721             func->Execute(*clickInfo);
722         };
723         auto tmpClickFunc = [func = std::move(onClick)](GestureEvent& info) { func(&info); };
724         gestureInfo.onClick = std::move(tmpClickFunc);
725     }
726 
727     auto longPressFunc = object->GetProperty("onLongPress");
728     if (longPressFunc->IsUndefined() || !longPressFunc->IsFunction()) {
729         gestureInfo.onLongPress = std::nullopt;
730     } else {
731         auto jsOnLongPressFunc = AceType::MakeRefPtr<JsWeakClickFunction>(JSRef<JSFunc>::Cast(longPressFunc));
732         auto onLongPress = [execCtx = args.GetExecutionContext(), func = jsOnLongPressFunc](BaseEventInfo* info) {
733             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
734             auto* longPressInfo = TypeInfoHelper::DynamicCast<GestureEvent>(info);
735             ACE_SCORING_EVENT("SpanString.onLongPress");
736             func->Execute(*longPressInfo);
737         };
738         auto tmpLongPressFunc = [func = std::move(onLongPress)](GestureEvent& info) { func(&info); };
739         gestureInfo.onLongPress = std::move(tmpLongPressFunc);
740     }
741 
742     auto touchFunc = object->GetProperty("onTouch");
743     if (touchFunc->IsUndefined() || !touchFunc->IsFunction()) {
744         gestureInfo.onTouch = std::nullopt;
745     } else {
746         auto jsOnTouchWeakFunc = AceType::MakeRefPtr<JsWeakFunction>(JSRef<JSFunc>::Cast(touchFunc));
747         auto onTouch = [execCtx = args.GetExecutionContext(), func = jsOnTouchWeakFunc](TouchEventInfo& info) {
748             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
749             ACE_SCORING_EVENT("SpanString.onTouch");
750             JSRef<JSVal> param = JsTouchFunction::CreateJSEventInfo(info);
751             func->ExecuteJS(1, &param);
752         };
753         gestureInfo.onTouch = std::move(onTouch);
754     }
755     return AceType::MakeRefPtr<GestureSpan>(gestureInfo);
756 }
757 
GetGestureSpan()758 RefPtr<GestureSpan>& JSGestureSpan::GetGestureSpan()
759 {
760     return gestureSpan_;
761 }
762 
SetGestureSpan(const RefPtr<GestureSpan> & gestureSpan)763 void JSGestureSpan::SetGestureSpan(const RefPtr<GestureSpan>& gestureSpan)
764 {
765     gestureSpan_ = gestureSpan;
766 }
JSBind(BindingTarget globalObj)767 void JSTextShadowSpan::JSBind(BindingTarget globalObj)
768 {
769     JSClass<JSTextShadowSpan>::Declare("TextShadowStyle");
770     JSClass<JSTextShadowSpan>::CustomProperty(
771         "textShadow", &JSTextShadowSpan::GetTextShadow, &JSTextShadowSpan::SetTextShadow);
772     JSClass<JSTextShadowSpan>::Bind(globalObj, JSTextShadowSpan::Constructor, JSTextShadowSpan::Destructor);
773 }
774 
Constructor(const JSCallbackInfo & args)775 void JSTextShadowSpan::Constructor(const JSCallbackInfo& args)
776 {
777     auto textShadowSpan = Referenced::MakeRefPtr<JSTextShadowSpan>();
778     textShadowSpan->IncRefCount();
779 
780     RefPtr<TextShadowSpan> span;
781     if (args.Length() <= 0 || !args[0]->IsObject()) {
782         std::vector<Shadow> shadows;
783         span = AceType::MakeRefPtr<TextShadowSpan>(shadows);
784     } else {
785         span = JSTextShadowSpan::ParseJSTextShadowSpan(JSRef<JSObject>::Cast(args[0]));
786     }
787     textShadowSpan->textShadowSpan_ = span;
788     args.SetReturnValue(Referenced::RawPtr(textShadowSpan));
789 }
790 
Destructor(JSTextShadowSpan * textShadowSpan)791 void JSTextShadowSpan::Destructor(JSTextShadowSpan* textShadowSpan)
792 {
793     if (textShadowSpan != nullptr) {
794         textShadowSpan->DecRefCount();
795     }
796 }
797 
ParseJSTextShadowSpan(const JSRef<JSObject> & obj)798 RefPtr<TextShadowSpan> JSTextShadowSpan::ParseJSTextShadowSpan(const JSRef<JSObject>& obj)
799 {
800     std::vector<Shadow> shadows;
801     ParseTextShadowFromShadowObject(obj, shadows);
802     return AceType::MakeRefPtr<TextShadowSpan>(shadows);
803 }
804 
GetTextShadow(const JSCallbackInfo & info)805 void JSTextShadowSpan::GetTextShadow(const JSCallbackInfo& info)
806 {
807     CHECK_NULL_VOID(textShadowSpan_);
808     auto shadows = textShadowSpan_->GetTextShadow();
809 
810     JSRef<JSArray> result = JSRef<JSArray>::New();
811     uint32_t index = 0;
812     for (auto iterator = shadows.begin(); iterator != shadows.end(); ++iterator) {
813         auto shadow = *iterator;
814         JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
815         objectTemplate->SetInternalFieldCount(1);
816         JSRef<JSObject> shadowObj = objectTemplate->NewInstance();
817         shadowObj->SetProperty<double>("radius", shadow.GetBlurRadius());
818         shadowObj->SetProperty<double>("offsetX", shadow.GetOffset().GetX());
819         shadowObj->SetProperty<double>("offsetY", shadow.GetOffset().GetY());
820         shadowObj->SetProperty<std::string>("color", shadow.GetColor().ColorToString());
821         shadowObj->SetProperty<int32_t>("type", static_cast<int32_t>(shadow.GetShadowType()));
822         result->SetValueAt(index++, shadowObj);
823     }
824     info.SetReturnValue(result);
825 }
826 
SetTextShadow(const JSCallbackInfo & info)827 void JSTextShadowSpan::SetTextShadow(const JSCallbackInfo& info) {}
828 
GetTextShadowSpan()829 RefPtr<TextShadowSpan>& JSTextShadowSpan::GetTextShadowSpan()
830 {
831     return textShadowSpan_;
832 }
833 
SetTextShadowSpan(const RefPtr<TextShadowSpan> & textShadowSpan)834 void JSTextShadowSpan::SetTextShadowSpan(const RefPtr<TextShadowSpan>& textShadowSpan)
835 {
836     textShadowSpan_ = textShadowSpan;
837 }
838 
839 // JSImageAttachment
Constructor(const JSCallbackInfo & args)840 void JSImageAttachment::Constructor(const JSCallbackInfo& args)
841 {
842     auto imageAttachment = Referenced::MakeRefPtr<JSImageAttachment>();
843     imageAttachment->IncRefCount();
844 
845     RefPtr<ImageSpan> span;
846     if (args.Length() <= 0 || !args[0]->IsObject()) {
847         ImageSpanOptions imageOption;
848         span = AceType::MakeRefPtr<ImageSpan>(imageOption);
849     } else {
850         span = JSImageAttachment::ParseJsImageSpan(JSRef<JSObject>::Cast(args[0]));
851     }
852     imageAttachment->imageSpan_ = span;
853     args.SetReturnValue(Referenced::RawPtr(imageAttachment));
854 }
855 
Destructor(JSImageAttachment * imageSpan)856 void JSImageAttachment::Destructor(JSImageAttachment* imageSpan)
857 {
858     if (imageSpan != nullptr) {
859         imageSpan->DecRefCount();
860     }
861 }
862 
JSBind(BindingTarget globalObj)863 void JSImageAttachment::JSBind(BindingTarget globalObj)
864 {
865     JSClass<JSImageAttachment>::Declare("ImageAttachment");
866     JSClass<JSImageAttachment>::CustomProperty(
867         "value", &JSImageAttachment::GetImageSrc, &JSImageAttachment::SetImageSrc);
868     JSClass<JSImageAttachment>::CustomProperty(
869         "size", &JSImageAttachment::GetImageSize, &JSImageAttachment::SetImageSize);
870     JSClass<JSImageAttachment>::CustomProperty(
871         "verticalAlign", &JSImageAttachment::GetImageVerticalAlign, &JSImageAttachment::SetImageVerticalAlign);
872     JSClass<JSImageAttachment>::CustomProperty(
873         "objectFit", &JSImageAttachment::GetImageObjectFit, &JSImageAttachment::SetImageObjectFit);
874     JSClass<JSImageAttachment>::CustomProperty(
875         "layoutStyle", &JSImageAttachment::GetImageLayoutStyle, &JSImageAttachment::SetImageLayoutStyle);
876     JSClass<JSImageAttachment>::CustomProperty(
877         "colorFilter", &JSImageAttachment::GetImageColorFilter, &JSImageAttachment::SetImageColorFilter);
878     JSClass<JSImageAttachment>::Bind(globalObj, JSImageAttachment::Constructor, JSImageAttachment::Destructor);
879 }
880 
ParseJsImageSpan(const JSRef<JSObject> & obj)881 RefPtr<ImageSpan> JSImageAttachment::ParseJsImageSpan(const JSRef<JSObject>& obj)
882 {
883     auto imageOptions = JSImageAttachment::CreateImageOptions(obj);
884     auto imageAttribute = JSImageAttachment::ParseJsImageSpanAttribute(obj);
885     imageOptions.imageAttribute = imageAttribute;
886     auto imageSpan = MakeRefPtr<ImageSpan>(imageOptions);
887     return imageSpan;
888 }
889 
CreateImageOptions(const JSRef<JSObject> & obj)890 ImageSpanOptions JSImageAttachment::CreateImageOptions(const JSRef<JSObject>& obj)
891 {
892     ImageSpanOptions options;
893     auto container = Container::CurrentSafely();
894     auto context = PipelineBase::GetCurrentContextSafelyWithCheck();
895     CHECK_NULL_RETURN(context, options);
896     bool isCard = context->IsFormRender() && container && !container->IsDynamicRender();
897 
898     std::string imageSrc;
899     std::string bundleName;
900     std::string moduleName;
901     int32_t resId = 0;
902     auto srcValid = obj->HasProperty("resourceValue");
903     auto imageValue = srcValid ? obj->GetProperty("resourceValue") : obj->GetProperty("value");
904     JSViewAbstract::ParseJsMediaWithBundleName(imageValue, imageSrc, bundleName, moduleName, resId);
905     if (isCard && imageValue->IsString()) {
906         SrcType srcType = ImageSourceInfo::ResolveURIType(imageSrc);
907         bool notSupport = (srcType == SrcType::NETWORK || srcType == SrcType::FILE || srcType == SrcType::DATA_ABILITY);
908         if (notSupport) {
909             imageSrc.clear();
910         }
911     }
912     options.image = imageSrc;
913     options.bundleName = bundleName;
914     options.moduleName = moduleName;
915     options.isUriPureNumber = (resId == -1);
916     if (!srcValid) {
917 #if defined(PIXEL_MAP_SUPPORTED)
918         if (!isCard) {
919             if (JSImage::IsDrawable(imageValue)) {
920                 options.imagePixelMap = GetDrawablePixmap(imageValue);
921             } else {
922                 options.imagePixelMap = CreatePixelMapFromNapiValue(imageValue);
923             }
924         }
925 #endif
926     }
927     return options;
928 }
929 
ParseJsImageSpanAttribute(const JSRef<JSObject> & obj)930 ImageSpanAttribute JSImageAttachment::ParseJsImageSpanAttribute(const JSRef<JSObject>& obj)
931 {
932     ImageSpanAttribute imageStyle;
933     ParseJsImageSpanSizeAttribute(obj, imageStyle);
934     JSRef<JSVal> verticalAlign = obj->GetProperty("verticalAlign");
935     if (!verticalAlign->IsNull()) {
936         auto align = static_cast<VerticalAlign>(verticalAlign->ToNumber<int32_t>());
937         if (align < VerticalAlign::TOP || align > VerticalAlign::NONE) {
938             align = VerticalAlign::BOTTOM;
939         }
940         imageStyle.verticalAlign = align;
941     }
942     JSRef<JSVal> objectFit = obj->GetProperty("objectFit");
943     if (!objectFit->IsNull() && objectFit->IsNumber()) {
944         auto fit = static_cast<ImageFit>(objectFit->ToNumber<int32_t>());
945         if (fit < ImageFit::FILL || fit > ImageFit::BOTTOM_END) {
946             fit = ImageFit::COVER;
947         }
948         imageStyle.objectFit = fit;
949     } else {
950         imageStyle.objectFit = ImageFit::COVER;
951     }
952     auto layoutStyleObj = obj->GetProperty("layoutStyle");
953     if (layoutStyleObj->IsObject()) {
954         auto layoutStyleObject = JSRef<JSObject>::Cast(layoutStyleObj);
955         if (!layoutStyleObject->IsUndefined()) {
956             auto marginAttr = layoutStyleObject->GetProperty("margin");
957             imageStyle.marginProp = JSRichEditor::ParseMarginAttr(marginAttr);
958             auto paddingAttr = layoutStyleObject->GetProperty("padding");
959             imageStyle.paddingProp = JSRichEditor::ParseMarginAttr(paddingAttr);
960             auto borderRadiusAttr = layoutStyleObject->GetProperty("borderRadius");
961             imageStyle.borderRadius = JSRichEditor::ParseBorderRadiusAttr(borderRadiusAttr);
962         }
963     }
964 
965     auto syncLoadObj = obj->GetProperty("syncLoad");
966     if (!syncLoadObj->IsNull() && syncLoadObj->IsBoolean()) {
967         imageStyle.syncLoad = syncLoadObj->ToBoolean();
968     }
969 
970     ParseJsImageSpanColorFilterAttribute(obj, imageStyle);
971     return imageStyle;
972 }
973 
ParseJsImageSpanColorFilterAttribute(const JSRef<JSObject> & obj,ImageSpanAttribute & imageStyle)974 void JSImageAttachment::ParseJsImageSpanColorFilterAttribute(const JSRef<JSObject>& obj, ImageSpanAttribute& imageStyle)
975 {
976     auto colorFilterObj = obj->GetProperty("colorFilter");
977     if (colorFilterObj->IsNull()) {
978         return;
979     }
980     if (!colorFilterObj->IsArray() && !colorFilterObj->IsObject()) {
981         SetImageSpanColorFilterAttribute(imageStyle, DEFAULT_COLORFILTER_MATRIX);
982         return;
983     }
984     if (colorFilterObj->IsObject() && !colorFilterObj->IsArray()) {
985         auto drawingColorFilter = CreateDrawingColorFilter(colorFilterObj);
986         if (drawingColorFilter) {
987             imageStyle.colorFilterMatrix = std::nullopt;
988             imageStyle.drawingColorFilter = drawingColorFilter;
989             return;
990         }
991         JSColorFilter* colorFilter;
992         if (!colorFilterObj->IsUndefined() && !colorFilterObj->IsNull()) {
993             colorFilter = JSRef<JSObject>::Cast(colorFilterObj)->Unwrap<JSColorFilter>();
994         } else {
995             SetImageSpanColorFilterAttribute(imageStyle, DEFAULT_COLORFILTER_MATRIX);
996             return;
997         }
998         if (colorFilter && colorFilter->GetColorFilterMatrix().size() == COLOR_FILTER_MATRIX_SIZE) {
999             SetImageSpanColorFilterAttribute(imageStyle, colorFilter->GetColorFilterMatrix());
1000             return;
1001         }
1002         SetImageSpanColorFilterAttribute(imageStyle, DEFAULT_COLORFILTER_MATRIX);
1003         return;
1004     }
1005     JSRef<JSArray> array = JSRef<JSArray>::Cast(colorFilterObj);
1006     if (array->Length() != COLOR_FILTER_MATRIX_SIZE) {
1007         SetImageSpanColorFilterAttribute(imageStyle, DEFAULT_COLORFILTER_MATRIX);
1008         return;
1009     }
1010     std::vector<float> colorfilter;
1011     for (size_t i = 0; i < array->Length(); i++) {
1012         JSRef<JSVal> value = array->GetValueAt(i);
1013         if (!value->IsNumber()) {
1014             SetImageSpanColorFilterAttribute(imageStyle, DEFAULT_COLORFILTER_MATRIX);
1015             return;
1016         }
1017         colorfilter.emplace_back(value->ToNumber<float>());
1018     }
1019     SetImageSpanColorFilterAttribute(imageStyle, colorfilter);
1020 }
1021 
SetImageSpanColorFilterAttribute(ImageSpanAttribute & imageStyle,const std::vector<float> & matrix)1022 void JSImageAttachment::SetImageSpanColorFilterAttribute(ImageSpanAttribute& imageStyle,
1023     const std::vector<float>& matrix)
1024 {
1025     imageStyle.colorFilterMatrix = matrix;
1026     imageStyle.drawingColorFilter = std::nullopt;
1027 }
1028 
ParseJsImageSpanSizeAttribute(const JSRef<JSObject> & obj,ImageSpanAttribute & imageStyle)1029 void JSImageAttachment::ParseJsImageSpanSizeAttribute(const JSRef<JSObject>& obj, ImageSpanAttribute& imageStyle)
1030 {
1031     auto sizeObj = obj->GetProperty("size");
1032     if (sizeObj->IsObject()) {
1033         ImageSpanSize imageSize;
1034         auto size = JSRef<JSObject>::Cast(sizeObj);
1035         JSRef<JSVal> width = size->GetProperty("width");
1036         CalcDimension imageSpanWidth;
1037         if (!width->IsNull() && JSContainerBase::ParseJsDimensionVpNG(width, imageSpanWidth, false) &&
1038             GreatNotEqual(imageSpanWidth.Value(), 0.0)) {
1039             imageSize.width = imageSpanWidth;
1040         }
1041         JSRef<JSVal> height = size->GetProperty("height");
1042         CalcDimension imageSpanHeight;
1043         if (!height->IsNull() && JSContainerBase::ParseJsDimensionVpNG(height, imageSpanHeight, false) &&
1044             GreatNotEqual(imageSpanHeight.Value(), 0.0)) {
1045             imageSize.height = imageSpanHeight;
1046         }
1047         imageStyle.size = imageSize;
1048     }
1049 }
1050 
GetImageSrc(const JSCallbackInfo & info)1051 void JSImageAttachment::GetImageSrc(const JSCallbackInfo& info)
1052 {
1053     CHECK_NULL_VOID(imageSpan_);
1054     auto imageOptions = imageSpan_->GetImageSpanOptions();
1055     JSRef<JSVal> ret;
1056     if (imageOptions.image.has_value()) {
1057         ret = JSRef<JSVal>::Make(ToJSValue(imageOptions.image.value()));
1058     }
1059     if (imageOptions.imagePixelMap.has_value()) {
1060 #ifdef PIXEL_MAP_SUPPORTED
1061         ret = ConvertPixmap(imageOptions.imagePixelMap.value());
1062 #endif
1063     }
1064     info.SetReturnValue(ret);
1065 }
1066 
GetImageSize(const JSCallbackInfo & info)1067 void JSImageAttachment::GetImageSize(const JSCallbackInfo& info)
1068 {
1069     CHECK_NULL_VOID(imageSpan_);
1070     auto imageAttr = imageSpan_->GetImageAttribute();
1071     if (!imageAttr.has_value() || !imageAttr->size.has_value()) {
1072         return;
1073     }
1074     auto imageSize = JSRef<JSObject>::New();
1075     auto size = imageAttr->size;
1076     if (size->width.has_value()) {
1077         imageSize->SetProperty<float>("width", size->width->ConvertToPx());
1078     } else {
1079         imageSize->SetProperty<float>("width", 0.0);
1080     }
1081 
1082     if (size->height.has_value()) {
1083         imageSize->SetProperty<float>("height", size->height->ConvertToPx());
1084     } else {
1085         imageSize->SetProperty<float>("height", 0.0);
1086     }
1087     info.SetReturnValue(imageSize);
1088 }
1089 
GetImageVerticalAlign(const JSCallbackInfo & info)1090 void JSImageAttachment::GetImageVerticalAlign(const JSCallbackInfo& info)
1091 {
1092     CHECK_NULL_VOID(imageSpan_);
1093     auto imageAttr = imageSpan_->GetImageAttribute();
1094     if (!imageAttr.has_value() || !imageAttr->verticalAlign.has_value()) {
1095         return;
1096     }
1097     info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(static_cast<int32_t>(imageAttr->verticalAlign.value()))));
1098 }
1099 
GetImageObjectFit(const JSCallbackInfo & info)1100 void JSImageAttachment::GetImageObjectFit(const JSCallbackInfo& info)
1101 {
1102     CHECK_NULL_VOID(imageSpan_);
1103     auto imageAttr = imageSpan_->GetImageAttribute();
1104     if (!imageAttr.has_value() || !imageAttr->objectFit.has_value()) {
1105         return;
1106     }
1107     info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(static_cast<int32_t>(imageAttr->objectFit.value()))));
1108 }
1109 
CreateEdge(const NG::PaddingPropertyT<NG::CalcLength> & edge)1110 JSRef<JSObject> JSImageAttachment::CreateEdge(const NG::PaddingPropertyT<NG::CalcLength>& edge)
1111 {
1112     auto obj = JSRef<JSObject>::New();
1113     if (edge.top.has_value()) {
1114         obj->SetProperty("top", edge.top->GetDimension().ConvertToVp());
1115     }
1116     if (edge.bottom.has_value()) {
1117         obj->SetProperty("bottom", edge.bottom->GetDimension().ConvertToVp());
1118     }
1119     if (edge.left.has_value()) {
1120         obj->SetProperty("left", edge.left->GetDimension().ConvertToVp());
1121     }
1122     if (edge.right.has_value()) {
1123         obj->SetProperty("right", edge.right->GetDimension().ConvertToVp());
1124     }
1125     return obj;
1126 }
1127 
CreateBorderRadius(const NG::BorderRadiusProperty & borderRadius)1128 JSRef<JSObject> JSImageAttachment::CreateBorderRadius(const NG::BorderRadiusProperty& borderRadius)
1129 {
1130     auto jsBorderRadius = JSRef<JSObject>::New();
1131     if (borderRadius.radiusTopLeft.has_value()) {
1132         jsBorderRadius->SetProperty("topLeft", borderRadius.radiusTopLeft->ConvertToVp());
1133     }
1134     if (borderRadius.radiusTopRight.has_value()) {
1135         jsBorderRadius->SetProperty("topRight", borderRadius.radiusTopRight->ConvertToVp());
1136     }
1137     if (borderRadius.radiusBottomLeft.has_value()) {
1138         jsBorderRadius->SetProperty("bottomLeft", borderRadius.radiusBottomLeft->ConvertToVp());
1139     }
1140     if (borderRadius.radiusBottomRight.has_value()) {
1141         jsBorderRadius->SetProperty("bottomRight", borderRadius.radiusBottomRight->ConvertToVp());
1142     }
1143     return jsBorderRadius;
1144 }
1145 
GetImageLayoutStyle(const JSCallbackInfo & info)1146 void JSImageAttachment::GetImageLayoutStyle(const JSCallbackInfo& info)
1147 {
1148     CHECK_NULL_VOID(imageSpan_);
1149     auto imageAttr = imageSpan_->GetImageAttribute();
1150     if (!imageAttr.has_value()) {
1151         return;
1152     }
1153     auto layoutStyle = JSRef<JSObject>::New();
1154     if (imageAttr->marginProp.has_value()) {
1155         layoutStyle->SetPropertyObject("margin", CreateEdge(imageAttr->marginProp.value()));
1156     }
1157     if (imageAttr->paddingProp.has_value()) {
1158         layoutStyle->SetPropertyObject("padding", CreateEdge(imageAttr->paddingProp.value()));
1159     }
1160     if (imageAttr->borderRadius.has_value()) {
1161         layoutStyle->SetPropertyObject("borderRadius", CreateBorderRadius(imageAttr->borderRadius.value()));
1162     }
1163     info.SetReturnValue(layoutStyle);
1164 }
1165 
GetImageColorFilter(const JSCallbackInfo & info)1166 void JSImageAttachment::GetImageColorFilter(const JSCallbackInfo& info)
1167 {
1168     CHECK_NULL_VOID(imageSpan_);
1169     auto imageAttr = imageSpan_->GetImageAttribute();
1170     if (!imageAttr.has_value()) {
1171         return;
1172     }
1173     if (imageAttr->colorFilterMatrix.has_value()) {
1174         JSRef<JSArray> colorFilterArr = JSRef<JSArray>::New();
1175         uint32_t othersIdx = 0;
1176         for (auto filterFloat : imageAttr->colorFilterMatrix.value()) {
1177             colorFilterArr->SetValueAt(othersIdx++, JSRef<JSVal>::Make(ToJSValue(filterFloat)));
1178         }
1179         info.SetReturnValue(colorFilterArr);
1180         return;
1181     }
1182     if (imageAttr->drawingColorFilter.has_value()) {
1183         auto engine = EngineHelper::GetCurrentEngine();
1184         CHECK_NULL_VOID(engine);
1185         NativeEngine* nativeEngine = engine->GetNativeEngine();
1186         CHECK_NULL_VOID(nativeEngine);
1187         auto jsColorFilter = imageAttr->drawingColorFilter.value()->GetDrawingColorFilterNapiValue(nativeEngine);
1188         CHECK_NULL_VOID(jsColorFilter);
1189         auto colorFilterJsVal = JsConverter::ConvertNapiValueToJsVal(jsColorFilter);
1190         CHECK_NULL_VOID(colorFilterJsVal->IsObject());
1191         info.SetReturnValue(JSRef<JSObject>::Cast(colorFilterJsVal));
1192     }
1193 }
1194 
GetImageSpan()1195 const RefPtr<ImageSpan>& JSImageAttachment::GetImageSpan()
1196 {
1197     return imageSpan_;
1198 }
1199 
SetImageSpan(const RefPtr<ImageSpan> & imageSpan)1200 void JSImageAttachment::SetImageSpan(const RefPtr<ImageSpan>& imageSpan)
1201 {
1202     imageSpan_ = imageSpan;
1203 }
1204 
GetImageOptions() const1205 const ImageSpanOptions& JSImageAttachment::GetImageOptions() const
1206 {
1207     return imageSpan_->GetImageSpanOptions();
1208 }
1209 
1210 // JSNativeCustomSpan
Constructor(const JSCallbackInfo & args)1211 void JSNativeCustomSpan::Constructor(const JSCallbackInfo& args)
1212 {
1213     auto customSpan = Referenced::MakeRefPtr<JSNativeCustomSpan>();
1214     customSpan->IncRefCount();
1215     args.SetReturnValue(Referenced::RawPtr(customSpan));
1216 }
1217 
Destructor(JSNativeCustomSpan * customSpan)1218 void JSNativeCustomSpan::Destructor(JSNativeCustomSpan* customSpan)
1219 {
1220     if (customSpan != nullptr) {
1221         customSpan->DecRefCount();
1222     }
1223 }
1224 
Invalidate(const JSCallbackInfo & info)1225 void JSNativeCustomSpan::Invalidate(const JSCallbackInfo& info)
1226 {
1227     for (const auto& styledStringWeakPtr : spanStringBaseSet_) {
1228         auto styledString = AceType::DynamicCast<SpanString>(styledStringWeakPtr.Upgrade());
1229         if (!styledString) {
1230             continue;
1231         }
1232         styledString->MarkDirtyFrameNode();
1233     }
1234 }
1235 
JSBind(BindingTarget globalObj)1236 void JSNativeCustomSpan::JSBind(BindingTarget globalObj)
1237 {
1238     JSClass<JSNativeCustomSpan>::Declare("NativeCustomSpan");
1239     JSClass<JSNativeCustomSpan>::CustomMethod("invalidate", &JSNativeCustomSpan::Invalidate);
1240     JSClass<JSNativeCustomSpan>::Bind(globalObj, JSNativeCustomSpan::Constructor, JSNativeCustomSpan::Destructor);
1241 }
1242 
AddStyledString(const WeakPtr<SpanStringBase> & spanString)1243 void JSNativeCustomSpan::AddStyledString(const WeakPtr<SpanStringBase>& spanString)
1244 {
1245     spanStringBaseSet_.insert(spanString);
1246 }
1247 
RemoveStyledString(const WeakPtr<SpanStringBase> & spanString)1248 void JSNativeCustomSpan::RemoveStyledString(const WeakPtr<SpanStringBase>& spanString)
1249 {
1250     spanStringBaseSet_.erase(spanString);
1251 }
1252 
1253 // JSCustomSpan
AddStyledString(const WeakPtr<SpanStringBase> & spanString)1254 void JSCustomSpan::AddStyledString(const WeakPtr<SpanStringBase>& spanString)
1255 {
1256     CHECK_NULL_VOID(customSpan_);
1257     customSpan_->AddStyledString(spanString);
1258 }
1259 
RemoveStyledString(const WeakPtr<SpanStringBase> & spanString)1260 void JSCustomSpan::RemoveStyledString(const WeakPtr<SpanStringBase>& spanString)
1261 {
1262     CHECK_NULL_VOID(customSpan_);
1263     customSpan_->RemoveStyledString(spanString);
1264 }
1265 
JSCustomSpan(JSRef<JSObject> customSpanObj,const JSCallbackInfo & args)1266 JSCustomSpan::JSCustomSpan(JSRef<JSObject> customSpanObj, const JSCallbackInfo& args) : customSpanObj_(customSpanObj)
1267 {
1268     auto obj = JSRef<JSObject>::Cast(customSpanObj);
1269     if (obj->IsUndefined()) {
1270         return;
1271     }
1272     JSRef<JSVal> onMeasure = obj->GetProperty("onMeasure");
1273     if (onMeasure->IsFunction()) {
1274         auto jsDrawFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(obj), JSRef<JSFunc>::Cast(onMeasure));
1275         auto onMeasureFunc = JSCustomSpan::ParseOnMeasureFunc(jsDrawFunc, args.GetExecutionContext());
1276         CustomSpan::SetOnMeasure(onMeasureFunc);
1277     }
1278     JSRef<JSVal> onDraw = obj->GetProperty("onDraw");
1279     if (onDraw->IsFunction()) {
1280         auto jsDrawFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(obj), JSRef<JSFunc>::Cast(onDraw));
1281         auto onDrawFunc = JSCustomSpan::ParseOnDrawFunc(jsDrawFunc, args.GetExecutionContext());
1282         CustomSpan::SetOnDraw(onDrawFunc);
1283     }
1284     auto type = customSpanObj->Unwrap<AceType>();
1285     CHECK_NULL_VOID(type);
1286     auto* nativeCustomSpan = AceType::DynamicCast<JSNativeCustomSpan>(type);
1287     customSpan_ = nativeCustomSpan;
1288 }
1289 
JSCustomSpan(JSRef<JSObject> customSpanObj,std::optional<std::function<CustomSpanMetrics (CustomSpanMeasureInfo)>> onMeasure,std::optional<std::function<void (NG::DrawingContext &,CustomSpanOptions)>> onDraw,int32_t start,int32_t end)1290 JSCustomSpan::JSCustomSpan(JSRef<JSObject> customSpanObj,
1291     std::optional<std::function<CustomSpanMetrics(CustomSpanMeasureInfo)>> onMeasure,
1292     std::optional<std::function<void(NG::DrawingContext&, CustomSpanOptions)>> onDraw, int32_t start, int32_t end)
1293     : CustomSpan(onMeasure, onDraw, start, end), customSpanObj_(customSpanObj)
1294 {
1295     auto type = customSpanObj->Unwrap<AceType>();
1296     CHECK_NULL_VOID(type);
1297     auto* nativeCustomSpan = AceType::DynamicCast<JSNativeCustomSpan>(type);
1298     customSpan_ = nativeCustomSpan;
1299 }
1300 
SetJsCustomSpanObject(const JSRef<JSObject> & customSpanObj)1301 void JSCustomSpan::SetJsCustomSpanObject(const JSRef<JSObject>& customSpanObj)
1302 {
1303     customSpanObj_ = customSpanObj;
1304 }
1305 
GetJsCustomSpanObject()1306 JSRef<JSObject>& JSCustomSpan::GetJsCustomSpanObject()
1307 {
1308     return customSpanObj_;
1309 }
GetSubSpan(int32_t start,int32_t end)1310 RefPtr<SpanBase> JSCustomSpan::GetSubSpan(int32_t start, int32_t end)
1311 {
1312     if (end - start > 1) {
1313         return nullptr;
1314     }
1315     RefPtr<SpanBase> spanBase = MakeRefPtr<JSCustomSpan>(customSpanObj_, GetOnMeasure(), GetOnDraw(), start, end);
1316     return spanBase;
1317 }
1318 
IsAttributesEqual(const RefPtr<SpanBase> & other) const1319 bool JSCustomSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
1320 {
1321     auto customSpan = DynamicCast<JSCustomSpan>(other);
1322     if (!customSpan) {
1323         return false;
1324     }
1325     return (customSpan->customSpanObj_)
1326         ->GetLocalHandle()
1327         ->IsStrictEquals(customSpanObj_->GetEcmaVM(), customSpanObj_->GetLocalHandle());
1328 }
1329 
ParseOnMeasureFunc(const RefPtr<JsFunction> & jsDraw,const JSExecutionContext & execCtx)1330 std::function<CustomSpanMetrics(CustomSpanMeasureInfo)> JSCustomSpan::ParseOnMeasureFunc(
1331     const RefPtr<JsFunction>& jsDraw, const JSExecutionContext& execCtx)
1332 {
1333     std::function<CustomSpanMetrics(CustomSpanMeasureInfo)> drawCallback =
1334         [func = std::move(jsDraw), execCtx](CustomSpanMeasureInfo customSpanMeasureInfo) -> CustomSpanMetrics {
1335         JAVASCRIPT_EXECUTION_SCOPE(execCtx);
1336         JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1337         objectTemplate->SetInternalFieldCount(1);
1338         JSRef<JSObject> contextObj = objectTemplate->NewInstance();
1339         contextObj->SetProperty<float>("fontSize", customSpanMeasureInfo.fontSize);
1340         auto jsVal = JSRef<JSVal>::Cast(contextObj);
1341         auto obj = func->ExecuteJS(1, &jsVal);
1342         if (obj->IsObject()) {
1343             JSRef<JSObject> result = JSRef<JSObject>::Cast(obj);
1344             float width = 0;
1345             if (result->HasProperty("width")) {
1346                 auto widthObj = result->GetProperty("width");
1347                 width = widthObj->ToNumber<float>();
1348                 if (LessNotEqual(width, 0.0)) {
1349                     width = 0;
1350                 }
1351             }
1352             std::optional<float> heightOpt;
1353             if (result->HasProperty("height")) {
1354                 auto heightObj = result->GetProperty("height");
1355                 auto height = heightObj->ToNumber<float>();
1356                 if (GreatOrEqual(height, 0.0)) {
1357                     heightOpt = height;
1358                 }
1359             }
1360             return { width, heightOpt };
1361         }
1362         return { 0, 0 };
1363     };
1364     return drawCallback;
1365 }
1366 
ParseOnDrawFunc(const RefPtr<JsFunction> & jsDraw,const JSExecutionContext & execCtx)1367 std::function<void(NG::DrawingContext&, CustomSpanOptions)> JSCustomSpan::ParseOnDrawFunc(
1368     const RefPtr<JsFunction>& jsDraw, const JSExecutionContext& execCtx)
1369 {
1370     std::function<void(NG::DrawingContext&, CustomSpanOptions)> drawCallback =
1371         [func = std::move(jsDraw), execCtx](NG::DrawingContext& context, CustomSpanOptions customSpanOptions) -> void {
1372         JAVASCRIPT_EXECUTION_SCOPE(execCtx);
1373 
1374         JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1375         objectTemplate->SetInternalFieldCount(1);
1376         JSRef<JSObject> contextObj = objectTemplate->NewInstance();
1377         JSRef<JSObject> sizeObj = objectTemplate->NewInstance();
1378         sizeObj->SetProperty<float>("height", PipelineBase::Px2VpWithCurrentDensity(context.height));
1379         sizeObj->SetProperty<float>("width", PipelineBase::Px2VpWithCurrentDensity(context.width));
1380         contextObj->SetPropertyObject("size", sizeObj);
1381 
1382         JSRef<JSObject> sizeInPxObj = objectTemplate->NewInstance();
1383         sizeInPxObj->SetProperty<float>("height", context.height);
1384         sizeInPxObj->SetProperty<float>("width", context.width);
1385         contextObj->SetPropertyObject("sizeInPixel", sizeInPxObj);
1386 
1387         auto engine = EngineHelper::GetCurrentEngine();
1388         CHECK_NULL_VOID(engine);
1389         NativeEngine* nativeEngine = engine->GetNativeEngine();
1390         napi_env env = reinterpret_cast<napi_env>(nativeEngine);
1391         ScopeRAII scope(env);
1392         auto jsCanvas = OHOS::Rosen::Drawing::JsCanvas::CreateJsCanvas(env, &context.canvas);
1393         OHOS::Rosen::Drawing::JsCanvas* unwrapCanvas = nullptr;
1394         napi_unwrap(env, jsCanvas, reinterpret_cast<void**>(&unwrapCanvas));
1395         if (unwrapCanvas) {
1396             unwrapCanvas->SaveCanvas();
1397             unwrapCanvas->ClipCanvas(context.width, context.height);
1398         }
1399         JsiRef<JsiValue> jsCanvasVal = JsConverter::ConvertNapiValueToJsVal(jsCanvas);
1400         contextObj->SetPropertyObject("canvas", jsCanvasVal);
1401 
1402         auto jsVal = JSRef<JSVal>::Cast(contextObj);
1403         panda::Local<JsiValue> value = jsVal.Get().GetLocalHandle();
1404         JSValueWrapper valueWrapper = value;
1405         napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
1406 
1407         napi_wrap(env, nativeValue, &context.canvas, [](napi_env, void*, void*) {}, nullptr, nullptr);
1408         JSRef<JSObject> customSpanOptionsObj = objectTemplate->NewInstance();
1409         customSpanOptionsObj->SetProperty<float>("x", customSpanOptions.x);
1410         customSpanOptionsObj->SetProperty<float>("lineTop", customSpanOptions.lineTop);
1411         customSpanOptionsObj->SetProperty<float>("lineBottom", customSpanOptions.lineBottom);
1412         customSpanOptionsObj->SetProperty<float>("baseline", customSpanOptions.baseline);
1413         auto customSpanOptionsVal = JSRef<JSVal>::Cast(customSpanOptionsObj);
1414         JSRef<JSVal> params[] = { jsVal, customSpanOptionsVal };
1415         func->ExecuteJS(2, params);
1416         if (unwrapCanvas) {
1417             unwrapCanvas->RestoreCanvas();
1418             unwrapCanvas->ResetCanvas();
1419         }
1420     };
1421     return drawCallback;
1422 }
1423 
JSBind(BindingTarget globalObj)1424 void JSLineHeightSpan::JSBind(BindingTarget globalObj)
1425 {
1426     JSClass<JSLineHeightSpan>::Declare("LineHeightStyle");
1427     JSClass<JSLineHeightSpan>::CustomProperty(
1428         "lineHeight", &JSLineHeightSpan::GetLineHeight, &JSLineHeightSpan::SetLineHeight);
1429     JSClass<JSLineHeightSpan>::Bind(globalObj, JSLineHeightSpan::Constructor, JSLineHeightSpan::Destructor);
1430 }
1431 
Constructor(const JSCallbackInfo & args)1432 void JSLineHeightSpan::Constructor(const JSCallbackInfo& args)
1433 {
1434     auto lineHeightSpan = Referenced::MakeRefPtr<JSLineHeightSpan>();
1435     lineHeightSpan->IncRefCount();
1436 
1437     RefPtr<LineHeightSpan> span;
1438     if (args.Length() <= 0 || !args[0]->IsObject()) {
1439         span = AceType::MakeRefPtr<LineHeightSpan>();
1440     } else {
1441         span = JSLineHeightSpan::ParseJSLineHeightSpan(JSRef<JSObject>::Cast(args[0]));
1442     }
1443     lineHeightSpan->lineHeightSpan_ = span;
1444     args.SetReturnValue(Referenced::RawPtr(lineHeightSpan));
1445 }
1446 
Destructor(JSLineHeightSpan * lineHeightSpan)1447 void JSLineHeightSpan::Destructor(JSLineHeightSpan* lineHeightSpan)
1448 {
1449     if (lineHeightSpan != nullptr) {
1450         lineHeightSpan->DecRefCount();
1451     }
1452 }
1453 
ParseJSLineHeightSpan(const JSRef<JSObject> & obj)1454 RefPtr<LineHeightSpan> JSLineHeightSpan::ParseJSLineHeightSpan(const JSRef<JSObject>& obj)
1455 {
1456     if (obj->IsUndefined()) {
1457         return AceType::MakeRefPtr<LineHeightSpan>(CalcDimension(0, DimensionUnit::VP));
1458     }
1459     return AceType::MakeRefPtr<LineHeightSpan>(ParseLengthMetrics(obj));
1460 }
1461 
GetLineHeight(const JSCallbackInfo & info)1462 void JSLineHeightSpan::GetLineHeight(const JSCallbackInfo& info)
1463 {
1464     CHECK_NULL_VOID(lineHeightSpan_);
1465     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(lineHeightSpan_->GetLineHeight().ConvertToVp())));
1466     info.SetReturnValue(ret);
1467 }
1468 
SetLineHeight(const JSCallbackInfo & info)1469 void JSLineHeightSpan::SetLineHeight(const JSCallbackInfo& info) {}
1470 
GetLineHeightSpan()1471 RefPtr<LineHeightSpan>& JSLineHeightSpan::GetLineHeightSpan()
1472 {
1473     return lineHeightSpan_;
1474 }
1475 
SetLineHeightSpan(const RefPtr<LineHeightSpan> & lineHeightSpan)1476 void JSLineHeightSpan::SetLineHeightSpan(const RefPtr<LineHeightSpan>& lineHeightSpan)
1477 {
1478     lineHeightSpan_ = lineHeightSpan;
1479 }
1480 
JSBind(BindingTarget globalObj)1481 void JSParagraphStyleSpan::JSBind(BindingTarget globalObj)
1482 {
1483     JSClass<JSParagraphStyleSpan>::Declare("ParagraphStyle");
1484     JSClass<JSParagraphStyleSpan>::CustomProperty(
1485         "textAlign", &JSParagraphStyleSpan::GetTextAlign, &JSParagraphStyleSpan::SetTextAlign);
1486     JSClass<JSParagraphStyleSpan>::CustomProperty(
1487         "textVerticalAlign", &JSParagraphStyleSpan::GetTextVerticalAlign, &JSParagraphStyleSpan::SetTextVerticalAlign);
1488     JSClass<JSParagraphStyleSpan>::CustomProperty(
1489         "textIndent", &JSParagraphStyleSpan::GetTextIndent, &JSParagraphStyleSpan::SetTextIndent);
1490     JSClass<JSParagraphStyleSpan>::CustomProperty(
1491         "maxLines", &JSParagraphStyleSpan::GetMaxLines, &JSParagraphStyleSpan::SetMaxLines);
1492     JSClass<JSParagraphStyleSpan>::CustomProperty(
1493         "overflow", &JSParagraphStyleSpan::GetOverflow, &JSParagraphStyleSpan::SetOverflow);
1494     JSClass<JSParagraphStyleSpan>::CustomProperty(
1495         "wordBreak", &JSParagraphStyleSpan::GetWordBreak, &JSParagraphStyleSpan::SetWordBreak);
1496     JSClass<JSParagraphStyleSpan>::CustomProperty(
1497         "leadingMargin", &JSParagraphStyleSpan::GetLeadingMargin, &JSParagraphStyleSpan::SetLeadingMargin);
1498     JSClass<JSParagraphStyleSpan>::CustomProperty(
1499         "paragraphSpacing", &JSParagraphStyleSpan::GetParagraphSpacing, &JSParagraphStyleSpan::SetParagraphSpacing);
1500     JSClass<JSParagraphStyleSpan>::Bind(globalObj, JSParagraphStyleSpan::Constructor, JSParagraphStyleSpan::Destructor);
1501 }
1502 
Constructor(const JSCallbackInfo & args)1503 void JSParagraphStyleSpan::Constructor(const JSCallbackInfo& args)
1504 {
1505     auto paragraphSpan = Referenced::MakeRefPtr<JSParagraphStyleSpan>();
1506     paragraphSpan->IncRefCount();
1507 
1508     RefPtr<ParagraphStyleSpan> span;
1509     if (args.Length() <= 0 || !args[0]->IsObject()) {
1510         SpanParagraphStyle paragraphStyle;
1511         span = AceType::MakeRefPtr<ParagraphStyleSpan>(paragraphStyle);
1512     } else {
1513         span = JSParagraphStyleSpan::ParseJsParagraphStyleSpan(JSRef<JSObject>::Cast(args[0]));
1514     }
1515     paragraphSpan->paragraphStyleSpan_ = span;
1516     args.SetReturnValue(Referenced::RawPtr(paragraphSpan));
1517 }
1518 
Destructor(JSParagraphStyleSpan * paragragrahSpan)1519 void JSParagraphStyleSpan::Destructor(JSParagraphStyleSpan* paragragrahSpan)
1520 {
1521     if (paragragrahSpan != nullptr) {
1522         paragragrahSpan->DecRefCount();
1523     }
1524 }
1525 
ParseJsParagraphStyleSpan(const JSRef<JSObject> & obj)1526 RefPtr<ParagraphStyleSpan> JSParagraphStyleSpan::ParseJsParagraphStyleSpan(const JSRef<JSObject>& obj)
1527 {
1528     SpanParagraphStyle paragraphStyle;
1529     ParseJsTextAlign(obj, paragraphStyle);
1530     ParseJsTextVerticalAlign(obj, paragraphStyle);
1531     ParseJsTextIndent(obj, paragraphStyle);
1532     ParseJsMaxLines(obj, paragraphStyle);
1533     ParseJsTextOverflow(obj, paragraphStyle);
1534     ParseJsWordBreak(obj, paragraphStyle);
1535     ParseJsLeadingMargin(obj, paragraphStyle);
1536     ParseParagraphSpacing(obj, paragraphStyle);
1537     return AceType::MakeRefPtr<ParagraphStyleSpan>(paragraphStyle);
1538 }
1539 
ParseJsTextAlign(const JSRef<JSObject> & obj,SpanParagraphStyle & paragraphStyle)1540 void JSParagraphStyleSpan::ParseJsTextAlign(const JSRef<JSObject>& obj, SpanParagraphStyle& paragraphStyle)
1541 {
1542     if (!obj->HasProperty("textAlign")) {
1543         return;
1544     }
1545     auto textAlignObj = obj->GetProperty("textAlign");
1546     int32_t value = 0;
1547     if (!textAlignObj->IsNull() && textAlignObj->IsNumber()) {
1548         value = textAlignObj->ToNumber<int32_t>();
1549     }
1550     if (value < 0 || value >= static_cast<int32_t>(TEXT_ALIGNS.size())) {
1551         value = 0;
1552     }
1553     paragraphStyle.align = TEXT_ALIGNS[value];
1554 }
1555 
ParseJsTextVerticalAlign(const JSRef<JSObject> & obj,SpanParagraphStyle & paragraphStyle)1556 void JSParagraphStyleSpan::ParseJsTextVerticalAlign(const JSRef<JSObject>& obj, SpanParagraphStyle& paragraphStyle)
1557 {
1558     if (!obj->HasProperty("textVerticalAlign")) {
1559         return;
1560     }
1561     auto textVerticalAlignObj = obj->GetProperty("textVerticalAlign");
1562     int32_t value = 0;
1563     if (!textVerticalAlignObj->IsNull() && textVerticalAlignObj->IsNumber()) {
1564         value = textVerticalAlignObj->ToNumber<int32_t>();
1565     }
1566     if (value < 0 || value >= static_cast<int32_t>(TEXT_VERTICAL_ALIGNS.size())) {
1567         value = 0;
1568     }
1569     paragraphStyle.textVerticalAlign = TEXT_VERTICAL_ALIGNS[value];
1570 }
1571 
ParseJsTextIndent(const JSRef<JSObject> & obj,SpanParagraphStyle & paragraphStyle)1572 void JSParagraphStyleSpan::ParseJsTextIndent(const JSRef<JSObject>& obj, SpanParagraphStyle& paragraphStyle)
1573 {
1574     if (!obj->HasProperty("textIndent")) {
1575         return;
1576     }
1577     auto textIndent = obj->GetProperty("textIndent");
1578     CalcDimension size;
1579     if (!textIndent->IsNull() && textIndent->IsObject()) {
1580         auto textIndentObj = JSRef<JSObject>::Cast(textIndent);
1581         auto value = 0.0;
1582         auto textIndentVal = textIndentObj->GetProperty("value");
1583         if (!textIndentVal->IsNull() && textIndentVal->IsNumber()) {
1584             value = textIndentVal->ToNumber<float>();
1585         }
1586         auto unit = DimensionUnit::VP;
1587         auto textIndentUnit = textIndentObj->GetProperty("unit");
1588         if (!textIndentUnit->IsNull() && textIndentUnit->IsNumber()) {
1589             unit = static_cast<DimensionUnit>(textIndentUnit->ToNumber<int32_t>());
1590         }
1591         if (value >= 0 && unit != DimensionUnit::PERCENT) {
1592             size = CalcDimension(value, unit);
1593         }
1594     }
1595     paragraphStyle.textIndent = size;
1596 }
1597 
ParseJsMaxLines(const JSRef<JSObject> & obj,SpanParagraphStyle & paragraphStyle)1598 void JSParagraphStyleSpan::ParseJsMaxLines(const JSRef<JSObject>& obj, SpanParagraphStyle& paragraphStyle)
1599 {
1600     if (!obj->HasProperty("maxLines")) {
1601         return;
1602     }
1603     JSRef<JSVal> args = obj->GetProperty("maxLines");
1604     int32_t value = Infinity<int32_t>();
1605     if (args->ToString() != "Infinity") {
1606         JSContainerBase::ParseJsInt32(args, value);
1607     }
1608     if (!args->IsUndefined()) {
1609         paragraphStyle.maxLines = value;
1610     }
1611 }
1612 
ParseJsTextOverflow(const JSRef<JSObject> & obj,SpanParagraphStyle & paragraphStyle)1613 void JSParagraphStyleSpan::ParseJsTextOverflow(const JSRef<JSObject>& obj, SpanParagraphStyle& paragraphStyle)
1614 {
1615     if (!obj->HasProperty("overflow")) {
1616         return;
1617     }
1618     int32_t overflow = 0;
1619     JSRef<JSVal> overflowValue = obj->GetProperty("overflow");
1620     if (overflowValue->IsNumber()) {
1621         overflow = overflowValue->ToNumber<int32_t>();
1622     }
1623     if (overflowValue->IsUndefined() || overflow < 0 || overflow >= static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
1624         overflow = 0;
1625     }
1626     paragraphStyle.textOverflow = TEXT_OVERFLOWS[overflow];
1627 }
ParseJsWordBreak(const JSRef<JSObject> & obj,SpanParagraphStyle & paragraphStyle)1628 void JSParagraphStyleSpan::ParseJsWordBreak(const JSRef<JSObject>& obj, SpanParagraphStyle& paragraphStyle)
1629 {
1630     if (!obj->HasProperty("wordBreak")) {
1631         return;
1632     }
1633     JSRef<JSVal> args = obj->GetProperty("wordBreak");
1634     int32_t index = WORD_BREAK_TYPES_DEFAULT;
1635     if (args->IsNumber()) {
1636         index = args->ToNumber<int32_t>();
1637     }
1638     if (index < 0 || index >= static_cast<int32_t>(WORD_BREAK_TYPES.size())) {
1639         index = 0;
1640     }
1641     paragraphStyle.wordBreak = WORD_BREAK_TYPES[index];
1642 }
1643 
IsPixelMap(const JSRef<JSVal> & jsValue)1644 bool JSParagraphStyleSpan::IsPixelMap(const JSRef<JSVal>& jsValue)
1645 {
1646     if (!jsValue->IsObject()) {
1647         return false;
1648     }
1649     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
1650     if (jsObj->IsUndefined()) {
1651         return false;
1652     }
1653     JSRef<JSVal> func = jsObj->GetProperty("readPixelsToBuffer");
1654     return (!func->IsNull() && func->IsFunction());
1655 }
1656 
ParseJsLeadingMargin(const JSRef<JSObject> & obj,SpanParagraphStyle & paragraphStyle)1657 void JSParagraphStyleSpan::ParseJsLeadingMargin(const JSRef<JSObject>& obj, SpanParagraphStyle& paragraphStyle)
1658 {
1659     if (!obj->HasProperty("leadingMargin")) {
1660         return;
1661     }
1662     auto margin = std::make_optional<NG::LeadingMargin>();
1663     auto leadingMargin = obj->GetProperty("leadingMargin");
1664     if (!leadingMargin->IsNull() && leadingMargin->IsObject()) {
1665         JSRef<JSObject> leadingMarginObject = JSRef<JSObject>::Cast(leadingMargin);
1666         // LeadingMarginPlaceholder
1667         if (leadingMarginObject->HasProperty("pixelMap")) {
1668             ParseLeadingMarginPixelMap(leadingMarginObject, margin, leadingMargin);
1669         } else { // LengthMetrics
1670             CalcDimension width;
1671             auto value = 0.0;
1672             auto widthVal = leadingMarginObject->GetProperty("value");
1673             if (!widthVal->IsNull() && widthVal->IsNumber()) {
1674                 value = widthVal->ToNumber<float>();
1675             }
1676             auto unit = DimensionUnit::VP;
1677             auto widthUnit = leadingMarginObject->GetProperty("unit");
1678             if (!widthUnit->IsNull() && widthUnit->IsNumber()) {
1679                 unit = static_cast<DimensionUnit>(widthUnit->ToNumber<int32_t>());
1680             }
1681             if (value >= 0 && unit != DimensionUnit::PERCENT) {
1682                 width = CalcDimension(value, unit);
1683             }
1684             margin->size = NG::LeadingMarginSize(width, Dimension(0.0, width.Unit()));
1685         }
1686     }
1687     paragraphStyle.leadingMargin = margin;
1688 }
1689 
ParseParagraphSpacing(const JSRef<JSObject> & obj,SpanParagraphStyle & paragraphStyle)1690 void JSParagraphStyleSpan::ParseParagraphSpacing(const JSRef<JSObject>& obj, SpanParagraphStyle& paragraphStyle)
1691 {
1692     if (!obj->HasProperty("paragraphSpacing")) {
1693         return;
1694     }
1695     auto paragraphSpacing = obj->GetProperty("paragraphSpacing");
1696     CalcDimension size;
1697     if (!paragraphSpacing->IsNull() && paragraphSpacing->IsObject()) {
1698         auto paragraphSpacingObj = JSRef<JSObject>::Cast(paragraphSpacing);
1699         auto value = 0.0;
1700         auto paragraphSpacingVal = paragraphSpacingObj->GetProperty("value");
1701         if (!paragraphSpacingVal->IsNull() && paragraphSpacingVal->IsNumber()) {
1702             value = paragraphSpacingVal->ToNumber<float>();
1703         }
1704         auto unit = DimensionUnit::VP;
1705         auto paragraphSpacingUnit = paragraphSpacingObj->GetProperty("unit");
1706         if (!paragraphSpacingUnit->IsNull() && paragraphSpacingUnit->IsNumber()) {
1707             unit = static_cast<DimensionUnit>(paragraphSpacingUnit->ToNumber<int32_t>());
1708         }
1709         if (value >= 0 && unit != DimensionUnit::PERCENT) {
1710             size = CalcDimension(value, unit);
1711         }
1712     }
1713     paragraphStyle.paragraphSpacing = size;
1714 }
1715 
ParseLeadingMarginPixelMap(const JSRef<JSObject> & leadingMarginObject,std::optional<NG::LeadingMargin> & margin,const JsiRef<JsiValue> & leadingMargin)1716 void JSParagraphStyleSpan::ParseLeadingMarginPixelMap(const JSRef<JSObject>& leadingMarginObject,
1717     std::optional<NG::LeadingMargin>& margin, const JsiRef<JsiValue>& leadingMargin)
1718 {
1719     JSRef<JSVal> placeholder = leadingMarginObject->GetProperty("pixelMap");
1720     if (IsPixelMap(placeholder)) {
1721 #if defined(PIXEL_MAP_SUPPORTED)
1722         auto pixelMap = CreatePixelMapFromNapiValue(placeholder);
1723         margin->pixmap = pixelMap;
1724 #endif
1725     }
1726     JSRef<JSVal> sizeVal = leadingMarginObject->GetProperty("size");
1727     if (!sizeVal->IsUndefined() && sizeVal->IsArray()) {
1728         auto rangeArray = JSRef<JSArray>::Cast(sizeVal);
1729         JSRef<JSVal> widthVal = rangeArray->GetValueAt(0);
1730         JSRef<JSVal> heightVal = rangeArray->GetValueAt(1);
1731         CalcDimension width;
1732         CalcDimension height;
1733         JSContainerBase::ParseJsDimensionVp(widthVal, width);
1734         JSContainerBase::ParseJsDimensionVp(heightVal, height);
1735         if (LessNotEqual(width.Value(), 0.0)) {
1736             width = Dimension(0.0, width.Unit());
1737         }
1738         if (LessNotEqual(height.Value(), 0.0)) {
1739             height = Dimension(0.0, height.Unit());
1740         }
1741         margin->size = NG::LeadingMarginSize(width, height);
1742     } else if (sizeVal->IsUndefined()) {
1743         std::string resWidthStr;
1744         if (JSContainerBase::ParseJsString(leadingMargin, resWidthStr)) {
1745             CalcDimension width;
1746             JSContainerBase::ParseJsDimensionVp(leadingMargin, width);
1747             margin->size = NG::LeadingMarginSize(width, Dimension(0.0, width.Unit()));
1748         }
1749     }
1750 }
1751 
GetTextAlign(const JSCallbackInfo & info)1752 void JSParagraphStyleSpan::GetTextAlign(const JSCallbackInfo& info)
1753 {
1754     CHECK_NULL_VOID(paragraphStyleSpan_);
1755     if (!paragraphStyleSpan_->GetParagraphStyle().align.has_value()) {
1756         return;
1757     }
1758     auto ret = JSRef<JSVal>::Make(
1759         JSVal(ToJSValue(static_cast<int32_t>(paragraphStyleSpan_->GetParagraphStyle().align.value()))));
1760     info.SetReturnValue(ret);
1761 }
1762 
SetTextAlign(const JSCallbackInfo & info)1763 void JSParagraphStyleSpan::SetTextAlign(const JSCallbackInfo& info) {}
1764 
GetTextVerticalAlign(const JSCallbackInfo & info)1765 void JSParagraphStyleSpan::GetTextVerticalAlign(const JSCallbackInfo& info)
1766 {
1767     CHECK_NULL_VOID(paragraphStyleSpan_);
1768     if (!paragraphStyleSpan_->GetParagraphStyle().textVerticalAlign.has_value()) {
1769         return;
1770     }
1771     auto ret = JSRef<JSVal>::Make(
1772         JSVal(ToJSValue(static_cast<int32_t>(paragraphStyleSpan_->GetParagraphStyle().textVerticalAlign.value()))));
1773     info.SetReturnValue(ret);
1774 }
1775 
SetTextVerticalAlign(const JSCallbackInfo & info)1776 void JSParagraphStyleSpan::SetTextVerticalAlign(const JSCallbackInfo& info) {}
1777 
GetTextIndent(const JSCallbackInfo & info)1778 void JSParagraphStyleSpan::GetTextIndent(const JSCallbackInfo& info)
1779 {
1780     CHECK_NULL_VOID(paragraphStyleSpan_);
1781     if (!paragraphStyleSpan_->GetParagraphStyle().textIndent.has_value()) {
1782         return;
1783     }
1784     auto ret =
1785         JSRef<JSVal>::Make(JSVal(ToJSValue(paragraphStyleSpan_->GetParagraphStyle().textIndent.value().ConvertToVp())));
1786     info.SetReturnValue(ret);
1787 }
1788 
SetTextIndent(const JSCallbackInfo & info)1789 void JSParagraphStyleSpan::SetTextIndent(const JSCallbackInfo& info) {}
1790 
GetMaxLines(const JSCallbackInfo & info)1791 void JSParagraphStyleSpan::GetMaxLines(const JSCallbackInfo& info)
1792 {
1793     CHECK_NULL_VOID(paragraphStyleSpan_);
1794     if (!paragraphStyleSpan_->GetParagraphStyle().maxLines.has_value()) {
1795         return;
1796     }
1797     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(paragraphStyleSpan_->GetParagraphStyle().maxLines.value())));
1798     info.SetReturnValue(ret);
1799 }
SetMaxLines(const JSCallbackInfo & info)1800 void JSParagraphStyleSpan::SetMaxLines(const JSCallbackInfo& info) {}
1801 
GetOverflow(const JSCallbackInfo & info)1802 void JSParagraphStyleSpan::GetOverflow(const JSCallbackInfo& info)
1803 {
1804     CHECK_NULL_VOID(paragraphStyleSpan_);
1805     if (!paragraphStyleSpan_->GetParagraphStyle().textOverflow.has_value()) {
1806         return;
1807     }
1808     auto ret = JSRef<JSVal>::Make(
1809         JSVal(ToJSValue(static_cast<int32_t>(paragraphStyleSpan_->GetParagraphStyle().textOverflow.value()))));
1810     info.SetReturnValue(ret);
1811 }
SetOverflow(const JSCallbackInfo & info)1812 void JSParagraphStyleSpan::SetOverflow(const JSCallbackInfo& info) {}
1813 
GetWordBreak(const JSCallbackInfo & info)1814 void JSParagraphStyleSpan::GetWordBreak(const JSCallbackInfo& info)
1815 {
1816     CHECK_NULL_VOID(paragraphStyleSpan_);
1817     if (!paragraphStyleSpan_->GetParagraphStyle().wordBreak.has_value()) {
1818         return;
1819     }
1820     auto ret = JSRef<JSVal>::Make(
1821         JSVal(ToJSValue(static_cast<int32_t>(paragraphStyleSpan_->GetParagraphStyle().wordBreak.value()))));
1822     info.SetReturnValue(ret);
1823 }
SetWordBreak(const JSCallbackInfo & info)1824 void JSParagraphStyleSpan::SetWordBreak(const JSCallbackInfo& info) {}
1825 
GetLeadingMargin(const JSCallbackInfo & info)1826 void JSParagraphStyleSpan::GetLeadingMargin(const JSCallbackInfo& info)
1827 {
1828     CHECK_NULL_VOID(paragraphStyleSpan_);
1829     if (!paragraphStyleSpan_->GetParagraphStyle().leadingMargin.has_value()) {
1830         return;
1831     }
1832     auto leadingMargin = paragraphStyleSpan_->GetParagraphStyle().leadingMargin.value();
1833     JSRef<JSVal> ret;
1834 #ifdef PIXEL_MAP_SUPPORTED
1835     if (leadingMargin.pixmap) {
1836         auto lmObj = JSRef<JSObject>::New();
1837         auto size = JSRef<JSArray>::New();
1838         size->SetValueAt(0, JSRef<JSVal>::Make(ToJSValue(Dimension(leadingMargin.size.Width()).ConvertToVp())));
1839         size->SetValueAt(1, JSRef<JSVal>::Make(ToJSValue(Dimension(leadingMargin.size.Height()).ConvertToVp())));
1840         lmObj->SetPropertyObject("pixelMap", ConvertPixmap(leadingMargin.pixmap));
1841         lmObj->SetPropertyObject("size", size);
1842         ret = JSRef<JSVal>::Cast(lmObj);
1843     } else {
1844         ret = JSRef<JSVal>::Make(JSVal(ToJSValue(Dimension(leadingMargin.size.Width()).ConvertToVp())));
1845     }
1846 #else
1847     ret = JSRef<JSVal>::Make(JSVal(ToJSValue(Dimension(leadingMargin.size.Width()).ConvertToVp())));
1848 #endif
1849     info.SetReturnValue(ret);
1850 }
1851 
SetLeadingMargin(const JSCallbackInfo & info)1852 void JSParagraphStyleSpan::SetLeadingMargin(const JSCallbackInfo& info) {}
1853 
GetParagraphSpacing(const JSCallbackInfo & info)1854 void JSParagraphStyleSpan::GetParagraphSpacing(const JSCallbackInfo& info)
1855 {
1856     CHECK_NULL_VOID(paragraphStyleSpan_);
1857     auto paragraphSpacing = paragraphStyleSpan_->GetParagraphStyle().paragraphSpacing;
1858     CHECK_EQUAL_VOID(paragraphSpacing.has_value(), false);
1859     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(paragraphSpacing.value().ConvertToVp())));
1860     info.SetReturnValue(ret);
1861 }
1862 
SetParagraphSpacing(const JSCallbackInfo & info)1863 void JSParagraphStyleSpan::SetParagraphSpacing(const JSCallbackInfo& info) {}
1864 
GetParagraphStyleSpan()1865 RefPtr<ParagraphStyleSpan>& JSParagraphStyleSpan::GetParagraphStyleSpan()
1866 {
1867     return paragraphStyleSpan_;
1868 }
1869 
SetParagraphStyleSpan(const RefPtr<ParagraphStyleSpan> & paragraphStyleSpan)1870 void JSParagraphStyleSpan::SetParagraphStyleSpan(const RefPtr<ParagraphStyleSpan>& paragraphStyleSpan)
1871 {
1872     paragraphStyleSpan_ = paragraphStyleSpan;
1873 }
1874 
1875 // JSExtSpan
JSExtSpan(JSRef<JSObject> extSpanObj)1876 JSExtSpan::JSExtSpan(JSRef<JSObject> extSpanObj) : extSpanObj_(extSpanObj) {}
1877 
JSExtSpan(JSRef<JSObject> extSpanObj,int32_t start,int32_t end)1878 JSExtSpan::JSExtSpan(JSRef<JSObject> extSpanObj, int32_t start, int32_t end)
1879     : ExtSpan(start, end), extSpanObj_(extSpanObj)
1880 {}
1881 
GetSubSpan(int32_t start,int32_t end)1882 RefPtr<SpanBase> JSExtSpan::GetSubSpan(int32_t start, int32_t end)
1883 {
1884     RefPtr<SpanBase> spanBase = MakeRefPtr<JSExtSpan>(extSpanObj_, start, end);
1885     return spanBase;
1886 }
1887 
IsAttributesEqual(const RefPtr<SpanBase> & other) const1888 bool JSExtSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
1889 {
1890     auto extSpan = DynamicCast<JSExtSpan>(other);
1891     if (!extSpan) {
1892         return false;
1893     }
1894     return (extSpan->extSpanObj_)
1895         ->GetLocalHandle()
1896         ->IsStrictEquals(extSpanObj_->GetEcmaVM(), extSpanObj_->GetLocalHandle());
1897 }
1898 
SetJsExtSpanObject(const JSRef<JSObject> & extSpanObj)1899 void JSExtSpan::SetJsExtSpanObject(const JSRef<JSObject>& extSpanObj)
1900 {
1901     extSpanObj_ = extSpanObj;
1902 }
1903 
GetJsExtSpanObject()1904 JSRef<JSObject>& JSExtSpan::GetJsExtSpanObject()
1905 {
1906     return extSpanObj_;
1907 }
1908 
JSBind(BindingTarget globalObj)1909 void JSBackgroundColorSpan::JSBind(BindingTarget globalObj)
1910 {
1911     JSClass<JSBackgroundColorSpan>::Declare("BackgroundColorStyle");
1912     JSClass<JSBackgroundColorSpan>::CustomProperty(
1913         "textBackgroundStyle", &JSBackgroundColorSpan::GetBackgroundColor, &JSBackgroundColorSpan::SetBackgroundColor);
1914     JSClass<JSBackgroundColorSpan>::Bind(
1915         globalObj, JSBackgroundColorSpan::Constructor, JSBackgroundColorSpan::Destructor);
1916 }
1917 
Constructor(const JSCallbackInfo & args)1918 void JSBackgroundColorSpan::Constructor(const JSCallbackInfo& args)
1919 {
1920     auto backgroundColor = Referenced::MakeRefPtr<JSBackgroundColorSpan>();
1921     CHECK_NULL_VOID(backgroundColor);
1922     backgroundColor->IncRefCount();
1923     RefPtr<BackgroundColorSpan> span;
1924     if (args.Length() <= 0 || !args[0]->IsObject()) {
1925         span = AceType::MakeRefPtr<BackgroundColorSpan>();
1926     } else {
1927         span = JSBackgroundColorSpan::ParseJSBackgroundColorSpan(args);
1928     }
1929     CHECK_NULL_VOID(span);
1930     backgroundColor->backgroundColorSpan_ = span;
1931     args.SetReturnValue(Referenced::RawPtr(backgroundColor));
1932 }
1933 
Destructor(JSBackgroundColorSpan * backgroundColor)1934 void JSBackgroundColorSpan::Destructor(JSBackgroundColorSpan* backgroundColor)
1935 {
1936     if (backgroundColor != nullptr) {
1937         backgroundColor->DecRefCount();
1938     }
1939 }
1940 
ParseJSBackgroundColorSpan(const JSCallbackInfo & info)1941 RefPtr<BackgroundColorSpan> JSBackgroundColorSpan::ParseJSBackgroundColorSpan(const JSCallbackInfo& info)
1942 {
1943     auto textBackgroundValue = JSContainerSpan::ParseTextBackgroundStyle(info);
1944     return AceType::MakeRefPtr<BackgroundColorSpan>(textBackgroundValue);
1945 }
1946 
GetBackgroundColor(const JSCallbackInfo & info)1947 void JSBackgroundColorSpan::GetBackgroundColor(const JSCallbackInfo& info)
1948 {
1949     CHECK_NULL_VOID(backgroundColorSpan_);
1950     auto backgroundColorStyle = backgroundColorSpan_->GetBackgroundColor();
1951     JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1952     objectTemplate->SetInternalFieldCount(1);
1953     JSRef<JSObject> backgroundColorObj = objectTemplate->NewInstance();
1954     backgroundColorObj->SetProperty<std::string>("color", backgroundColorStyle.backgroundColor->ColorToString());
1955     backgroundColorObj->SetProperty<std::string>(
1956         "BorderRadiusProperty", backgroundColorStyle.backgroundRadius->ToString());
1957     info.SetReturnValue(backgroundColorObj);
1958 }
1959 
SetBackgroundColor(const JSCallbackInfo & info)1960 void JSBackgroundColorSpan::SetBackgroundColor(const JSCallbackInfo& info) {};
1961 
GetBackgroundColorSpan()1962 RefPtr<BackgroundColorSpan>& JSBackgroundColorSpan::GetBackgroundColorSpan()
1963 {
1964     return backgroundColorSpan_;
1965 }
1966 
SetBackgroundColorSpan(const RefPtr<BackgroundColorSpan> & backgroundColorSpan)1967 void JSBackgroundColorSpan::SetBackgroundColorSpan(const RefPtr<BackgroundColorSpan>& backgroundColorSpan)
1968 {
1969     backgroundColorSpan_ = backgroundColorSpan;
1970 }
1971 
1972 // JSUrlSpan
JSBind(BindingTarget globalObj)1973 void JSUrlSpan::JSBind(BindingTarget globalObj)
1974 {
1975     JSClass<JSUrlSpan>::Declare("UrlStyle");
1976     JSClass<JSUrlSpan>::CustomProperty(
1977         "url", &JSUrlSpan::GetUrlContext, &JSUrlSpan::SetUrlContext);
1978     JSClass<JSUrlSpan>::Bind(globalObj, JSUrlSpan::Constructor, JSUrlSpan::Destructor);
1979 }
1980 
Constructor(const JSCallbackInfo & args)1981 void JSUrlSpan::Constructor(const JSCallbackInfo& args)
1982 {
1983     auto urlSpan = Referenced::MakeRefPtr<JSUrlSpan>();
1984     urlSpan->IncRefCount();
1985     RefPtr<UrlSpan> span;
1986     if (args.Length() > 0 && args[0]->IsString()) {
1987         auto address = args[0]->ToString();
1988         span = AceType::MakeRefPtr<UrlSpan>(address);
1989     } else {
1990         span = AceType::MakeRefPtr<UrlSpan>();
1991     }
1992     CHECK_NULL_VOID(span);
1993     urlSpan->urlContextSpan_ = span;
1994     args.SetReturnValue(Referenced::RawPtr(urlSpan));
1995 }
1996 
Destructor(JSUrlSpan * urlSpan)1997 void JSUrlSpan::Destructor(JSUrlSpan* urlSpan)
1998 {
1999     if (urlSpan != nullptr) {
2000         urlSpan->DecRefCount();
2001     }
2002 }
2003 
GetUrlContext(const JSCallbackInfo & info)2004 void JSUrlSpan::GetUrlContext(const JSCallbackInfo& info)
2005 {
2006     CHECK_NULL_VOID(urlContextSpan_);
2007     auto ret = JSRef<JSVal>::Make(JSVal(ToJSValue(urlContextSpan_->GetUrlSpanAddress())));
2008     info.SetReturnValue(ret);
2009 }
2010 
SetUrlContext(const JSCallbackInfo & info)2011 void JSUrlSpan::SetUrlContext(const JSCallbackInfo& info) {}
2012 
GetUrlSpan()2013 const RefPtr<UrlSpan>& JSUrlSpan::GetUrlSpan()
2014 {
2015     return urlContextSpan_;
2016 }
2017 
SetUrlSpan(const RefPtr<UrlSpan> & urlSpan)2018 void JSUrlSpan::SetUrlSpan(const RefPtr<UrlSpan>& urlSpan)
2019 {
2020     urlContextSpan_ = urlSpan;
2021 }
2022 } // namespace OHOS::Ace::Framework