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