• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/bridge/declarative_frontend/style_string/js_span_object.h"
17 
18 #include <numeric>
19 #include <string>
20 
21 #include "canvas_napi/js_canvas.h"
22 
23 #include "base/geometry/calc_dimension.h"
24 #include "base/geometry/dimension.h"
25 #include "base/log/ace_scoring_log.h"
26 #include "base/memory/ace_type.h"
27 #include "bridge/common/utils/engine_helper.h"
28 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
29 #include "bridge/declarative_frontend/engine/js_converter.h"
30 #include "bridge/declarative_frontend/engine/js_types.h"
31 #include "bridge/declarative_frontend/jsview/js_richeditor.h"
32 #include "bridge/declarative_frontend/jsview/js_utils.h"
33 #include "core/components/common/layout/constants.h"
34 #include "core/components/common/properties/text_style.h"
35 #include "core/components/text/text_theme.h"
36 #include "core/components/text_field/textfield_theme.h"
37 #include "core/components_ng/pattern/text/span/span_object.h"
38 #include "core/components_ng/pattern/text/span/span_string.h"
39 #include "core/components_ng/render/paragraph.h"
40 #include "frameworks/bridge/common/utils/utils.h"
41 #include "frameworks/bridge/declarative_frontend/jsview/js_container_span.h"
42 #include "frameworks/bridge/declarative_frontend/jsview/js_image.h"
43 #include "frameworks/bridge/declarative_frontend/jsview/js_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