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