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