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