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