• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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/jsview/js_text.h"
17 
18 #include <cstdint>
19 #include <sstream>
20 #include <string>
21 #include <vector>
22 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
23 #include "core/components_ng/pattern/text/text_layout_property.h"
24 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
25 #endif
26 
27 #include "base/geometry/dimension.h"
28 #include "base/log/ace_scoring_log.h"
29 #include "base/log/ace_trace.h"
30 #include "base/utils/utils.h"
31 #include "bridge/common/utils/utils.h"
32 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_theme_utils.h"
33 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
34 #include "bridge/declarative_frontend/engine/functions/js_drag_function.h"
35 #include "bridge/declarative_frontend/engine/functions/js_function.h"
36 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
37 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
38 #include "bridge/declarative_frontend/jsview/js_layout_manager.h"
39 #include "bridge/declarative_frontend/jsview/js_text.h"
40 #include "bridge/declarative_frontend/jsview/js_utils.h"
41 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
42 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
43 #include "bridge/declarative_frontend/jsview/models/text_model_impl.h"
44 #include "bridge/declarative_frontend/style_string/js_span_string.h"
45 #include "bridge/declarative_frontend/view_stack_processor.h"
46 #include "core/common/container.h"
47 #include "core/components/common/layout/constants.h"
48 #include "core/components/common/properties/text_style_parser.h"
49 #include "core/components_ng/pattern/text/text_model_ng.h"
50 #include "core/event/ace_event_handler.h"
51 #include "core/pipeline/pipeline_base.h"
52 
53 namespace OHOS::Ace {
54 
55 std::unique_ptr<TextModel> TextModel::instance_ = nullptr;
56 std::mutex TextModel::mutex_;
57 
GetInstance()58 TextModel* TextModel::GetInstance()
59 {
60 #ifdef NG_BUILD
61     static NG::TextModelNG instance;
62     return &instance;
63 #else
64     if (Container::IsCurrentUseNewPipeline()) {
65         static NG::TextModelNG instance;
66         return &instance;
67     } else {
68         static Framework::TextModelImpl instance;
69         return &instance;
70     }
71 #endif
72 }
73 
74 } // namespace OHOS::Ace
75 
76 namespace OHOS::Ace::Framework {
77 namespace {
78 
79 const std::vector<TextCase> TEXT_CASES = { TextCase::NORMAL, TextCase::LOWERCASE, TextCase::UPPERCASE };
80 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
81     TextOverflow::MARQUEE };
82 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
83 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END, TextAlign::JUSTIFY,
84     TextAlign::LEFT, TextAlign::RIGHT };
85 const std::vector<TextHeightAdaptivePolicy> HEIGHT_ADAPTIVE_POLICY = { TextHeightAdaptivePolicy::MAX_LINES_FIRST,
86     TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST };
87 const std::vector<LineBreakStrategy> LINE_BREAK_STRATEGY_TYPES = { LineBreakStrategy::GREEDY,
88     LineBreakStrategy::HIGH_QUALITY, LineBreakStrategy::BALANCED };
89 const std::vector<EllipsisMode> ELLIPSIS_MODALS = { EllipsisMode::HEAD, EllipsisMode::MIDDLE, EllipsisMode::TAIL };
90 const std::vector<TextSelectableMode> TEXT_SELECTABLE_MODE = { TextSelectableMode::SELECTABLE_UNFOCUSABLE,
91     TextSelectableMode::SELECTABLE_FOCUSABLE, TextSelectableMode::UNSELECTABLE };
92 constexpr TextDecorationStyle DEFAULT_TEXT_DECORATION_STYLE = TextDecorationStyle::SOLID;
93 const int32_t DEFAULT_VARIABLE_FONT_WEIGHT = 400;
94 }; // namespace
95 
SetWidth(const JSCallbackInfo & info)96 void JSText::SetWidth(const JSCallbackInfo& info)
97 {
98     JSViewAbstract::JsWidth(info);
99     TextModel::GetInstance()->OnSetWidth();
100 }
101 
SetHeight(const JSCallbackInfo & info)102 void JSText::SetHeight(const JSCallbackInfo& info)
103 {
104     JSViewAbstract::JsHeight(info);
105     TextModel::GetInstance()->OnSetHeight();
106 }
107 
SetFont(const JSCallbackInfo & info)108 void JSText::SetFont(const JSCallbackInfo& info)
109 {
110     Font font;
111     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
112     CHECK_NULL_VOID(pipelineContext);
113     auto theme = pipelineContext->GetTheme<TextTheme>();
114     CHECK_NULL_VOID(theme);
115     font.fontSize = theme->GetTextStyle().GetFontSize();
116     font.fontWeight = theme->GetTextStyle().GetFontWeight();
117     font.fontFamilies = theme->GetTextStyle().GetFontFamilies();
118     font.fontStyle = theme->GetTextStyle().GetFontStyle();
119     GetFontInfo(info, font);
120     TextModel::GetInstance()->SetFont(font);
121     if (info.Length() < 2) { // 2 : two args
122         return;
123     }
124     auto tmpInfo = info[1];
125     if (!tmpInfo->IsObject()) {
126         return;
127     }
128     auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
129     auto enableVariableFontWeight = paramObject->GetProperty("enableVariableFontWeight");
130     if (enableVariableFontWeight->IsBoolean()) {
131         TextModel::GetInstance()->SetEnableVariableFontWeight(enableVariableFontWeight->ToBoolean());
132     } else {
133         TextModel::GetInstance()->SetEnableVariableFontWeight(false);
134     }
135 }
136 
GetFontInfo(const JSCallbackInfo & info,Font & font)137 void JSText::GetFontInfo(const JSCallbackInfo& info, Font& font)
138 {
139     auto tmpInfo = info[0];
140     if (!tmpInfo->IsObject()) {
141         return;
142     }
143     auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
144     auto fontSize = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::SIZE));
145     CalcDimension size;
146     RefPtr<ResourceObject> fontSizeResObj;
147     UnRegisterResource("FontSize");
148     if (ParseJsDimensionFpNG(fontSize, size, fontSizeResObj, false) && size.IsNonNegative()) {
149         font.fontSize = size;
150         if (SystemProperties::ConfigChangePerform() && fontSizeResObj) {
151             RegisterResource<CalcDimension>("FontSize", fontSizeResObj, size);
152         }
153     }
154     std::string weight;
155     auto fontWeight = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::WEIGHT));
156     if (!fontWeight->IsNull()) {
157         int32_t variableFontWeight = DEFAULT_VARIABLE_FONT_WEIGHT;
158         ParseJsInt32(fontWeight, variableFontWeight);
159         TextModel::GetInstance()->SetVariableFontWeight(variableFontWeight);
160         if (fontWeight->IsNumber()) {
161             weight = std::to_string(fontWeight->ToNumber<int32_t>());
162         } else {
163             JSContainerBase::ParseJsString(fontWeight, weight);
164         }
165         font.fontWeight = ConvertStrToFontWeight(weight);
166     }
167     auto fontFamily = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::FAMILY));
168     if (!fontFamily->IsNull()) {
169         std::vector<std::string> fontFamilies;
170         RefPtr<ResourceObject> fontFamiliesResObj;
171         UnRegisterResource("FontFamily");
172         if (JSContainerBase::ParseJsFontFamilies(fontFamily, fontFamilies, fontFamiliesResObj)) {
173             font.fontFamilies = fontFamilies;
174             if (SystemProperties::ConfigChangePerform() && fontFamiliesResObj) {
175                 RegisterResource<std::vector<std::string>>(
176                     "FontFamily", fontFamiliesResObj, fontFamilies);
177             }
178         }
179     }
180     auto style = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::STYLE));
181     if (!style->IsNull() || style->IsNumber()) {
182         font.fontStyle = static_cast<FontStyle>(style->ToNumber<int32_t>());
183     }
184 }
185 
SetFontSize(const JSCallbackInfo & info)186 void JSText::SetFontSize(const JSCallbackInfo& info)
187 {
188     if (info.Length() < 1) {
189         return;
190     }
191     CalcDimension fontSize;
192     RefPtr<ResourceObject> resObj;
193     UnRegisterResource("FontSize");
194     JSRef<JSVal> args = info[0];
195     if (!ParseJsDimensionFpNG(args, fontSize, resObj, false) || fontSize.IsNegative()) {
196         auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
197         CHECK_NULL_VOID(pipelineContext);
198         auto theme = pipelineContext->GetTheme<TextTheme>();
199         CHECK_NULL_VOID(theme);
200         fontSize = theme->GetTextStyle().GetFontSize();
201         TextModel::GetInstance()->SetFontSize(fontSize);
202         return;
203     }
204     TextModel::GetInstance()->SetFontSize(fontSize);
205     if (SystemProperties::ConfigChangePerform() && resObj) {
206         RegisterResource<CalcDimension>("FontSize", resObj, fontSize);
207     }
208 }
209 
SetFontWeight(const JSCallbackInfo & info)210 void JSText::SetFontWeight(const JSCallbackInfo& info)
211 {
212     if (info.Length() < 1) {
213         return;
214     }
215     JSRef<JSVal> args = info[0];
216     std::string fontWeight;
217     int32_t variableFontWeight = DEFAULT_VARIABLE_FONT_WEIGHT;
218     ParseJsInt32(args, variableFontWeight);
219     TextModel::GetInstance()->SetVariableFontWeight(variableFontWeight);
220 
221     if (args->IsNumber()) {
222         fontWeight = args->ToString();
223     } else {
224         ParseJsString(args, fontWeight);
225     }
226     TextModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(fontWeight));
227 
228     if (info.Length() < 2) { // 2 : two args
229         return;
230     }
231     auto tmpInfo = info[1];
232     if (!tmpInfo->IsObject()) {
233         return;
234     }
235     auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
236     auto enableVariableFontWeight = paramObject->GetProperty("enableVariableFontWeight");
237     if (enableVariableFontWeight->IsBoolean()) {
238         TextModel::GetInstance()->SetEnableVariableFontWeight(enableVariableFontWeight->ToBoolean());
239     } else {
240         TextModel::GetInstance()->SetEnableVariableFontWeight(false);
241     }
242 }
243 
SetMinFontScale(const JSCallbackInfo & info)244 void JSText::SetMinFontScale(const JSCallbackInfo& info)
245 {
246     double minFontScale;
247     RefPtr<ResourceObject> resourceObject;
248     UnRegisterResource("MinFontScale");
249     if (info.Length() < 1 || !ParseJsDouble(info[0], minFontScale, resourceObject)) {
250         return;
251     }
252     auto minFontScaleValue = static_cast<float>(std::clamp(minFontScale, 0.0, 1.0));
253     if (SystemProperties::ConfigChangePerform() && resourceObject) {
254         RegisterResource<float>("MinFontScale", resourceObject, minFontScaleValue);
255     }
256     TextModel::GetInstance()->SetMinFontScale(minFontScaleValue);
257 }
258 
SetMaxFontScale(const JSCallbackInfo & info)259 void JSText::SetMaxFontScale(const JSCallbackInfo& info)
260 {
261     double maxFontScale;
262     RefPtr<ResourceObject> resourceObject;
263     UnRegisterResource("MaxFontScale");
264     if (info.Length() < 1 || !ParseJsDouble(info[0], maxFontScale, resourceObject)) {
265         return;
266     }
267     auto maxFontScaleValue = static_cast<float>(std::max(maxFontScale, 1.0));
268     if (SystemProperties::ConfigChangePerform() && resourceObject) {
269         RegisterResource<float>("MaxFontScale", resourceObject, maxFontScaleValue);
270     }
271     TextModel::GetInstance()->SetMaxFontScale(maxFontScaleValue);
272 }
273 
SetForegroundColor(const JSCallbackInfo & info)274 void JSText::SetForegroundColor(const JSCallbackInfo& info)
275 {
276     if (info.Length() < 1) {
277         return;
278     }
279     ForegroundColorStrategy strategy;
280     if (ParseJsColorStrategy(info[0], strategy)) {
281         TextModel::GetInstance()->SetTextColor(Color::FOREGROUND);
282         ViewAbstractModel::GetInstance()->SetForegroundColorStrategy(strategy);
283         return;
284     }
285     SetTextColor(info);
286 }
287 
SetTextColor(const JSCallbackInfo & info)288 void JSText::SetTextColor(const JSCallbackInfo& info)
289 {
290     if (info.Length() < 1) {
291         return;
292     }
293     Color textColor;
294     RefPtr<ResourceObject> resourceObject;
295     UnRegisterResource("TextColor");
296     JSRef<JSVal> args = info[0];
297     if (!ParseJsColor(args, textColor, resourceObject)) {
298         TextModel::GetInstance()->ResetTextColor();
299         return;
300     }
301     if (SystemProperties::ConfigChangePerform() && resourceObject) {
302         RegisterResource<Color>("TextColor", resourceObject, textColor);
303     }
304     TextModel::GetInstance()->SetTextColor(textColor);
305 }
306 
SetTextShadow(const JSCallbackInfo & info)307 void JSText::SetTextShadow(const JSCallbackInfo& info)
308 {
309     if (info.Length() < 1) {
310         return;
311     }
312     std::vector<Shadow> shadows;
313     JSRef<JSVal> args = info[0];
314     ParseTextShadowFromShadowObject(args, shadows);
315     TextModel::GetInstance()->SetTextShadow(shadows);
316 }
317 
SetTextOverflow(const JSCallbackInfo & info)318 void JSText::SetTextOverflow(const JSCallbackInfo& info)
319 {
320     do {
321         auto tmpInfo = info[0];
322         if (!tmpInfo->IsObject()) {
323             break;
324         }
325         JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
326         JSRef<JSVal> overflowValue = obj->GetProperty("overflow");
327         if (!overflowValue->IsNumber() && !overflowValue->IsUndefined()) {
328             break;
329         }
330         auto overflow = overflowValue->ToNumber<int32_t>();
331         if(overflowValue->IsUndefined()) {
332             overflow = 0;
333         } else if (overflow < 0 || overflow >= static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
334             break;
335         }
336         TextModel::GetInstance()->SetTextOverflow(TEXT_OVERFLOWS[overflow]);
337     } while (false);
338 
339     info.SetReturnValue(info.This());
340 }
341 
SetWordBreak(const JSCallbackInfo & info)342 void JSText::SetWordBreak(const JSCallbackInfo& info)
343 {
344     JSRef<JSVal> args = info[0];
345     if (!args->IsNumber()) {
346         return;
347     }
348     uint32_t index = args->ToNumber<uint32_t>();
349     if (index < WORD_BREAK_TYPES.size()) {
350         TextModel::GetInstance()->SetWordBreak(WORD_BREAK_TYPES[index]);
351     }
352 }
353 
SetEllipsisMode(const JSCallbackInfo & info)354 void JSText::SetEllipsisMode(const JSCallbackInfo& info)
355 {
356     JSRef<JSVal> args = info[0];
357     if (!args->IsNumber()) {
358         return;
359     }
360     uint32_t index = args->ToNumber<uint32_t>();
361     if (index < ELLIPSIS_MODALS.size()) {
362         TextModel::GetInstance()->SetEllipsisMode(ELLIPSIS_MODALS[index]);
363     }
364 }
365 
SetLineBreakStrategy(const JSCallbackInfo & info)366 void JSText::SetLineBreakStrategy(const JSCallbackInfo& info)
367 {
368     if (info.Length() < 1) {
369         TextModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
370         return;
371     }
372     if (!info[0]->IsNumber()) {
373         TextModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
374         return;
375     }
376     auto index = info[0]->ToNumber<int32_t>();
377     if (index < 0 || index >= static_cast<int32_t>(LINE_BREAK_STRATEGY_TYPES.size())) {
378         TextModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
379         return;
380     }
381     TextModel::GetInstance()->SetLineBreakStrategy(LINE_BREAK_STRATEGY_TYPES[index]);
382 }
383 
SetTextSelection(const JSCallbackInfo & info)384 void JSText::SetTextSelection(const JSCallbackInfo& info)
385 {
386     if (info.Length() < 1) {
387         return;
388     }
389     JSRef<JSVal> argsStartIndex = info[0];
390     JSRef<JSVal> argsEndIndex = info[1];
391     if (!argsStartIndex->IsNumber() || !argsEndIndex->IsNumber()) {
392         return;
393     }
394     auto startIndex = argsStartIndex->ToNumber<int32_t>();
395     auto endIndex = argsEndIndex->ToNumber<int32_t>();
396     TextModel::GetInstance()->SetTextSelection(startIndex, endIndex);
397 }
398 
SetTextCaretColor(const JSCallbackInfo & info)399 void JSText::SetTextCaretColor(const JSCallbackInfo& info)
400 {
401     if (info.Length() < 1) {
402         return;
403     }
404     Color caretColor;
405     RefPtr<ResourceObject> resObj;
406     UnRegisterResource("TextCaretColor");
407     if (!ParseJsColor(info[0], caretColor, resObj)) {
408         auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
409         CHECK_NULL_VOID(pipelineContext);
410         auto theme = pipelineContext->GetTheme<TextTheme>();
411         CHECK_NULL_VOID(theme);
412         caretColor = theme->GetCaretColor();
413     }
414     if (SystemProperties::ConfigChangePerform() && resObj) {
415         RegisterResource<Color>("TextCaretColor", resObj, caretColor);
416     }
417     TextModel::GetInstance()->SetTextCaretColor(caretColor);
418 }
419 
SetSelectedBackgroundColor(const JSCallbackInfo & info)420 void JSText::SetSelectedBackgroundColor(const JSCallbackInfo& info)
421 {
422     if (info.Length() < 1) {
423         return;
424     }
425     Color selectedColor;
426     RefPtr<ResourceObject> resObj;
427     UnRegisterResource("SelectedBackgroundColor");
428     if (!ParseJsColor(info[0], selectedColor, resObj)) {
429         auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
430         CHECK_NULL_VOID(pipelineContext);
431         auto theme = pipelineContext->GetTheme<TextTheme>();
432         CHECK_NULL_VOID(theme);
433         selectedColor = theme->GetSelectedColor();
434     }
435     if (SystemProperties::ConfigChangePerform() && resObj) {
436         RegisterResource<Color>("SelectedBackgroundColor", resObj, selectedColor);
437     }
438     // Alpha = 255 means opaque
439     if (selectedColor.GetAlpha() == JSThemeUtils::DEFAULT_ALPHA) {
440         // Default setting of 20% opacity
441         selectedColor = selectedColor.ChangeOpacity(JSThemeUtils::DEFAULT_OPACITY);
442     }
443     TextModel::GetInstance()->SetSelectedBackgroundColor(selectedColor);
444 }
445 
SetTextSelectableMode(const JSCallbackInfo & info)446 void JSText::SetTextSelectableMode(const JSCallbackInfo& info)
447 {
448     if (info.Length() < 1) {
449         TextModel::GetInstance()->SetTextSelectableMode(TextSelectableMode::SELECTABLE_UNFOCUSABLE);
450         return;
451     }
452     if (!info[0]->IsNumber()) {
453         TextModel::GetInstance()->SetTextSelectableMode(TextSelectableMode::SELECTABLE_UNFOCUSABLE);
454         return;
455     }
456     auto index = info[0]->ToNumber<int32_t>();
457     if (index < 0 || index >= static_cast<int32_t>(TEXT_SELECTABLE_MODE.size())) {
458         TextModel::GetInstance()->SetTextSelectableMode(TextSelectableMode::SELECTABLE_UNFOCUSABLE);
459         return;
460     }
461     TextModel::GetInstance()->SetTextSelectableMode(TEXT_SELECTABLE_MODE[index]);
462 }
463 
SetMaxLines(const JSCallbackInfo & info)464 void JSText::SetMaxLines(const JSCallbackInfo& info)
465 {
466     JSRef<JSVal> args = info[0];
467     auto value = Infinity<int32_t>();
468     if (args->ToString() != "Infinity") {
469         ParseJsInt32(args, value);
470     }
471     TextModel::GetInstance()->SetMaxLines(value);
472 }
473 
SetTextIndent(const JSCallbackInfo & info)474 void JSText::SetTextIndent(const JSCallbackInfo& info)
475 {
476     CalcDimension value;
477     RefPtr<ResourceObject> resObj;
478     JSRef<JSVal> args = info[0];
479 
480     if (!ParseJsDimensionFpNG(args, value, resObj)) {
481         value.Reset();
482         TextModel::GetInstance()->SetTextIndent(value);
483         UnRegisterResource("TextIndent");
484         return;
485     }
486     if (SystemProperties::ConfigChangePerform() && resObj) {
487         RegisterResource<CalcDimension>("TextIndent", resObj, value);
488     }
489     TextModel::GetInstance()->SetTextIndent(value);
490 }
491 
SetFontStyle(int32_t value)492 void JSText::SetFontStyle(int32_t value)
493 {
494     if (value < 0 || value >= static_cast<int32_t>(FONT_STYLES.size())) {
495         if (!(Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE))) {
496             return;
497         }
498         value = 0;
499     }
500     TextModel::GetInstance()->SetItalicFontStyle(FONT_STYLES[value]);
501 }
502 
SetTextAlign(int32_t value)503 void JSText::SetTextAlign(int32_t value)
504 {
505     if (value < 0 || value >= static_cast<int32_t>(TEXT_ALIGNS.size())) {
506         if (!(Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE))) {
507             return;
508         }
509         value = 0;
510     }
511     TextModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
512 }
513 
SetAlign(const JSCallbackInfo & info)514 void JSText::SetAlign(const JSCallbackInfo& info)
515 {
516     JSViewAbstract::JsAlign(info);
517     JSRef<JSVal> args = info[0];
518     if (!args->IsNumber()) {
519         return;
520     }
521     TextModel::GetInstance()->OnSetAlign();
522 }
523 
SetLineHeight(const JSCallbackInfo & info)524 void JSText::SetLineHeight(const JSCallbackInfo& info)
525 {
526     CalcDimension value;
527     JSRef<JSVal> args = info[0];
528     RefPtr<ResourceObject> resObj;
529 
530     if (!ParseJsDimensionFpNG(args, value, resObj)) {
531         value.Reset();
532         TextModel::GetInstance()->SetLineHeight(value);
533         UnRegisterResource("LineHeight");
534         return;
535     }
536     if (SystemProperties::ConfigChangePerform() && resObj) {
537         RegisterResource<CalcDimension>("LineHeight", resObj, value);
538     }
539     if (value.IsNegative()) {
540         value.Reset();
541     }
542     TextModel::GetInstance()->SetLineHeight(value);
543 }
544 
SetLineSpacing(const JSCallbackInfo & info)545 void JSText::SetLineSpacing(const JSCallbackInfo& info)
546 {
547     CalcDimension value;
548     JSRef<JSVal> args = info[0];
549     UnRegisterResource("LineSpacing");
550     RefPtr<ResourceObject> resObj;
551     if (!ParseLengthMetricsToPositiveDimension(args, value, resObj)) {
552         value.Reset();
553     }
554     if (value.IsNegative()) {
555         value.Reset();
556     }
557     TextModel::GetInstance()->SetLineSpacing(value);
558     if (SystemProperties::ConfigChangePerform() && resObj) {
559         RegisterResource<CalcDimension>("LineSpacing", resObj, value);
560     }
561     if (info.Length() < 2) { // 2 : two args
562         TextModel::GetInstance()->SetIsOnlyBetweenLines(false);
563         return;
564     }
565     auto jsonValue = info[1];
566     if (!jsonValue->IsObject()) {
567         TextModel::GetInstance()->SetIsOnlyBetweenLines(false);
568         return;
569     }
570     auto paramObject = JSRef<JSObject>::Cast(jsonValue);
571     auto param = paramObject->GetProperty("onlyBetweenLines");
572     if (!param->IsBoolean() || param->IsUndefined() || param->IsNull()) {
573         TextModel::GetInstance()->SetIsOnlyBetweenLines(false);
574     } else {
575         auto isOnlyBetweenLines = param->ToBoolean();
576         TextModel::GetInstance()->SetIsOnlyBetweenLines(isOnlyBetweenLines);
577     }
578 }
579 
SetFontFamily(const JSCallbackInfo & info)580 void JSText::SetFontFamily(const JSCallbackInfo& info)
581 {
582     std::vector<std::string> fontFamilies;
583     RefPtr<ResourceObject> resObj;
584     UnRegisterResource("FontFamily");
585     JSRef<JSVal> args = info[0];
586     ParseJsFontFamilies(args, fontFamilies, resObj);
587     if (SystemProperties::ConfigChangePerform() && resObj) {
588         RegisterResource<std::vector<std::string>>("FontFamily", resObj, fontFamilies);
589     }
590     TextModel::GetInstance()->SetFontFamily(fontFamilies);
591 }
592 
SetMinFontSize(const JSCallbackInfo & info)593 void JSText::SetMinFontSize(const JSCallbackInfo& info)
594 {
595     if (info.Length() < 1) {
596         return;
597     }
598     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
599     CHECK_NULL_VOID(pipelineContext);
600     auto theme = pipelineContext->GetTheme<TextTheme>();
601     CHECK_NULL_VOID(theme);
602     CalcDimension minFontSize = theme->GetTextStyle().GetAdaptMinFontSize();
603     JSRef<JSVal> args = info[0];
604     RefPtr<ResourceObject> resObj;
605     if (!ParseJsDimensionFpNG(args, minFontSize, resObj, false)) {
606         minFontSize = theme->GetTextStyle().GetAdaptMinFontSize();
607         TextModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
608         UnRegisterResource("AdaptMinFontSize");
609         return;
610     }
611     if (SystemProperties::ConfigChangePerform() && resObj) {
612         RegisterResource<CalcDimension>("AdaptMinFontSize", resObj, minFontSize);
613     }
614     if (minFontSize.IsNegative()) {
615         minFontSize = theme->GetTextStyle().GetAdaptMinFontSize();
616     }
617     TextModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
618 }
619 
SetMaxFontSize(const JSCallbackInfo & info)620 void JSText::SetMaxFontSize(const JSCallbackInfo& info)
621 {
622     if (info.Length() < 1) {
623         return;
624     }
625     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
626     CHECK_NULL_VOID(pipelineContext);
627     auto theme = pipelineContext->GetTheme<TextTheme>();
628     CHECK_NULL_VOID(theme);
629     CalcDimension maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
630     JSRef<JSVal> args = info[0];
631     RefPtr<ResourceObject> resObj;
632     if (!ParseJsDimensionFpNG(args, maxFontSize, resObj, false)) {
633         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
634         TextModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
635         UnRegisterResource("AdaptMaxFontSize");
636         return;
637     }
638     if (maxFontSize.IsNegative()) {
639         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
640     }
641     if (SystemProperties::ConfigChangePerform() && resObj) {
642         RegisterResource<CalcDimension>("AdaptMaxFontSize", resObj, maxFontSize);
643     }
644     TextModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
645 }
646 
SetLetterSpacing(const JSCallbackInfo & info)647 void JSText::SetLetterSpacing(const JSCallbackInfo& info)
648 {
649     CalcDimension value;
650     JSRef<JSVal> args = info[0];
651     RefPtr<ResourceObject> resObj;
652     UnRegisterResource("LetterSpacing");
653     if (!ParseJsDimensionFpNG(args, value, resObj, false)) {
654         value.Reset();
655         TextModel::GetInstance()->SetLetterSpacing(value);
656         return;
657     }
658     if (SystemProperties::ConfigChangePerform() && resObj) {
659         RegisterResource<CalcDimension>("LetterSpacing", resObj, value);
660     }
661     TextModel::GetInstance()->SetLetterSpacing(value);
662 }
663 
SetTextCase(int32_t value)664 void JSText::SetTextCase(int32_t value)
665 {
666     if (value < 0 || value >= static_cast<int32_t>(TEXT_CASES.size())) {
667         if (!(Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE))) {
668             return;
669         }
670         value = 0;
671     }
672     TextModel::GetInstance()->SetTextCase(TEXT_CASES[value]);
673 }
674 
SetBaselineOffset(const JSCallbackInfo & info)675 void JSText::SetBaselineOffset(const JSCallbackInfo& info)
676 {
677     CalcDimension value;
678     JSRef<JSVal> args = info[0];
679     RefPtr<ResourceObject> resObj;
680     if (!ParseJsDimensionFpNG(args, value, resObj, false)) {
681         value.Reset();
682         TextModel::GetInstance()->SetBaselineOffset(value);
683         UnRegisterResource("BaselineOffset");
684         return;
685     }
686     if (SystemProperties::ConfigChangePerform() && resObj) {
687         RegisterResource<CalcDimension>("BaselineOffset", resObj, value);
688     }
689     TextModel::GetInstance()->SetBaselineOffset(value);
690 }
691 
SetDecoration(const JSCallbackInfo & info)692 void JSText::SetDecoration(const JSCallbackInfo& info)
693 {
694     auto tmpInfo = info[0];
695     UnRegisterResource("TextDecorationColor");
696     if (tmpInfo->IsUndefined()) {
697         TextModel::GetInstance()->SetTextDecoration(TextDecoration::NONE);
698         info.ReturnSelf();
699         return;
700     }
701     if (!tmpInfo->IsObject()) {
702         info.ReturnSelf();
703         return;
704     }
705     JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
706     JSRef<JSVal> typeValue = obj->GetProperty("type");
707     JSRef<JSVal> colorValue = obj->GetProperty("color");
708     JSRef<JSVal> styleValue = obj->GetProperty("style");
709     JSRef<JSVal> thicknessScaleValue = obj->GetProperty("thicknessScale");
710 
711     TextDecoration textDecoration;
712     if (typeValue->IsNumber()) {
713         textDecoration = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
714     } else {
715         auto theme = GetTheme<TextTheme>();
716         CHECK_NULL_VOID(theme);
717         textDecoration = theme->GetTextDecoration();
718     }
719     Color result;
720     RefPtr<ResourceObject> resObj;
721     if (!ParseJsColor(colorValue, result, resObj)) {
722         auto theme = GetTheme<TextTheme>();
723         CHECK_NULL_VOID(theme);
724         if (Container::CurrentColorMode() == ColorMode::DARK) {
725             result = theme->GetTextStyle().GetTextColor();
726         } else {
727             result = theme->GetTextStyle().GetTextDecorationColor();
728         }
729     }
730     if (SystemProperties::ConfigChangePerform() && resObj) {
731         RegisterResource<Color>("TextDecorationColor", resObj, result);
732     }
733     auto style =
734         styleValue->IsNumber() ? styleValue->ToNumber<int32_t>() : static_cast<int32_t>(DEFAULT_TEXT_DECORATION_STYLE);
735     float lineThicknessScale = thicknessScaleValue->IsNumber() ? thicknessScaleValue->ToNumber<float>() : 1.0f;
736     lineThicknessScale = lineThicknessScale < 0 ? 1.0f : lineThicknessScale;
737     TextModel::GetInstance()->SetTextDecoration(textDecoration);
738     TextModel::GetInstance()->SetTextDecorationColor(result);
739     TextModel::GetInstance()->SetTextDecorationStyle(static_cast<TextDecorationStyle>(style));
740     TextModel::GetInstance()->SetLineThicknessScale(lineThicknessScale);
741     info.ReturnSelf();
742 }
743 
SetHeightAdaptivePolicy(int32_t value)744 void JSText::SetHeightAdaptivePolicy(int32_t value)
745 {
746     if (value < 0 || value >= static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICY.size())) {
747         if (!(Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE))) {
748             return;
749         }
750         value = 0;
751     }
752     TextModel::GetInstance()->SetHeightAdaptivePolicy(HEIGHT_ADAPTIVE_POLICY[value]);
753 }
754 
JsOnClick(const JSCallbackInfo & info)755 void JSText::JsOnClick(const JSCallbackInfo& info)
756 {
757     JSRef<JSVal> args = info[0];
758     if (Container::IsCurrentUseNewPipeline()) {
759         if (args->IsUndefined() && IsDisableEventVersion()) {
760             TextModel::GetInstance()->ClearOnClick();
761             return;
762         }
763         if (!args->IsFunction()) {
764             return;
765         }
766         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
767         auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(args));
768         auto onClick = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, node = frameNode]
769             (BaseEventInfo* info) {
770             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
771             auto* clickInfo = TypeInfoHelper::DynamicCast<GestureEvent>(info);
772             ACE_SCORING_EVENT("Text.onClick");
773             PipelineContext::SetCallBackNode(node);
774             func->Execute(*clickInfo);
775 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
776             std::u16string label = u"";
777             auto frameNode = node.Upgrade();
778             if (frameNode) {
779                 auto pattern = frameNode->GetPattern();
780                 CHECK_NULL_VOID(pattern);
781                 auto layoutProperty = pattern->GetLayoutProperty<NG::TextLayoutProperty>();
782                 CHECK_NULL_VOID(layoutProperty);
783                 label = layoutProperty->GetContent().value_or(u"");
784             }
785             JSInteractableView::ReportClickEvent(node, label);
786 #endif
787         };
788         double distanceThreshold = std::numeric_limits<double>::infinity();
789         if (info.Length() > 1 && info[1]->IsNumber()) {
790             distanceThreshold = info[1]->ToNumber<double>();
791             distanceThreshold = Dimension(distanceThreshold, DimensionUnit::VP).ConvertToPx();
792         }
793         TextModel::GetInstance()->SetOnClick(std::move(onClick), distanceThreshold);
794 
795         auto focusHub = NG::ViewStackProcessor::GetInstance()->GetOrCreateMainFrameNodeFocusHub();
796         CHECK_NULL_VOID(focusHub);
797         focusHub->SetFocusable(true, false);
798     } else {
799         JsOnClickWithoutNGBUILD(info);
800     }
801 }
802 
JsOnClickWithoutNGBUILD(const JSCallbackInfo & info)803 void JSText::JsOnClickWithoutNGBUILD(const JSCallbackInfo& info)
804 {
805 #ifndef NG_BUILD
806     JSRef<JSVal> args = info[0];
807     if (args->IsFunction()) {
808         auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
809         auto impl = inspector ? inspector->GetInspectorFunctionImpl() : nullptr;
810         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
811         RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(args));
812         auto onClickId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), impl,
813                              node = frameNode](const BaseEventInfo* info) {
814             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
815             const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
816             auto newInfo = *clickInfo;
817             if (impl) {
818                 impl->UpdateEventInfo(newInfo);
819             }
820             ACE_SCORING_EVENT("Text.onClick");
821             PipelineContext::SetCallBackNode(node);
822             func->Execute(newInfo);
823         };
824         double distanceThreshold = std::numeric_limits<double>::infinity();
825         if (info.Length() > 1 && info[1]->IsNumber()) {
826             distanceThreshold = info[1]->ToNumber<double>();
827             distanceThreshold = Dimension(distanceThreshold, DimensionUnit::VP).ConvertToPx();
828         }
829         TextModel::GetInstance()->SetOnClick(std::move(onClickId), distanceThreshold);
830     }
831 #endif
832 }
833 
JsRemoteMessage(const JSCallbackInfo & info)834 void JSText::JsRemoteMessage(const JSCallbackInfo& info)
835 {
836     JSInteractableView::JsCommonRemoteMessage(info);
837     auto callback = JSInteractableView::GetRemoteMessageEventCallback(info);
838     TextModel::GetInstance()->SetRemoteMessage(std::move(callback));
839 }
840 
Create(const JSCallbackInfo & info)841 void JSText::Create(const JSCallbackInfo& info)
842 {
843     std::u16string data;
844     if (info.Length() <= 0) {
845         TextModel::GetInstance()->Create(data);
846         UnRegisterResource("Content");
847         return;
848     }
849 
850     if (info[0]->IsObject() && JSRef<JSObject>::Cast(info[0])->Unwrap<JSSpanString>()) {
851         auto *spanString = JSRef<JSObject>::Cast(info[0])->Unwrap<JSSpanString>();
852         if (spanString == nullptr) {
853             return;
854         }
855         auto spanStringController = spanString->GetController();
856         if (spanStringController) {
857             TextModel::GetInstance()->Create(spanStringController);
858         } else {
859             TextModel::GetInstance()->Create(data);
860         }
861         UnRegisterResource("Content");
862     } else {
863         RefPtr<ResourceObject> resObj;
864         auto ret = ParseJsString(info[0], data, resObj);
865         UtfUtils::HandleInvalidUTF16(reinterpret_cast<uint16_t*>(data.data()), data.length(), 0);
866         TextModel::GetInstance()->Create(data);
867         UnRegisterResource("Content");
868         if (ret && SystemProperties::ConfigChangePerform() && resObj) {
869             RegisterResource<std::u16string>("Content", resObj, data);
870         }
871     }
872 
873     if (info.Length() <= 1 || !info[1]->IsObject()) {
874         return;
875     }
876 
877     JSTextController* jsController = nullptr;
878     auto paramObject = JSRef<JSObject>::Cast(info[1]);
879     auto controllerObj = paramObject->GetProperty("controller");
880     if (!controllerObj->IsUndefined() && !controllerObj->IsNull() && controllerObj->IsObject()) {
881         jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextController>();
882     }
883 
884     RefPtr<TextControllerBase> controller = TextModel::GetInstance()->GetTextController();
885     if (!controller) {
886         TAG_LOGW(AceLogTag::ACE_TEXT, "JSText::Create controller is null");
887     }
888 
889     if (jsController) {
890         jsController->SetController(controller);
891         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FIFTEEN)) {
892             auto styledString = jsController->GetStyledString();
893             if (styledString && controller) {
894                 controller->SetStyledString(styledString, false);
895                 jsController->ClearStyledString();
896             }
897         }
898     }
899 }
900 
SetCopyOption(const JSCallbackInfo & info)901 void JSText::SetCopyOption(const JSCallbackInfo& info)
902 {
903     if (info.Length() == 0) {
904         return;
905     }
906     auto copyOptions = CopyOptions::None;
907     auto tmpInfo = info[0];
908     if (tmpInfo->IsNumber()) {
909         auto emunNumber = tmpInfo->ToNumber<int>();
910         copyOptions = static_cast<CopyOptions>(emunNumber);
911     }
912     TextModel::GetInstance()->SetCopyOption(copyOptions);
913 }
914 
SetOnCopy(const JSCallbackInfo & info)915 void JSText::SetOnCopy(const JSCallbackInfo& info)
916 {
917     JSRef<JSVal> args = info[0];
918     CHECK_NULL_VOID(args->IsFunction());
919     JsEventCallback<void(const std::u16string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(args));
920     TextModel::GetInstance()->SetOnCopy(std::move(callback));
921 }
922 
JsOnDragStart(const JSCallbackInfo & info)923 void JSText::JsOnDragStart(const JSCallbackInfo& info)
924 {
925     JSRef<JSVal> args = info[0];
926     CHECK_NULL_VOID(args->IsFunction());
927     RefPtr<JsDragFunction> jsOnDragStartFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
928     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
929     auto onDragStart = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragStartFunc),
930                            targetNode = frameNode](
931                            const RefPtr<DragEvent>& info, const std::string& extraParams) -> NG::DragDropBaseInfo {
932         NG::DragDropBaseInfo itemInfo;
933         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, itemInfo);
934         PipelineContext::SetCallBackNode(targetNode);
935         auto ret = func->Execute(info, extraParams);
936         if (!ret->IsObject()) {
937             return itemInfo;
938         }
939         auto node = ParseDragNode(ret);
940         if (node) {
941             itemInfo.node = node;
942             return itemInfo;
943         }
944         auto builderObj = JSRef<JSObject>::Cast(ret);
945 #if defined(PIXEL_MAP_SUPPORTED)
946         auto pixmap = builderObj->GetProperty("pixelMap");
947         itemInfo.pixelMap = CreatePixelMapFromNapiValue(pixmap);
948 #endif
949         auto extraInfo = builderObj->GetProperty("extraInfo");
950         ParseJsString(extraInfo, itemInfo.extraInfo);
951         node = ParseDragNode(builderObj->GetProperty("builder"));
952         itemInfo.node = node;
953         return itemInfo;
954     };
955 
956     TextModel::GetInstance()->SetOnDragStart(std::move(onDragStart));
957 }
958 
JsFocusable(const JSCallbackInfo & info)959 void JSText::JsFocusable(const JSCallbackInfo& info)
960 {
961     auto tmpInfo = info[0];
962     if (!tmpInfo->IsBoolean()) {
963         return;
964     }
965     JSInteractableView::SetFocusable(tmpInfo->ToBoolean());
966     JSInteractableView::SetFocusNode(false);
967 }
968 
JsDraggable(const JSCallbackInfo & info)969 void JSText::JsDraggable(const JSCallbackInfo& info)
970 {
971     auto tmpInfo = info[0];
972     if (!tmpInfo->IsBoolean()) {
973         return;
974     }
975     ViewAbstractModel::GetInstance()->SetDraggable(tmpInfo->ToBoolean());
976 }
977 
JsEnableDataDetector(const JSCallbackInfo & info)978 void JSText::JsEnableDataDetector(const JSCallbackInfo& info)
979 {
980     if (info.Length() < 1) {
981         LOGI("The argv is wrong, it is supposed to have at least 1 argument");
982         return;
983     }
984     auto tmpInfo = info[0];
985     if (!tmpInfo->IsBoolean()) {
986         TextModel::GetInstance()->SetTextDetectEnable(false);
987         return;
988     }
989     auto enable = tmpInfo->ToBoolean();
990     TextModel::GetInstance()->SetTextDetectEnable(enable);
991 }
992 
JsDataDetectorConfig(const JSCallbackInfo & info)993 void JSText::JsDataDetectorConfig(const JSCallbackInfo& info)
994 {
995     if (info.Length() < 1) {
996         LOGI("The argv is wrong, it is supposed to have at least 1 argument");
997         return;
998     }
999     JSRef<JSVal> args = info[0];
1000     if (!args->IsObject()) {
1001         return;
1002     }
1003 
1004     TextDetectConfig textDetectConfig;
1005     if (!ParseDataDetectorConfig(info, textDetectConfig)) {
1006         return;
1007     }
1008     TextModel::GetInstance()->SetTextDetectConfig(textDetectConfig);
1009 }
1010 
BindSelectionMenu(const JSCallbackInfo & info)1011 void JSText::BindSelectionMenu(const JSCallbackInfo& info)
1012 {
1013     // TextSpanType
1014     NG::TextSpanType textSpanType = NG::TextSpanType::TEXT;
1015     bool isValidTextSpanType = true;
1016     JSRef<JSVal> argsSpanType = info[0];
1017     if (argsSpanType->IsNumber()) {
1018         auto spanTypeId = argsSpanType->ToNumber<int32_t>();
1019         isValidTextSpanType = NG::TextSpanTypeMapper::GetTextSpanTypeFromJsType(spanTypeId, textSpanType);
1020     }
1021 
1022     // Builder
1023     JSRef<JSVal> argsMenuObj = info[1];
1024     if (!argsMenuObj->IsObject()) {
1025         return;
1026     }
1027     JSRef<JSObject> menuObj = JSRef<JSObject>::Cast(argsMenuObj);
1028     auto builder = menuObj->GetProperty("builder");
1029     if (!builder->IsFunction()) {
1030         return;
1031     }
1032     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
1033     CHECK_NULL_VOID(builderFunc);
1034 
1035     // TextResponseType
1036     uint32_t resquiredParameterCount = 3;
1037     JSRef<JSVal> argsResponse = info[resquiredParameterCount - 1];
1038     NG::TextResponseType responseType = NG::TextResponseType::LONG_PRESS;
1039     if (argsResponse->IsNumber()) {
1040         auto response = argsResponse->ToNumber<int32_t>();
1041         responseType = static_cast<NG::TextResponseType>(response);
1042     }
1043 
1044     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1045     std::function<void()> buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc),
1046                                           node = frameNode]() {
1047         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1048         ACE_SCORING_EVENT("BindSelectionMenu");
1049         PipelineContext::SetCallBackNode(node);
1050         func->Execute();
1051     };
1052 
1053     // SelectionMenuOptions
1054     NG::SelectMenuParam menuParam;
1055     menuParam.isValid = isValidTextSpanType;
1056     if (info.Length() > static_cast<uint32_t>(resquiredParameterCount)) {
1057         JSRef<JSVal> argsMenuOptions = info[resquiredParameterCount];
1058         if (argsMenuOptions->IsObject()) {
1059             ParseMenuParam(info, argsMenuOptions, menuParam);
1060         }
1061     }
1062 
1063     TextModel::GetInstance()->BindSelectionMenu(textSpanType, responseType, buildFunc, menuParam);
1064 }
1065 
SetOnTextSelectionChange(const JSCallbackInfo & info)1066 void JSText::SetOnTextSelectionChange(const JSCallbackInfo& info)
1067 {
1068     JSRef<JSVal> args = info[0];
1069     CHECK_NULL_VOID(args->IsFunction());
1070     JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(args));
1071     TextModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
1072 }
1073 
JsClip(const JSCallbackInfo & info)1074 void JSText::JsClip(const JSCallbackInfo& info)
1075 {
1076     JSViewAbstract::JsClip(info);
1077     JSRef<JSVal> args = info[0];
1078     if (args->IsBoolean()) {
1079         TextModel::GetInstance()->SetClipEdge(args->ToBoolean());
1080     }
1081 }
1082 
SetFontFeature(const JSCallbackInfo & info)1083 void JSText::SetFontFeature(const JSCallbackInfo& info)
1084 {
1085     if (info.Length() < 1) {
1086         return;
1087     }
1088 
1089     if (!info[0]->IsString() && !info[0]->IsObject()) {
1090         return;
1091     }
1092     std::string fontFeatureSettings = info[0]->ToString();
1093     TextModel::GetInstance()->SetFontFeature(ParseFontFeatureSettings(fontFeatureSettings));
1094 }
1095 
JsResponseRegion(const JSCallbackInfo & info)1096 void JSText::JsResponseRegion(const JSCallbackInfo& info)
1097 {
1098     JSViewAbstract::JsResponseRegion(info);
1099     TextModel::GetInstance()->SetResponseRegion(true);
1100 }
1101 
SetHalfLeading(const JSCallbackInfo & info)1102 void JSText::SetHalfLeading(const JSCallbackInfo& info)
1103 {
1104     if (info.Length() < 1) {
1105         return;
1106     }
1107     auto halfLeading = info[0];
1108     if (!halfLeading->IsBoolean()) {
1109         TextModel::GetInstance()->SetHalfLeading(false);
1110         return;
1111     }
1112     auto enable = halfLeading->ToBoolean();
1113     TextModel::GetInstance()->SetHalfLeading(enable);
1114 }
1115 
SetEnableHapticFeedback(const JSCallbackInfo & info)1116 void JSText::SetEnableHapticFeedback(const JSCallbackInfo& info)
1117 {
1118     bool state = true;
1119     if (info.Length() > 0 && info[0]->IsBoolean()) {
1120         state = info[0]->ToBoolean();
1121     }
1122     TextModel::GetInstance()->SetEnableHapticFeedback(state);
1123 }
1124 
SetOptimizeTrailingSpace(const JSCallbackInfo & info)1125 void JSText::SetOptimizeTrailingSpace(const JSCallbackInfo& info)
1126 {
1127     bool state = false;
1128 
1129     if (info.Length() > 0 && info[0]->IsBoolean()) {
1130         state = info[0]->ToBoolean();
1131     }
1132 
1133     TextModel::GetInstance()->SetOptimizeTrailingSpace(state);
1134 }
1135 
SetEnableAutoSpacing(const JSCallbackInfo & info)1136 void JSText::SetEnableAutoSpacing(const JSCallbackInfo& info)
1137 {
1138     bool enabled = false;
1139     if (info.Length() > 0 && info[0]->IsBoolean()) {
1140         enabled = info[0]->ToBoolean();
1141     }
1142     TextModel::GetInstance()->SetEnableAutoSpacing(enabled);
1143 }
1144 
SetTextVerticalAlign(const JSCallbackInfo & info)1145 void JSText::SetTextVerticalAlign(const JSCallbackInfo& info)
1146 {
1147     TextVerticalAlign verticalAlign = TextVerticalAlign::BASELINE;
1148     if (info.Length() > 0 && info[0]->IsNumber()) {
1149         verticalAlign = static_cast<TextVerticalAlign>(info[0]->ToNumber<int32_t>());
1150     }
1151     TextModel::GetInstance()->SetTextVerticalAlign(verticalAlign);
1152 }
1153 
SetShaderStyle(const JSCallbackInfo & info)1154 void JSText::SetShaderStyle(const JSCallbackInfo& info)
1155 {
1156     if (info.Length() < 1 || !info[0]->IsObject()) {
1157         TextModel::GetInstance()->ResetGradientShaderStyle();
1158         return;
1159     }
1160     NG::Gradient gradient;
1161     ParseShaderStyle(info, gradient);
1162 }
1163 
ParseShaderStyle(const JSCallbackInfo & info,NG::Gradient & gradient)1164 void JSText::ParseShaderStyle(const JSCallbackInfo& info, NG::Gradient& gradient)
1165 {
1166     CalcDimension value;
1167     if (info.Length() < 1 || (info.Length() > 0 && !info[0]->IsObject())) {
1168         TextModel::GetInstance()->ResetGradientShaderStyle();
1169         return;
1170     }
1171     auto shaderStyleObj = JSRef<JSObject>::Cast(info[0]);
1172     if (shaderStyleObj->HasProperty("options")) {
1173         auto optionsValue = shaderStyleObj->GetProperty("options");
1174         shaderStyleObj = JSRef<JSObject>::Cast(optionsValue);
1175     }
1176     if (shaderStyleObj->HasProperty("center") && shaderStyleObj->HasProperty("radius")) {
1177         NewRadialGradient(shaderStyleObj, gradient);
1178         TextModel::GetInstance()->SetGradientShaderStyle(gradient);
1179     } else if (shaderStyleObj->HasProperty("colors")) {
1180         NewLinearGradient(shaderStyleObj, gradient);
1181         TextModel::GetInstance()->SetGradientShaderStyle(gradient);
1182     } else if (shaderStyleObj->HasProperty("color")) {
1183         Color textColor;
1184         auto infoColor = shaderStyleObj->GetProperty("color");
1185         ParseJsColor(infoColor, textColor);
1186         TextModel::GetInstance()->SetColorShaderStyle(textColor);
1187     } else {
1188         TextModel::GetInstance()->ResetGradientShaderStyle();
1189     }
1190 }
1191 
SetContentTransition(const JSCallbackInfo & info)1192 void JSText::SetContentTransition(const JSCallbackInfo& info)
1193 {
1194     if (info.Length() > 0 && !info[0]->IsObject()) {
1195         TextModel::GetInstance()->ResetContentTransition();
1196         return;
1197     }
1198     auto contentTransitionObj = JSRef<JSObject>::Cast(info[0]);
1199     TextFlipDirection direction = TextFlipDirection::DOWN;
1200     bool enableBlur = false;
1201     if (contentTransitionObj->HasProperty("flipDirection")) {
1202         auto directionObj = contentTransitionObj->GetProperty("flipDirection");
1203         if (directionObj->IsNumber()) {
1204             direction = static_cast<TextFlipDirection>(directionObj->ToNumber<int32_t>());
1205         }
1206     }
1207     if (contentTransitionObj->HasProperty("enableBlur")) {
1208         auto enableBlurObj = contentTransitionObj->GetProperty("enableBlur");
1209         if (enableBlurObj->IsBoolean()) {
1210             enableBlur = enableBlurObj->ToBoolean();
1211         }
1212     }
1213     TextModel::GetInstance()->SetContentTransition(TextEffectStrategy::FLIP, direction, enableBlur);
1214 }
1215 
JSBind(BindingTarget globalObj)1216 void JSText::JSBind(BindingTarget globalObj)
1217 {
1218     JSClass<JSText>::Declare("Text");
1219     MethodOptions opt = MethodOptions::NONE;
1220     JSClass<JSText>::StaticMethod("create", &JSText::Create, opt);
1221     JSClass<JSText>::StaticMethod("width", &JSText::SetWidth);
1222     JSClass<JSText>::StaticMethod("height", &JSText::SetHeight);
1223     JSClass<JSText>::StaticMethod("font", &JSText::SetFont, opt);
1224     JSClass<JSText>::StaticMethod("fontColor", &JSText::SetTextColor, opt);
1225     JSClass<JSText>::StaticMethod("textShadow", &JSText::SetTextShadow, opt);
1226     JSClass<JSText>::StaticMethod("fontSize", &JSText::SetFontSize, opt);
1227     JSClass<JSText>::StaticMethod("fontWeight", &JSText::SetFontWeight, opt);
1228     JSClass<JSText>::StaticMethod("minFontScale", &JSText::SetMinFontScale, opt);
1229     JSClass<JSText>::StaticMethod("maxFontScale", &JSText::SetMaxFontScale, opt);
1230     JSClass<JSText>::StaticMethod("wordBreak", &JSText::SetWordBreak, opt);
1231     JSClass<JSText>::StaticMethod("lineBreakStrategy", &JSText::SetLineBreakStrategy, opt);
1232     JSClass<JSText>::StaticMethod("selection", &JSText::SetTextSelection, opt);
1233     JSClass<JSText>::StaticMethod("ellipsisMode", &JSText::SetEllipsisMode, opt);
1234     JSClass<JSText>::StaticMethod("textSelectable", &JSText::SetTextSelectableMode, opt);
1235     JSClass<JSText>::StaticMethod("maxLines", &JSText::SetMaxLines, opt);
1236     JSClass<JSText>::StaticMethod("textIndent", &JSText::SetTextIndent);
1237     JSClass<JSText>::StaticMethod("textOverflow", &JSText::SetTextOverflow, opt);
1238     JSClass<JSText>::StaticMethod("fontStyle", &JSText::SetFontStyle, opt);
1239     JSClass<JSText>::StaticMethod("align", &JSText::SetAlign, opt);
1240     JSClass<JSText>::StaticMethod("textAlign", &JSText::SetTextAlign, opt);
1241     JSClass<JSText>::StaticMethod("lineHeight", &JSText::SetLineHeight, opt);
1242     JSClass<JSText>::StaticMethod("lineSpacing", &JSText::SetLineSpacing, opt);
1243     JSClass<JSText>::StaticMethod("fontFamily", &JSText::SetFontFamily, opt);
1244     JSClass<JSText>::StaticMethod("minFontSize", &JSText::SetMinFontSize, opt);
1245     JSClass<JSText>::StaticMethod("maxFontSize", &JSText::SetMaxFontSize, opt);
1246     JSClass<JSText>::StaticMethod("letterSpacing", &JSText::SetLetterSpacing, opt);
1247     JSClass<JSText>::StaticMethod("textCase", &JSText::SetTextCase, opt);
1248     JSClass<JSText>::StaticMethod("baselineOffset", &JSText::SetBaselineOffset, opt);
1249     JSClass<JSText>::StaticMethod("caretColor", &JSText::SetTextCaretColor);
1250     JSClass<JSText>::StaticMethod("selectedBackgroundColor", &JSText::SetSelectedBackgroundColor);
1251     JSClass<JSText>::StaticMethod("decoration", &JSText::SetDecoration);
1252     JSClass<JSText>::StaticMethod("heightAdaptivePolicy", &JSText::SetHeightAdaptivePolicy);
1253     JSClass<JSText>::StaticMethod("contentTransition", &JSText::SetContentTransition);
1254     JSClass<JSText>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
1255     JSClass<JSText>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
1256     JSClass<JSText>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
1257     JSClass<JSText>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
1258     JSClass<JSText>::StaticMethod("remoteMessage", &JSText::JsRemoteMessage);
1259     JSClass<JSText>::StaticMethod("copyOption", &JSText::SetCopyOption);
1260     JSClass<JSText>::StaticMethod("onClick", &JSText::JsOnClick);
1261     JSClass<JSText>::StaticMethod("onCopy", &JSText::SetOnCopy);
1262     JSClass<JSText>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
1263     JSClass<JSText>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
1264     JSClass<JSText>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
1265     JSClass<JSText>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
1266     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_FIFTEEN)) {
1267         JSClass<JSText>::StaticMethod("onDragStart", &JSText::JsOnDragStart);
1268     } else {
1269         JSClass<JSText>::StaticMethod("onDragStart", &JSViewAbstract::JsOnDragStart);
1270     }
1271     JSClass<JSText>::StaticMethod("focusable", &JSText::JsFocusable);
1272     JSClass<JSText>::StaticMethod("draggable", &JSText::JsDraggable);
1273     JSClass<JSText>::StaticMethod("enableDataDetector", &JSText::JsEnableDataDetector);
1274     JSClass<JSText>::StaticMethod("dataDetectorConfig", &JSText::JsDataDetectorConfig);
1275     JSClass<JSText>::StaticMethod("bindSelectionMenu", &JSText::BindSelectionMenu);
1276     JSClass<JSText>::StaticMethod("onTextSelectionChange", &JSText::SetOnTextSelectionChange);
1277     JSClass<JSText>::StaticMethod("clip", &JSText::JsClip);
1278     JSClass<JSText>::StaticMethod("foregroundColor", &JSText::SetForegroundColor);
1279     JSClass<JSText>::StaticMethod("fontFeature", &JSText::SetFontFeature);
1280     JSClass<JSText>::StaticMethod("marqueeOptions", &JSText::SetMarqueeOptions);
1281     JSClass<JSText>::StaticMethod("onMarqueeStateChange", &JSText::SetOnMarqueeStateChange);
1282     JSClass<JSText>::StaticMethod("editMenuOptions", &JSText::EditMenuOptions);
1283     JSClass<JSText>::StaticMethod("responseRegion", &JSText::JsResponseRegion);
1284     JSClass<JSText>::StaticMethod("halfLeading", &JSText::SetHalfLeading);
1285     JSClass<JSText>::StaticMethod("enableHapticFeedback", &JSText::SetEnableHapticFeedback);
1286     JSClass<JSText>::StaticMethod("optimizeTrailingSpace", &JSText::SetOptimizeTrailingSpace);
1287     JSClass<JSText>::StaticMethod("enableAutoSpacing", &JSText::SetEnableAutoSpacing);
1288     JSClass<JSText>::StaticMethod("textVerticalAlign", &JSText::SetTextVerticalAlign);
1289     JSClass<JSText>::StaticMethod("shaderStyle", &JSText::SetShaderStyle);
1290     JSClass<JSText>::InheritAndBind<JSContainerBase>(globalObj);
1291 }
1292 
CloseSelectionMenu()1293 void JSTextController::CloseSelectionMenu()
1294 {
1295     auto controller = controllerWeak_.Upgrade();
1296     CHECK_NULL_VOID(controller);
1297     controller->CloseSelectionMenu();
1298 }
1299 
GetLayoutManager(const JSCallbackInfo & args)1300 void JSTextController::GetLayoutManager(const JSCallbackInfo& args)
1301 {
1302     JSRef<JSObject> obj = JSClass<JSLayoutManager>::NewInstance();
1303     auto jsLayoutManager = Referenced::Claim(obj->Unwrap<JSLayoutManager>());
1304     CHECK_NULL_VOID(jsLayoutManager);
1305     jsLayoutManager->IncRefCount();
1306     auto controller = controllerWeak_.Upgrade();
1307     CHECK_NULL_VOID(controller);
1308     auto layoutInfoInterface = controller->GetLayoutInfoInterface();
1309     jsLayoutManager->SetLayoutInfoInterface(layoutInfoInterface);
1310     args.SetReturnValue(obj);
1311 }
1312 
SetStyledString(const JSCallbackInfo & info)1313 void JSTextController::SetStyledString(const JSCallbackInfo& info)
1314 {
1315     if (info.Length() != 1 || !info[0]->IsObject()) {
1316         JSException::Throw(ERROR_CODE_PARAM_INVALID, "%s", "Input parameter check failed.");
1317         return;
1318     }
1319     auto* spanString = JSRef<JSObject>::Cast(info[0])->Unwrap<JSSpanString>();
1320     if (!spanString) {
1321         JSException::Throw(ERROR_CODE_PARAM_INVALID, "%s", "Input parameter check failed.");
1322         return;
1323     }
1324     auto spanStringController = spanString->GetController();
1325     CHECK_NULL_VOID(spanStringController);
1326     auto controller = controllerWeak_.Upgrade();
1327     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FIFTEEN) && !controller) {
1328         styledString_ = spanStringController;
1329     }
1330     CHECK_NULL_VOID(controller);
1331     controller->SetStyledString(spanStringController, true);
1332     auto thisObj = info.This();
1333     thisObj->SetPropertyObject("STYLED_STRING_IN_CONTROLLER", info[0]);
1334 }
1335 
JSBind(BindingTarget globalObj)1336 void JSTextController::JSBind(BindingTarget globalObj)
1337 {
1338     JSClass<JSTextController>::Declare("TextController");
1339     JSClass<JSTextController>::Method("closeSelectionMenu", &JSTextController::CloseSelectionMenu);
1340     JSClass<JSTextController>::CustomMethod("setStyledString", &JSTextController::SetStyledString);
1341     JSClass<JSTextController>::CustomMethod("getLayoutManager", &JSTextController::GetLayoutManager);
1342     JSClass<JSTextController>::Bind(globalObj, JSTextController::Constructor, JSTextController::Destructor);
1343 }
1344 
ParseMenuParam(const JSCallbackInfo & info,const JSRef<JSObject> & menuOptions,NG::SelectMenuParam & menuParam)1345 void JSText::ParseMenuParam(
1346     const JSCallbackInfo& info, const JSRef<JSObject>& menuOptions, NG::SelectMenuParam& menuParam)
1347 {
1348     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1349     auto onAppearValue = menuOptions->GetProperty("onAppear");
1350     if (onAppearValue->IsFunction()) {
1351         RefPtr<JsFunction> jsOnAppearFunc =
1352             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAppearValue));
1353         auto onAppear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAppearFunc), node = frameNode](
1354                             int32_t start, int32_t end) {
1355             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1356             ACE_SCORING_EVENT("onAppear");
1357 
1358             JSRef<JSVal> params[2];
1359             params[0] = JSRef<JSVal>::Make(ToJSValue(start));
1360             params[1] = JSRef<JSVal>::Make(ToJSValue(end));
1361             PipelineContext::SetCallBackNode(node);
1362             func->ExecuteJS(2, params);
1363         };
1364         menuParam.onAppear = std::move(onAppear);
1365     }
1366 
1367     auto onDisappearValue = menuOptions->GetProperty("onDisappear");
1368     if (onDisappearValue->IsFunction()) {
1369         RefPtr<JsFunction> jsOnDisAppearFunc =
1370             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDisappearValue));
1371         auto onDisappear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDisAppearFunc),
1372                                node = frameNode]() {
1373             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1374             ACE_SCORING_EVENT("onDisappear");
1375             PipelineContext::SetCallBackNode(node);
1376             func->Execute();
1377         };
1378         menuParam.onDisappear = std::move(onDisappear);
1379     }
1380     menuParam.onMenuShow = ParseMenuCallback(frameNode, menuOptions, info, "onMenuShow");
1381     menuParam.onMenuHide = ParseMenuCallback(frameNode, menuOptions, info, "onMenuHide");
1382     menuParam.previewMenuOptions = ParsePreviewMenuOptions(menuOptions);
1383 }
1384 
ParseMenuCallback(const WeakPtr<NG::FrameNode> & frameNode,const JSRef<JSObject> & menuOptions,const JSCallbackInfo & info,const std::string & name)1385 std::function<void(int32_t, int32_t)> JSText::ParseMenuCallback(const WeakPtr<NG::FrameNode>& frameNode,
1386     const JSRef<JSObject>& menuOptions, const JSCallbackInfo& info, const std::string& name)
1387 {
1388     auto onMenuCallbackValue = menuOptions->GetProperty(name.c_str());
1389     if (onMenuCallbackValue->IsFunction()) {
1390         RefPtr<JsFunction> jsOnMenuCallbackFunc =
1391             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onMenuCallbackValue));
1392         auto onMenuCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsOnMenuCallbackFunc),
1393                                   node = frameNode, eventName = name](int32_t start, int32_t end) {
1394             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1395             ACE_SCORING_EVENT(eventName);
1396 
1397             JSRef<JSVal> params[2];
1398             params[0] = JSRef<JSVal>::Make(ToJSValue(start));
1399             params[1] = JSRef<JSVal>::Make(ToJSValue(end));
1400             PipelineContext::SetCallBackNode(node);
1401             func->ExecuteJS(2, params);
1402         };
1403         return onMenuCallback;
1404     }
1405     return nullptr;
1406 }
1407 
ParsePreviewMenuOptions(const JSRef<JSObject> & menuOptions)1408 NG::PreviewMenuOptions JSText::ParsePreviewMenuOptions(const JSRef<JSObject>& menuOptions)
1409 {
1410     NG::PreviewMenuOptions previewMenuOptions;
1411     auto jsPreviewMenuOp = menuOptions->GetProperty("previewMenuOptions");
1412     CHECK_EQUAL_RETURN(jsPreviewMenuOp->IsObject(), false, previewMenuOptions);
1413     auto jsPreviewMenuOpObj = JSRef<JSObject>::Cast(jsPreviewMenuOp);
1414     CHECK_EQUAL_RETURN(jsPreviewMenuOpObj->IsUndefined(), true, previewMenuOptions);
1415     JSRef<JSVal> jsHapticFeedbackMode = jsPreviewMenuOpObj->GetProperty("hapticFeedbackMode");
1416     CHECK_EQUAL_RETURN(jsHapticFeedbackMode->IsNumber(), false, previewMenuOptions);
1417     auto hapticFeedbackMode = static_cast<HapticFeedbackMode>(jsHapticFeedbackMode->ToNumber<int32_t>());
1418     if (hapticFeedbackMode >= HapticFeedbackMode::DISABLED && hapticFeedbackMode <= HapticFeedbackMode::AUTO) {
1419         previewMenuOptions.hapticFeedbackMode = hapticFeedbackMode;
1420     }
1421     return previewMenuOptions;
1422 }
1423 
SetMarqueeOptions(const JSCallbackInfo & info)1424 void JSText::SetMarqueeOptions(const JSCallbackInfo& info)
1425 {
1426     if (info.Length() < 1) {
1427         return;
1428     }
1429 
1430     auto args = info[0];
1431     NG::TextMarqueeOptions options;
1432 
1433     if (!args->IsObject()) {
1434         TextModel::GetInstance()->SetMarqueeOptions(options);
1435         return;
1436     }
1437 
1438     auto paramObject = JSRef<JSObject>::Cast(args);
1439     ParseMarqueeParam(paramObject, options);
1440     TextModel::GetInstance()->SetMarqueeOptions(options);
1441 }
1442 
ParseMarqueeParam(const JSRef<JSObject> & paramObject,NG::TextMarqueeOptions & options)1443 void JSText::ParseMarqueeParam(const JSRef<JSObject>& paramObject, NG::TextMarqueeOptions& options)
1444 {
1445     auto getStart = paramObject->GetProperty("start");
1446     if (getStart->IsBoolean()) {
1447         options.UpdateTextMarqueeStart(getStart->ToBoolean());
1448     }
1449 
1450     auto getLoop = paramObject->GetProperty("loop");
1451     if (getLoop->IsNumber()) {
1452         int32_t loop = static_cast<int32_t>(getLoop->ToNumber<double>());
1453         if (loop == std::numeric_limits<int32_t>::max() || loop <= 0) {
1454             loop = -1;
1455         }
1456         options.UpdateTextMarqueeLoop(loop);
1457     }
1458 
1459     auto getStep = paramObject->GetProperty("step");
1460     if (getStep->IsNumber()) {
1461         auto step = getStep->ToNumber<double>();
1462         if (GreatNotEqual(step, 0.0)) {
1463             options.UpdateTextMarqueeStep(Dimension(step, DimensionUnit::VP).ConvertToPx());
1464         }
1465     }
1466 
1467     auto delay = paramObject->GetProperty("delay");
1468     if (delay->IsNumber()) {
1469         auto delayDouble = delay->ToNumber<double>();
1470         auto delayValue = static_cast<int32_t>(delayDouble);
1471         if (delayValue < 0) {
1472             delayValue = 0;
1473         }
1474         options.UpdateTextMarqueeDelay(delayValue);
1475     }
1476 
1477     auto getFromStart = paramObject->GetProperty("fromStart");
1478     if (getFromStart->IsBoolean()) {
1479         options.UpdateTextMarqueeDirection(
1480             getFromStart->ToBoolean() ? MarqueeDirection::DEFAULT : MarqueeDirection::DEFAULT_REVERSE);
1481     }
1482 
1483     auto getFadeout = paramObject->GetProperty("fadeout");
1484     if (getFadeout->IsBoolean()) {
1485         options.UpdateTextMarqueeFadeout(getFadeout->ToBoolean());
1486     }
1487 
1488     auto getStartPolicy = paramObject->GetProperty("marqueeStartPolicy");
1489     if (getStartPolicy->IsNumber()) {
1490         auto startPolicy = static_cast<MarqueeStartPolicy>(getStartPolicy->ToNumber<int32_t>());
1491         options.UpdateTextMarqueeStartPolicy(startPolicy);
1492     }
1493 }
1494 
SetOnMarqueeStateChange(const JSCallbackInfo & info)1495 void JSText::SetOnMarqueeStateChange(const JSCallbackInfo& info)
1496 {
1497     if (!info[0]->IsFunction()) {
1498         return;
1499     }
1500 
1501     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
1502     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1503     auto onMarqueeStateChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
1504                                     int32_t value) {
1505         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1506         ACE_SCORING_EVENT("Text.onMarqueeStateChange");
1507         PipelineContext::SetCallBackNode(node);
1508         auto newJSVal = JSRef<JSVal>::Make(ToJSValue(value));
1509         func->ExecuteJS(1, &newJSVal);
1510     };
1511 
1512     TextModel::GetInstance()->SetOnMarqueeStateChange(std::move(onMarqueeStateChange));
1513 }
1514 
EditMenuOptions(const JSCallbackInfo & info)1515 void JSText::EditMenuOptions(const JSCallbackInfo& info)
1516 {
1517     NG::OnCreateMenuCallback onCreateMenuCallback;
1518     NG::OnMenuItemClickCallback onMenuItemClick;
1519     NG::OnPrepareMenuCallback onPrepareMenuCallback;
1520     JSViewAbstract::ParseEditMenuOptions(info, onCreateMenuCallback, onMenuItemClick, onPrepareMenuCallback);
1521     TextModel::GetInstance()->SetSelectionMenuOptions(
1522         std::move(onCreateMenuCallback), std::move(onMenuItemClick), std::move(onPrepareMenuCallback));
1523 }
1524 } // namespace OHOS::Ace::Framework
1525