• 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_text_theme.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/text/text_theme.h"
50 #include "core/components_ng/base/view_stack_processor.h"
51 #include "core/components_ng/event/gesture_event_hub.h"
52 #include "core/components_ng/pattern/text/text_model.h"
53 #include "core/components_ng/pattern/text/text_model_ng.h"
54 #include "core/event/ace_event_handler.h"
55 #include "core/pipeline/pipeline_base.h"
56 
57 namespace OHOS::Ace {
58 
59 std::unique_ptr<TextModel> TextModel::instance_ = nullptr;
60 std::mutex TextModel::mutex_;
61 
GetInstance()62 TextModel* TextModel::GetInstance()
63 {
64 #ifdef NG_BUILD
65     static NG::TextModelNG instance;
66     return &instance;
67 #else
68     if (Container::IsCurrentUseNewPipeline()) {
69         static NG::TextModelNG instance;
70         return &instance;
71     } else {
72         static Framework::TextModelImpl instance;
73         return &instance;
74     }
75 #endif
76 }
77 
78 } // namespace OHOS::Ace
79 
80 namespace OHOS::Ace::Framework {
81 namespace {
82 
83 const std::vector<TextCase> TEXT_CASES = { TextCase::NORMAL, TextCase::LOWERCASE, TextCase::UPPERCASE };
84 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
85     TextOverflow::MARQUEE };
86 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
87 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END, TextAlign::JUSTIFY,
88     TextAlign::LEFT, TextAlign::RIGHT };
89 const std::vector<TextHeightAdaptivePolicy> HEIGHT_ADAPTIVE_POLICY = { TextHeightAdaptivePolicy::MAX_LINES_FIRST,
90     TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST };
91 const std::vector<LineBreakStrategy> LINE_BREAK_STRATEGY_TYPES = { LineBreakStrategy::GREEDY,
92     LineBreakStrategy::HIGH_QUALITY, LineBreakStrategy::BALANCED };
93 const std::vector<EllipsisMode> ELLIPSIS_MODALS = { EllipsisMode::HEAD, EllipsisMode::MIDDLE, EllipsisMode::TAIL };
94 const std::vector<TextSelectableMode> TEXT_SELECTABLE_MODE = { TextSelectableMode::SELECTABLE_UNFOCUSABLE,
95     TextSelectableMode::SELECTABLE_FOCUSABLE, TextSelectableMode::UNSELECTABLE };
96 constexpr TextDecorationStyle DEFAULT_TEXT_DECORATION_STYLE = TextDecorationStyle::SOLID;
97 const int32_t DEFAULT_VARIABLE_FONT_WEIGHT = 400;
98 }; // namespace
99 
SetWidth(const JSCallbackInfo & info)100 void JSText::SetWidth(const JSCallbackInfo& info)
101 {
102     JSViewAbstract::JsWidth(info);
103     TextModel::GetInstance()->OnSetWidth();
104 }
105 
SetHeight(const JSCallbackInfo & info)106 void JSText::SetHeight(const JSCallbackInfo& info)
107 {
108     JSViewAbstract::JsHeight(info);
109     TextModel::GetInstance()->OnSetHeight();
110 }
111 
SetFont(const JSCallbackInfo & info)112 void JSText::SetFont(const JSCallbackInfo& info)
113 {
114     Font font;
115     GetFontInfo(info, font);
116     TextModel::GetInstance()->SetFont(font);
117     if (info.Length() < 2) { // 2 : two args
118         return;
119     }
120     auto tmpInfo = info[1];
121     if (!tmpInfo->IsObject()) {
122         return;
123     }
124     auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
125     auto enableVariableFontWeight = paramObject->GetProperty("enableVariableFontWeight");
126     if (enableVariableFontWeight->IsBoolean()) {
127         TextModel::GetInstance()->SetEnableVariableFontWeight(enableVariableFontWeight->ToBoolean());
128     } else {
129         TextModel::GetInstance()->SetEnableVariableFontWeight(false);
130     }
131 }
132 
GetFontInfo(const JSCallbackInfo & info,Font & font)133 void JSText::GetFontInfo(const JSCallbackInfo& info, Font& font)
134 {
135     auto tmpInfo = info[0];
136     auto pipelineContext = PipelineContext::GetCurrentContext();
137     CHECK_NULL_VOID(pipelineContext);
138     auto theme = pipelineContext->GetTheme<TextTheme>();
139     CHECK_NULL_VOID(theme);
140     font.fontSize = theme->GetTextStyle().GetFontSize();
141     font.fontWeight = theme->GetTextStyle().GetFontWeight();
142     font.fontFamilies = theme->GetTextStyle().GetFontFamilies();
143     font.fontStyle = theme->GetTextStyle().GetFontStyle();
144 
145     if (!tmpInfo->IsObject()) {
146         return;
147     }
148     auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
149     auto fontSize = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::SIZE));
150     CalcDimension size;
151     if (ParseJsDimensionFpNG(fontSize, size, false) && size.IsNonNegative()) {
152         font.fontSize = size;
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         if (JSContainerBase::ParseJsFontFamilies(fontFamily, fontFamilies)) {
171             font.fontFamilies = fontFamilies;
172         }
173     }
174     auto style = paramObject->GetProperty(static_cast<int32_t>(ArkUIIndex::STYLE));
175     if (!style->IsNull() || style->IsNumber()) {
176         font.fontStyle = static_cast<FontStyle>(style->ToNumber<int32_t>());
177     }
178 }
179 
SetFontSize(const JSCallbackInfo & info)180 void JSText::SetFontSize(const JSCallbackInfo& info)
181 {
182     if (info.Length() < 1) {
183         return;
184     }
185     CalcDimension fontSize;
186     JSRef<JSVal> args = info[0];
187     if (!ParseJsDimensionFpNG(args, fontSize, false) || fontSize.IsNegative()) {
188         auto pipelineContext = PipelineBase::GetCurrentContext();
189         CHECK_NULL_VOID(pipelineContext);
190         auto theme = pipelineContext->GetTheme<TextTheme>();
191         CHECK_NULL_VOID(theme);
192         fontSize = theme->GetTextStyle().GetFontSize();
193         TextModel::GetInstance()->SetFontSize(fontSize);
194         return;
195     }
196     TextModel::GetInstance()->SetFontSize(fontSize);
197 }
198 
SetFontWeight(const JSCallbackInfo & info)199 void JSText::SetFontWeight(const JSCallbackInfo& info)
200 {
201     if (info.Length() < 1) {
202         return;
203     }
204     JSRef<JSVal> args = info[0];
205     std::string fontWeight;
206     int32_t variableFontWeight = DEFAULT_VARIABLE_FONT_WEIGHT;
207     ParseJsInt32(args, variableFontWeight);
208     TextModel::GetInstance()->SetVariableFontWeight(variableFontWeight);
209 
210     if (args->IsNumber()) {
211         fontWeight = args->ToString();
212     } else {
213         ParseJsString(args, fontWeight);
214     }
215     TextModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(fontWeight));
216 
217     if (info.Length() < 2) { // 2 : two args
218         return;
219     }
220     auto tmpInfo = info[1];
221     if (!tmpInfo->IsObject()) {
222         return;
223     }
224     auto paramObject = JSRef<JSObject>::Cast(tmpInfo);
225     auto enableVariableFontWeight = paramObject->GetProperty("enableVariableFontWeight");
226     if (enableVariableFontWeight->IsBoolean()) {
227         TextModel::GetInstance()->SetEnableVariableFontWeight(enableVariableFontWeight->ToBoolean());
228     } else {
229         TextModel::GetInstance()->SetEnableVariableFontWeight(false);
230     }
231 }
232 
SetMinFontScale(const JSCallbackInfo & info)233 void JSText::SetMinFontScale(const JSCallbackInfo& info)
234 {
235     double minFontScale;
236     if (info.Length() < 1 || !ParseJsDouble(info[0], minFontScale)) {
237         return;
238     }
239     if (LessOrEqual(minFontScale, 0.0f)) {
240         TextModel::GetInstance()->SetMinFontScale(0.0f);
241         return;
242     }
243     if (GreatOrEqual(minFontScale, 1.0f)) {
244         TextModel::GetInstance()->SetMinFontScale(1.0f);
245         return;
246     }
247     TextModel::GetInstance()->SetMinFontScale(static_cast<float>(minFontScale));
248 }
249 
SetMaxFontScale(const JSCallbackInfo & info)250 void JSText::SetMaxFontScale(const JSCallbackInfo& info)
251 {
252     double maxFontScale;
253     if (info.Length() < 1 || !ParseJsDouble(info[0], maxFontScale)) {
254         return;
255     }
256     if (LessOrEqual(maxFontScale, 1.0f)) {
257         TextModel::GetInstance()->SetMaxFontScale(1.0f);
258         return;
259     }
260     TextModel::GetInstance()->SetMaxFontScale(static_cast<float>(maxFontScale));
261 }
262 
SetForegroundColor(const JSCallbackInfo & info)263 void JSText::SetForegroundColor(const JSCallbackInfo& info)
264 {
265     if (info.Length() < 1) {
266         return;
267     }
268     ForegroundColorStrategy strategy;
269     if (ParseJsColorStrategy(info[0], strategy)) {
270         TextModel::GetInstance()->SetTextColor(Color::FOREGROUND);
271         ViewAbstractModel::GetInstance()->SetForegroundColorStrategy(strategy);
272         return;
273     }
274     SetTextColor(info);
275 }
276 
SetTextColor(const JSCallbackInfo & info)277 void JSText::SetTextColor(const JSCallbackInfo& info)
278 {
279     if (info.Length() < 1) {
280         return;
281     }
282     Color textColor;
283     JSRef<JSVal> args = info[0];
284     if (!ParseJsColor(args, textColor)) {
285         auto pipelineContext = PipelineBase::GetCurrentContext();
286         CHECK_NULL_VOID(pipelineContext);
287         auto theme = pipelineContext->GetTheme<TextTheme>();
288         CHECK_NULL_VOID(theme);
289         textColor = theme->GetTextStyle().GetTextColor();
290     }
291     TextModel::GetInstance()->SetTextColor(textColor);
292 }
293 
SetTextShadow(const JSCallbackInfo & info)294 void JSText::SetTextShadow(const JSCallbackInfo& info)
295 {
296     if (info.Length() < 1) {
297         return;
298     }
299     std::vector<Shadow> shadows;
300     JSRef<JSVal> args = info[0];
301     ParseTextShadowFromShadowObject(args, shadows);
302     TextModel::GetInstance()->SetTextShadow(shadows);
303 }
304 
SetTextOverflow(const JSCallbackInfo & info)305 void JSText::SetTextOverflow(const JSCallbackInfo& info)
306 {
307     do {
308         auto tmpInfo = info[0];
309         if (!tmpInfo->IsObject()) {
310             break;
311         }
312         JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
313         JSRef<JSVal> overflowValue = obj->GetProperty("overflow");
314         if (!overflowValue->IsNumber() && !overflowValue->IsUndefined()) {
315             break;
316         }
317         auto overflow = overflowValue->ToNumber<int32_t>();
318         if (overflowValue->IsUndefined()) {
319             overflow = 0;
320         } else if (overflow < 0 || overflow >= static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
321             break;
322         }
323         TextModel::GetInstance()->SetTextOverflow(TEXT_OVERFLOWS[overflow]);
324     } while (false);
325 
326     info.SetReturnValue(info.This());
327 }
328 
SetWordBreak(const JSCallbackInfo & info)329 void JSText::SetWordBreak(const JSCallbackInfo& info)
330 {
331     JSRef<JSVal> args = info[0];
332     if (!args->IsNumber()) {
333         return;
334     }
335     uint32_t index = args->ToNumber<uint32_t>();
336     if (index < WORD_BREAK_TYPES.size()) {
337         TextModel::GetInstance()->SetWordBreak(WORD_BREAK_TYPES[index]);
338     }
339 }
340 
SetEllipsisMode(const JSCallbackInfo & info)341 void JSText::SetEllipsisMode(const JSCallbackInfo& info)
342 {
343     JSRef<JSVal> args = info[0];
344     if (!args->IsNumber()) {
345         return;
346     }
347     uint32_t index = args->ToNumber<uint32_t>();
348     if (index < ELLIPSIS_MODALS.size()) {
349         TextModel::GetInstance()->SetEllipsisMode(ELLIPSIS_MODALS[index]);
350     }
351 }
352 
SetLineBreakStrategy(const JSCallbackInfo & info)353 void JSText::SetLineBreakStrategy(const JSCallbackInfo& info)
354 {
355     if (info.Length() < 1) {
356         TextModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
357         return;
358     }
359     if (!info[0]->IsNumber()) {
360         TextModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
361         return;
362     }
363     auto index = info[0]->ToNumber<int32_t>();
364     if (index < 0 || index >= static_cast<int32_t>(LINE_BREAK_STRATEGY_TYPES.size())) {
365         TextModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
366         return;
367     }
368     TextModel::GetInstance()->SetLineBreakStrategy(LINE_BREAK_STRATEGY_TYPES[index]);
369 }
370 
SetTextSelection(const JSCallbackInfo & info)371 void JSText::SetTextSelection(const JSCallbackInfo& info)
372 {
373     if (info.Length() < 1) {
374         return;
375     }
376     JSRef<JSVal> argsStartIndex = info[0];
377     JSRef<JSVal> argsEndIndex = info[1];
378     if (!argsStartIndex->IsNumber() || !argsEndIndex->IsNumber()) {
379         return;
380     }
381     auto startIndex = argsStartIndex->ToNumber<int32_t>();
382     auto endIndex = argsEndIndex->ToNumber<int32_t>();
383     if (startIndex == -1 && endIndex == -1) {
384         TextModel::GetInstance()->SetTextSelection(startIndex, endIndex);
385         return;
386     }
387     if (startIndex >= endIndex) {
388         return;
389     }
390     TextModel::GetInstance()->SetTextSelection(startIndex, endIndex);
391 }
392 
SetTextCaretColor(const JSCallbackInfo & info)393 void JSText::SetTextCaretColor(const JSCallbackInfo& info)
394 {
395     if (info.Length() < 1) {
396         return;
397     }
398     Color caretColor;
399     if (!ParseJsColor(info[0], caretColor)) {
400         auto pipelineContext = PipelineContext::GetCurrentContextSafely();
401         CHECK_NULL_VOID(pipelineContext);
402         auto theme = pipelineContext->GetTheme<TextTheme>();
403         CHECK_NULL_VOID(theme);
404         caretColor = theme->GetCaretColor();
405     }
406     TextModel::GetInstance()->SetTextCaretColor(caretColor);
407 }
408 
SetSelectedBackgroundColor(const JSCallbackInfo & info)409 void JSText::SetSelectedBackgroundColor(const JSCallbackInfo& info)
410 {
411     if (info.Length() < 1) {
412         return;
413     }
414     Color selectedColor;
415     if (!ParseJsColor(info[0], selectedColor)) {
416         auto pipelineContext = PipelineContext::GetCurrentContextSafely();
417         CHECK_NULL_VOID(pipelineContext);
418         auto theme = pipelineContext->GetTheme<TextTheme>();
419         CHECK_NULL_VOID(theme);
420         selectedColor = theme->GetSelectedColor();
421     }
422     // Alpha = 255 means opaque
423     if (selectedColor.GetAlpha() == JSThemeUtils::DEFAULT_ALPHA) {
424         // Default setting of 20% opacity
425         selectedColor = selectedColor.ChangeOpacity(JSThemeUtils::DEFAULT_OPACITY);
426     }
427     TextModel::GetInstance()->SetSelectedBackgroundColor(selectedColor);
428 }
429 
SetTextSelectableMode(const JSCallbackInfo & info)430 void JSText::SetTextSelectableMode(const JSCallbackInfo& info)
431 {
432     if (info.Length() < 1) {
433         TextModel::GetInstance()->SetTextSelectableMode(TextSelectableMode::SELECTABLE_UNFOCUSABLE);
434         return;
435     }
436     if (!info[0]->IsNumber()) {
437         TextModel::GetInstance()->SetTextSelectableMode(TextSelectableMode::SELECTABLE_UNFOCUSABLE);
438         return;
439     }
440     auto index = info[0]->ToNumber<int32_t>();
441     if (index < 0 || index >= static_cast<int32_t>(TEXT_SELECTABLE_MODE.size())) {
442         TextModel::GetInstance()->SetTextSelectableMode(TextSelectableMode::SELECTABLE_UNFOCUSABLE);
443         return;
444     }
445     TextModel::GetInstance()->SetTextSelectableMode(TEXT_SELECTABLE_MODE[index]);
446 }
447 
SetMaxLines(const JSCallbackInfo & info)448 void JSText::SetMaxLines(const JSCallbackInfo& info)
449 {
450     JSRef<JSVal> args = info[0];
451     auto value = Infinity<int32_t>();
452     if (args->ToString() != "Infinity") {
453         ParseJsInt32(args, value);
454     }
455     TextModel::GetInstance()->SetMaxLines(value);
456 }
457 
SetTextIndent(const JSCallbackInfo & info)458 void JSText::SetTextIndent(const JSCallbackInfo& info)
459 {
460     CalcDimension value;
461     JSRef<JSVal> args = info[0];
462     if (!ParseJsDimensionFpNG(args, value)) {
463         value.Reset();
464         TextModel::GetInstance()->SetTextIndent(value);
465         return;
466     }
467     TextModel::GetInstance()->SetTextIndent(value);
468 }
469 
SetFontStyle(int32_t value)470 void JSText::SetFontStyle(int32_t value)
471 {
472     if (value < 0 || value >= static_cast<int32_t>(FONT_STYLES.size())) {
473         if (!(AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE))) {
474             return;
475         }
476         value = 0;
477     }
478     TextModel::GetInstance()->SetItalicFontStyle(FONT_STYLES[value]);
479 }
480 
SetTextAlign(int32_t value)481 void JSText::SetTextAlign(int32_t value)
482 {
483     if (value < 0 || value >= static_cast<int32_t>(TEXT_ALIGNS.size())) {
484         if (!(AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE))) {
485             return;
486         }
487         value = 0;
488     }
489     TextModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
490 }
491 
SetAlign(const JSCallbackInfo & info)492 void JSText::SetAlign(const JSCallbackInfo& info)
493 {
494     JSViewAbstract::JsAlign(info);
495     JSRef<JSVal> args = info[0];
496     if (!args->IsNumber()) {
497         return;
498     }
499     TextModel::GetInstance()->OnSetAlign();
500 }
501 
SetLineHeight(const JSCallbackInfo & info)502 void JSText::SetLineHeight(const JSCallbackInfo& info)
503 {
504     CalcDimension value;
505     JSRef<JSVal> args = info[0];
506     if (!ParseJsDimensionFpNG(args, value)) {
507         value.Reset();
508         TextModel::GetInstance()->SetLineHeight(value);
509         return;
510     }
511     if (value.IsNegative()) {
512         value.Reset();
513     }
514     TextModel::GetInstance()->SetLineHeight(value);
515 }
516 
SetLineSpacing(const JSCallbackInfo & info)517 void JSText::SetLineSpacing(const JSCallbackInfo& info)
518 {
519     CalcDimension value;
520     JSRef<JSVal> args = info[0];
521     if (!ParseLengthMetricsToPositiveDimension(args, value)) {
522         value.Reset();
523     }
524     if (value.IsNegative()) {
525         value.Reset();
526     }
527     TextModel::GetInstance()->SetLineSpacing(value);
528 }
529 
SetFontFamily(const JSCallbackInfo & info)530 void JSText::SetFontFamily(const JSCallbackInfo& info)
531 {
532     std::vector<std::string> fontFamilies;
533     JSRef<JSVal> args = info[0];
534     ParseJsFontFamilies(args, fontFamilies);
535     TextModel::GetInstance()->SetFontFamily(fontFamilies);
536 }
537 
SetMinFontSize(const JSCallbackInfo & info)538 void JSText::SetMinFontSize(const JSCallbackInfo& info)
539 {
540     if (info.Length() < 1) {
541         return;
542     }
543     auto pipelineContext = PipelineBase::GetCurrentContext();
544     CHECK_NULL_VOID(pipelineContext);
545     auto theme = pipelineContext->GetTheme<TextTheme>();
546     CHECK_NULL_VOID(theme);
547     CalcDimension minFontSize = theme->GetTextStyle().GetAdaptMinFontSize();
548     JSRef<JSVal> args = info[0];
549     if (!ParseJsDimensionFpNG(args, minFontSize, false)) {
550         minFontSize = theme->GetTextStyle().GetAdaptMinFontSize();
551         TextModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
552         return;
553     }
554     if (minFontSize.IsNegative()) {
555         minFontSize = theme->GetTextStyle().GetAdaptMinFontSize();
556     }
557     TextModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
558 }
559 
SetMaxFontSize(const JSCallbackInfo & info)560 void JSText::SetMaxFontSize(const JSCallbackInfo& info)
561 {
562     if (info.Length() < 1) {
563         return;
564     }
565     auto pipelineContext = PipelineBase::GetCurrentContext();
566     CHECK_NULL_VOID(pipelineContext);
567     auto theme = pipelineContext->GetTheme<TextTheme>();
568     CHECK_NULL_VOID(theme);
569     CalcDimension maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
570     JSRef<JSVal> args = info[0];
571     if (!ParseJsDimensionFpNG(args, maxFontSize, false)) {
572         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
573         TextModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
574         return;
575     }
576     if (maxFontSize.IsNegative()) {
577         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
578     }
579     TextModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
580 }
581 
SetLetterSpacing(const JSCallbackInfo & info)582 void JSText::SetLetterSpacing(const JSCallbackInfo& info)
583 {
584     CalcDimension value;
585     JSRef<JSVal> args = info[0];
586     if (!ParseJsDimensionFpNG(args, value, false)) {
587         value.Reset();
588         TextModel::GetInstance()->SetLetterSpacing(value);
589         return;
590     }
591     TextModel::GetInstance()->SetLetterSpacing(value);
592 }
593 
SetTextCase(int32_t value)594 void JSText::SetTextCase(int32_t value)
595 {
596     if (value < 0 || value >= static_cast<int32_t>(TEXT_CASES.size())) {
597         if (!(AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE))) {
598             return;
599         }
600         value = 0;
601     }
602     TextModel::GetInstance()->SetTextCase(TEXT_CASES[value]);
603 }
604 
SetBaselineOffset(const JSCallbackInfo & info)605 void JSText::SetBaselineOffset(const JSCallbackInfo& info)
606 {
607     CalcDimension value;
608     JSRef<JSVal> args = info[0];
609     if (!ParseJsDimensionFpNG(args, value, false)) {
610         value.Reset();
611         TextModel::GetInstance()->SetBaselineOffset(value);
612         return;
613     }
614     TextModel::GetInstance()->SetBaselineOffset(value);
615 }
616 
SetDecoration(const JSCallbackInfo & info)617 void JSText::SetDecoration(const JSCallbackInfo& info)
618 {
619     auto tmpInfo = info[0];
620     if (tmpInfo->IsUndefined()) {
621         TextModel::GetInstance()->SetTextDecoration(TextDecoration::NONE);
622         info.ReturnSelf();
623         return;
624     }
625     if (!tmpInfo->IsObject()) {
626         info.ReturnSelf();
627         return;
628     }
629     JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
630     JSRef<JSVal> typeValue = obj->GetProperty("type");
631     JSRef<JSVal> colorValue = obj->GetProperty("color");
632     JSRef<JSVal> styleValue = obj->GetProperty("style");
633 
634     TextDecoration textDecoration;
635     if (typeValue->IsNumber()) {
636         textDecoration = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
637     } else {
638         auto theme = GetTheme<TextTheme>();
639         CHECK_NULL_VOID(theme);
640         textDecoration = theme->GetTextStyle().GetTextDecoration();
641     }
642     Color result;
643     if (!ParseJsColor(colorValue, result)) {
644         auto theme = GetTheme<TextTheme>();
645         CHECK_NULL_VOID(theme);
646         if (SystemProperties::GetColorMode() == ColorMode::DARK) {
647             result = theme->GetTextStyle().GetTextColor();
648         } else {
649             result = theme->GetTextStyle().GetTextDecorationColor();
650         }
651     }
652     std::optional<TextDecorationStyle> textDecorationStyle;
653     if (styleValue->IsNumber()) {
654         textDecorationStyle = static_cast<TextDecorationStyle>(styleValue->ToNumber<int32_t>());
655     } else {
656         textDecorationStyle = DEFAULT_TEXT_DECORATION_STYLE;
657     }
658     TextModel::GetInstance()->SetTextDecoration(textDecoration);
659     TextModel::GetInstance()->SetTextDecorationColor(result);
660     if (textDecorationStyle) {
661         TextModel::GetInstance()->SetTextDecorationStyle(textDecorationStyle.value());
662     }
663     info.ReturnSelf();
664 }
665 
SetHeightAdaptivePolicy(int32_t value)666 void JSText::SetHeightAdaptivePolicy(int32_t value)
667 {
668     if (value < 0 || value >= static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICY.size())) {
669         if (!(AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE))) {
670             return;
671         }
672         value = 0;
673     }
674     TextModel::GetInstance()->SetHeightAdaptivePolicy(HEIGHT_ADAPTIVE_POLICY[value]);
675 }
676 
JsOnClick(const JSCallbackInfo & info)677 void JSText::JsOnClick(const JSCallbackInfo& info)
678 {
679     JSRef<JSVal> args = info[0];
680     if (Container::IsCurrentUseNewPipeline()) {
681         if (args->IsUndefined() && IsDisableEventVersion()) {
682             TextModel::GetInstance()->ClearOnClick();
683             return;
684         }
685         if (!args->IsFunction()) {
686             return;
687         }
688         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
689         auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(args));
690         auto onClick = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, weakNode = frameNode]
691             (BaseEventInfo* info) {
692             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
693             auto* clickInfo = TypeInfoHelper::DynamicCast<GestureEvent>(info);
694             ACE_SCORING_EVENT("Text.onClick");
695             PipelineContext::SetCallBackNode(weakNode);
696             func->Execute(*clickInfo);
697 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
698             std::string label = "";
699             auto node = weakNode.Upgrade();
700             if (node) {
701                 auto pattern = node.GetRawPtr()->GetPattern();
702                 CHECK_NULL_VOID(pattern);
703                 auto layoutProperty = pattern->GetLayoutProperty<NG::TextLayoutProperty>();
704                 CHECK_NULL_VOID(layoutProperty);
705                 label = layoutProperty->GetContent().value_or("");
706             }
707             JSInteractableView::ReportClickEvent(node, label);
708 #endif
709         };
710         TextModel::GetInstance()->SetOnClick(std::move(onClick));
711 
712         auto focusHub = NG::ViewStackProcessor::GetInstance()->GetOrCreateMainFrameNodeFocusHub();
713         CHECK_NULL_VOID(focusHub);
714         focusHub->SetFocusable(true, false);
715     } else {
716         JsOnClickWithoutNGBUILD(info);
717     }
718 }
719 
JsOnClickWithoutNGBUILD(const JSCallbackInfo & info)720 void JSText::JsOnClickWithoutNGBUILD(const JSCallbackInfo& info)
721 {
722 #ifndef NG_BUILD
723     JSRef<JSVal> args = info[0];
724     if (args->IsFunction()) {
725         auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
726         auto impl = inspector ? inspector->GetInspectorFunctionImpl() : nullptr;
727         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
728         RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(args));
729         auto onClickId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), impl,
730                              node = frameNode](const BaseEventInfo* info) {
731             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
732             const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
733             auto newInfo = *clickInfo;
734             if (impl) {
735                 impl->UpdateEventInfo(newInfo);
736             }
737             ACE_SCORING_EVENT("Text.onClick");
738             PipelineContext::SetCallBackNode(node);
739             func->Execute(newInfo);
740         };
741         TextModel::GetInstance()->SetOnClick(std::move(onClickId));
742     }
743 #endif
744 }
745 
JsRemoteMessage(const JSCallbackInfo & info)746 void JSText::JsRemoteMessage(const JSCallbackInfo& info)
747 {
748     JSInteractableView::JsCommonRemoteMessage(info);
749     auto callback = JSInteractableView::GetRemoteMessageEventCallback(info);
750     TextModel::GetInstance()->SetRemoteMessage(std::move(callback));
751 }
752 
Create(const JSCallbackInfo & info)753 void JSText::Create(const JSCallbackInfo& info)
754 {
755     std::string data;
756     if (info.Length() <= 0) {
757         TextModel::GetInstance()->Create(data);
758         return;
759     }
760 
761     if (info[0]->IsObject() && JSRef<JSObject>::Cast(info[0])->Unwrap<JSSpanString>()) {
762         auto *spanString = JSRef<JSObject>::Cast(info[0])->Unwrap<JSSpanString>();
763         if (spanString == nullptr) {
764             return;
765         }
766         auto spanStringController = spanString->GetController();
767         if (spanStringController) {
768             TextModel::GetInstance()->Create(spanStringController);
769         } else {
770             TextModel::GetInstance()->Create(data);
771         }
772     } else {
773         ParseJsString(info[0], data);
774         TextModel::GetInstance()->Create(data);
775     }
776 
777     JSTextTheme::ApplyTheme();
778     if (info.Length() <= 1 || !info[1]->IsObject()) {
779         return;
780     }
781 
782     JSTextController* jsController = nullptr;
783     auto paramObject = JSRef<JSObject>::Cast(info[1]);
784     auto controllerObj = paramObject->GetProperty("controller");
785     if (!controllerObj->IsUndefined() && !controllerObj->IsNull() && controllerObj->IsObject()) {
786         jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextController>();
787     }
788 
789     RefPtr<TextControllerBase> controller = TextModel::GetInstance()->GetTextController();
790     if (jsController) {
791         jsController->SetController(controller);
792         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FIFTEEN)) {
793             auto styledString = jsController->GetStyledString();
794             if (styledString) {
795                 controller->SetStyledString(styledString, false);
796                 jsController->ClearStyledString();
797             }
798         }
799     }
800 }
801 
SetCopyOption(const JSCallbackInfo & info)802 void JSText::SetCopyOption(const JSCallbackInfo& info)
803 {
804     if (info.Length() == 0) {
805         return;
806     }
807     auto copyOptions = CopyOptions::None;
808     auto tmpInfo = info[0];
809     if (tmpInfo->IsNumber()) {
810         auto emunNumber = tmpInfo->ToNumber<int>();
811         copyOptions = static_cast<CopyOptions>(emunNumber);
812     }
813     TextModel::GetInstance()->SetCopyOption(copyOptions);
814 }
815 
SetOnCopy(const JSCallbackInfo & info)816 void JSText::SetOnCopy(const JSCallbackInfo& info)
817 {
818     JSRef<JSVal> args = info[0];
819     CHECK_NULL_VOID(args->IsFunction());
820     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(args));
821     TextModel::GetInstance()->SetOnCopy(std::move(callback));
822 }
823 
JsOnDragStart(const JSCallbackInfo & info)824 void JSText::JsOnDragStart(const JSCallbackInfo& info)
825 {
826     JSRef<JSVal> args = info[0];
827     CHECK_NULL_VOID(args->IsFunction());
828     RefPtr<JsDragFunction> jsOnDragStartFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
829     auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
830     auto onDragStart = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragStartFunc),
831                            targetNode = frameNode](
832                            const RefPtr<DragEvent>& info, const std::string& extraParams) -> NG::DragDropBaseInfo {
833         NG::DragDropBaseInfo itemInfo;
834         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, itemInfo);
835         PipelineContext::SetCallBackNode(targetNode);
836         auto ret = func->Execute(info, extraParams);
837         if (!ret->IsObject()) {
838             return itemInfo;
839         }
840         auto node = ParseDragNode(ret);
841         if (node) {
842             itemInfo.node = node;
843             return itemInfo;
844         }
845         auto builderObj = JSRef<JSObject>::Cast(ret);
846 #if defined(PIXEL_MAP_SUPPORTED)
847         auto pixmap = builderObj->GetProperty("pixelMap");
848         itemInfo.pixelMap = CreatePixelMapFromNapiValue(pixmap);
849 #endif
850         auto extraInfo = builderObj->GetProperty("extraInfo");
851         ParseJsString(extraInfo, itemInfo.extraInfo);
852         node = ParseDragNode(builderObj->GetProperty("builder"));
853         itemInfo.node = node;
854         return itemInfo;
855     };
856 
857     TextModel::GetInstance()->SetOnDragStart(std::move(onDragStart));
858 }
859 
JsOnDragEnter(const JSCallbackInfo & info)860 void JSText::JsOnDragEnter(const JSCallbackInfo& info)
861 {
862     JSRef<JSVal> args = info[0];
863     CHECK_NULL_VOID(args->IsFunction());
864     auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
865     RefPtr<JsDragFunction> jsOnDragEnterFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
866     auto onDragEnterId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragEnterFunc), node = frameNode](
867                              const RefPtr<DragEvent>& info, const std::string& extraParams) {
868         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
869         ACE_SCORING_EVENT("onDragEnter");
870         PipelineContext::SetCallBackNode(node);
871         func->Execute(info, extraParams);
872     };
873     TextModel::GetInstance()->SetOnDragEnter(std::move(onDragEnterId));
874 }
875 
JsOnDragMove(const JSCallbackInfo & info)876 void JSText::JsOnDragMove(const JSCallbackInfo& info)
877 {
878     JSRef<JSVal> args = info[0];
879     CHECK_NULL_VOID(args->IsFunction());
880     auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
881     RefPtr<JsDragFunction> jsOnDragMoveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
882     auto onDragMoveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragMoveFunc), node = frameNode](
883                             const RefPtr<DragEvent>& info, const std::string& extraParams) {
884         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
885         ACE_SCORING_EVENT("onDragMove");
886         PipelineContext::SetCallBackNode(node);
887         func->Execute(info, extraParams);
888     };
889     TextModel::GetInstance()->SetOnDragMove(std::move(onDragMoveId));
890 }
891 
JsOnDragLeave(const JSCallbackInfo & info)892 void JSText::JsOnDragLeave(const JSCallbackInfo& info)
893 {
894     JSRef<JSVal> args = info[0];
895     CHECK_NULL_VOID(args->IsFunction());
896     auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
897     RefPtr<JsDragFunction> jsOnDragLeaveFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
898     auto onDragLeaveId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDragLeaveFunc), node = frameNode](
899                              const RefPtr<DragEvent>& info, const std::string& extraParams) {
900         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
901         ACE_SCORING_EVENT("onDragLeave");
902         PipelineContext::SetCallBackNode(node);
903         func->Execute(info, extraParams);
904     };
905     TextModel::GetInstance()->SetOnDragLeave(std::move(onDragLeaveId));
906 }
907 
JsOnDrop(const JSCallbackInfo & info)908 void JSText::JsOnDrop(const JSCallbackInfo& info)
909 {
910     JSRef<JSVal> args = info[0];
911     CHECK_NULL_VOID(args->IsFunction());
912     RefPtr<JsDragFunction> jsOnDropFunc = AceType::MakeRefPtr<JsDragFunction>(JSRef<JSFunc>::Cast(args));
913     auto onDropId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDropFunc)](
914                         const RefPtr<DragEvent>& info, const std::string& extraParams) {
915         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
916         ACE_SCORING_EVENT("onDrop");
917         func->Execute(info, extraParams);
918     };
919     TextModel::GetInstance()->SetOnDrop(std::move(onDropId));
920 }
921 
JsFocusable(const JSCallbackInfo & info)922 void JSText::JsFocusable(const JSCallbackInfo& info)
923 {
924     auto tmpInfo = info[0];
925     if (!tmpInfo->IsBoolean()) {
926         return;
927     }
928     JSInteractableView::SetFocusable(tmpInfo->ToBoolean());
929     JSInteractableView::SetFocusNode(false);
930 }
931 
JsDraggable(const JSCallbackInfo & info)932 void JSText::JsDraggable(const JSCallbackInfo& info)
933 {
934     auto tmpInfo = info[0];
935     if (!tmpInfo->IsBoolean()) {
936         return;
937     }
938     ViewAbstractModel::GetInstance()->SetDraggable(tmpInfo->ToBoolean());
939 }
940 
JsEnableDataDetector(const JSCallbackInfo & info)941 void JSText::JsEnableDataDetector(const JSCallbackInfo& info)
942 {
943     if (info.Length() < 1) {
944         LOGI("The argv is wrong, it is supposed to have at least 1 argument");
945         return;
946     }
947     auto tmpInfo = info[0];
948     if (!tmpInfo->IsBoolean()) {
949         TextModel::GetInstance()->SetTextDetectEnable(false);
950         return;
951     }
952     auto enable = tmpInfo->ToBoolean();
953     TextModel::GetInstance()->SetTextDetectEnable(enable);
954 }
955 
JsDataDetectorConfig(const JSCallbackInfo & info)956 void JSText::JsDataDetectorConfig(const JSCallbackInfo& info)
957 {
958     if (info.Length() < 1) {
959         LOGI("The argv is wrong, it is supposed to have at least 1 argument");
960         return;
961     }
962     JSRef<JSVal> args = info[0];
963     if (!args->IsObject()) {
964         return;
965     }
966 
967     TextDetectConfig textDetectConfig;
968     if (!ParseDataDetectorConfig(info, textDetectConfig)) {
969         return;
970     }
971     TextModel::GetInstance()->SetTextDetectConfig(textDetectConfig);
972 }
973 
BindSelectionMenu(const JSCallbackInfo & info)974 void JSText::BindSelectionMenu(const JSCallbackInfo& info)
975 {
976     // TextSpanType
977     NG::TextSpanType textSpanType = NG::TextSpanType::TEXT;
978     bool isValidTextSpanType = true;
979     JSRef<JSVal> argsSpanType = info[0];
980     if (argsSpanType->IsNumber()) {
981         auto spanTypeId = argsSpanType->ToNumber<int32_t>();
982         isValidTextSpanType = NG::TextSpanTypeMapper::GetTextSpanTypeFromJsType(spanTypeId, textSpanType);
983     }
984 
985     // Builder
986     JSRef<JSVal> argsMenuObj = info[1];
987     if (!argsMenuObj->IsObject()) {
988         return;
989     }
990     JSRef<JSObject> menuObj = JSRef<JSObject>::Cast(argsMenuObj);
991     auto builder = menuObj->GetProperty("builder");
992     if (!builder->IsFunction()) {
993         return;
994     }
995     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
996     CHECK_NULL_VOID(builderFunc);
997 
998     // TextResponseType
999     int32_t resquiredParameterCount = 3;
1000     JSRef<JSVal> argsResponse = info[resquiredParameterCount - 1];
1001     NG::TextResponseType responseType = NG::TextResponseType::LONG_PRESS;
1002     if (argsResponse->IsNumber()) {
1003         auto response = argsResponse->ToNumber<int32_t>();
1004         responseType = static_cast<NG::TextResponseType>(response);
1005     }
1006 
1007     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1008     std::function<void()> buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc),
1009                                           node = frameNode]() {
1010         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1011         ACE_SCORING_EVENT("BindSelectionMenu");
1012         PipelineContext::SetCallBackNode(node);
1013         func->Execute();
1014     };
1015 
1016     // SelectionMenuOptions
1017     NG::SelectMenuParam menuParam;
1018     menuParam.isValid = isValidTextSpanType;
1019     if (info.Length() > resquiredParameterCount) {
1020         JSRef<JSVal> argsMenuOptions = info[resquiredParameterCount];
1021         if (argsMenuOptions->IsObject()) {
1022             ParseMenuParam(info, argsMenuOptions, menuParam);
1023         }
1024     }
1025 
1026     TextModel::GetInstance()->BindSelectionMenu(textSpanType, responseType, buildFunc, menuParam);
1027 }
1028 
SetOnTextSelectionChange(const JSCallbackInfo & info)1029 void JSText::SetOnTextSelectionChange(const JSCallbackInfo& info)
1030 {
1031     JSRef<JSVal> args = info[0];
1032     CHECK_NULL_VOID(args->IsFunction());
1033     JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(args));
1034     TextModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
1035 }
1036 
JsClip(const JSCallbackInfo & info)1037 void JSText::JsClip(const JSCallbackInfo& info)
1038 {
1039     JSViewAbstract::JsClip(info);
1040     JSRef<JSVal> args = info[0];
1041     if (args->IsBoolean()) {
1042         TextModel::GetInstance()->SetClipEdge(args->ToBoolean());
1043     }
1044 }
1045 
SetFontFeature(const JSCallbackInfo & info)1046 void JSText::SetFontFeature(const JSCallbackInfo& info)
1047 {
1048     if (info.Length() < 1) {
1049         return;
1050     }
1051 
1052     if (!info[0]->IsString() && !info[0]->IsObject()) {
1053         return;
1054     }
1055     std::string fontFeatureSettings = info[0]->ToString();
1056     TextModel::GetInstance()->SetFontFeature(ParseFontFeatureSettings(fontFeatureSettings));
1057 }
1058 
JsResponseRegion(const JSCallbackInfo & info)1059 void JSText::JsResponseRegion(const JSCallbackInfo& info)
1060 {
1061     JSViewAbstract::JsResponseRegion(info);
1062     TextModel::GetInstance()->SetResponseRegion(true);
1063 }
1064 
SetHalfLeading(const JSCallbackInfo & info)1065 void JSText::SetHalfLeading(const JSCallbackInfo& info)
1066 {
1067     if (info.Length() < 1) {
1068         return;
1069     }
1070     auto halfLeading = info[0];
1071     if (!halfLeading->IsBoolean()) {
1072         TextModel::GetInstance()->SetHalfLeading(false);
1073         return;
1074     }
1075     auto enable = halfLeading->ToBoolean();
1076     TextModel::GetInstance()->SetHalfLeading(enable);
1077 }
1078 
SetEnableHapticFeedback(const JSCallbackInfo & info)1079 void JSText::SetEnableHapticFeedback(const JSCallbackInfo& info)
1080 {
1081     bool state = true;
1082     if (info.Length() > 0 && info[0]->IsBoolean()) {
1083         state = info[0]->ToBoolean();
1084     }
1085     TextModel::GetInstance()->SetEnableHapticFeedback(state);
1086 }
1087 
JSBind(BindingTarget globalObj)1088 void JSText::JSBind(BindingTarget globalObj)
1089 {
1090     JSClass<JSText>::Declare("Text");
1091     MethodOptions opt = MethodOptions::NONE;
1092     JSClass<JSText>::StaticMethod("create", &JSText::Create, opt);
1093     JSClass<JSText>::StaticMethod("width", &JSText::SetWidth);
1094     JSClass<JSText>::StaticMethod("height", &JSText::SetHeight);
1095     JSClass<JSText>::StaticMethod("font", &JSText::SetFont, opt);
1096     JSClass<JSText>::StaticMethod("fontColor", &JSText::SetTextColor, opt);
1097     JSClass<JSText>::StaticMethod("textShadow", &JSText::SetTextShadow, opt);
1098     JSClass<JSText>::StaticMethod("fontSize", &JSText::SetFontSize, opt);
1099     JSClass<JSText>::StaticMethod("fontWeight", &JSText::SetFontWeight, opt);
1100     JSClass<JSText>::StaticMethod("minFontScale", &JSText::SetMinFontScale, opt);
1101     JSClass<JSText>::StaticMethod("maxFontScale", &JSText::SetMaxFontScale, opt);
1102     JSClass<JSText>::StaticMethod("wordBreak", &JSText::SetWordBreak, opt);
1103     JSClass<JSText>::StaticMethod("lineBreakStrategy", &JSText::SetLineBreakStrategy, opt);
1104     JSClass<JSText>::StaticMethod("selection", &JSText::SetTextSelection, opt);
1105     JSClass<JSText>::StaticMethod("ellipsisMode", &JSText::SetEllipsisMode, opt);
1106     JSClass<JSText>::StaticMethod("textSelectable", &JSText::SetTextSelectableMode, opt);
1107     JSClass<JSText>::StaticMethod("maxLines", &JSText::SetMaxLines, opt);
1108     JSClass<JSText>::StaticMethod("textIndent", &JSText::SetTextIndent);
1109     JSClass<JSText>::StaticMethod("textOverflow", &JSText::SetTextOverflow, opt);
1110     JSClass<JSText>::StaticMethod("fontStyle", &JSText::SetFontStyle, opt);
1111     JSClass<JSText>::StaticMethod("align", &JSText::SetAlign, opt);
1112     JSClass<JSText>::StaticMethod("textAlign", &JSText::SetTextAlign, opt);
1113     JSClass<JSText>::StaticMethod("lineHeight", &JSText::SetLineHeight, opt);
1114     JSClass<JSText>::StaticMethod("lineSpacing", &JSText::SetLineSpacing, opt);
1115     JSClass<JSText>::StaticMethod("fontFamily", &JSText::SetFontFamily, opt);
1116     JSClass<JSText>::StaticMethod("minFontSize", &JSText::SetMinFontSize, opt);
1117     JSClass<JSText>::StaticMethod("maxFontSize", &JSText::SetMaxFontSize, opt);
1118     JSClass<JSText>::StaticMethod("letterSpacing", &JSText::SetLetterSpacing, opt);
1119     JSClass<JSText>::StaticMethod("textCase", &JSText::SetTextCase, opt);
1120     JSClass<JSText>::StaticMethod("baselineOffset", &JSText::SetBaselineOffset, opt);
1121     JSClass<JSText>::StaticMethod("caretColor", &JSText::SetTextCaretColor);
1122     JSClass<JSText>::StaticMethod("selectedBackgroundColor", &JSText::SetSelectedBackgroundColor);
1123     JSClass<JSText>::StaticMethod("decoration", &JSText::SetDecoration);
1124     JSClass<JSText>::StaticMethod("heightAdaptivePolicy", &JSText::SetHeightAdaptivePolicy);
1125     JSClass<JSText>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
1126     JSClass<JSText>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
1127     JSClass<JSText>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
1128     JSClass<JSText>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
1129     JSClass<JSText>::StaticMethod("remoteMessage", &JSText::JsRemoteMessage);
1130     JSClass<JSText>::StaticMethod("copyOption", &JSText::SetCopyOption);
1131     JSClass<JSText>::StaticMethod("onClick", &JSText::JsOnClick);
1132     JSClass<JSText>::StaticMethod("onCopy", &JSText::SetOnCopy);
1133     JSClass<JSText>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
1134     JSClass<JSText>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
1135     JSClass<JSText>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
1136     JSClass<JSText>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
1137     JSClass<JSText>::StaticMethod("onDragStart", &JSText::JsOnDragStart);
1138     JSClass<JSText>::StaticMethod("onDragEnter", &JSText::JsOnDragEnter);
1139     JSClass<JSText>::StaticMethod("onDragMove", &JSText::JsOnDragMove);
1140     JSClass<JSText>::StaticMethod("onDragLeave", &JSText::JsOnDragLeave);
1141     JSClass<JSText>::StaticMethod("onDrop", &JSText::JsOnDrop);
1142     JSClass<JSText>::StaticMethod("focusable", &JSText::JsFocusable);
1143     JSClass<JSText>::StaticMethod("draggable", &JSText::JsDraggable);
1144     JSClass<JSText>::StaticMethod("enableDataDetector", &JSText::JsEnableDataDetector);
1145     JSClass<JSText>::StaticMethod("dataDetectorConfig", &JSText::JsDataDetectorConfig);
1146     JSClass<JSText>::StaticMethod("bindSelectionMenu", &JSText::BindSelectionMenu);
1147     JSClass<JSText>::StaticMethod("onTextSelectionChange", &JSText::SetOnTextSelectionChange);
1148     JSClass<JSText>::StaticMethod("clip", &JSText::JsClip);
1149     JSClass<JSText>::StaticMethod("foregroundColor", &JSText::SetForegroundColor);
1150     JSClass<JSText>::StaticMethod("fontFeature", &JSText::SetFontFeature);
1151     JSClass<JSText>::StaticMethod("editMenuOptions", &JSText::EditMenuOptions);
1152     JSClass<JSText>::StaticMethod("responseRegion", &JSText::JsResponseRegion);
1153     JSClass<JSText>::StaticMethod("halfLeading", &JSText::SetHalfLeading);
1154     JSClass<JSText>::StaticMethod("enableHapticFeedback", &JSText::SetEnableHapticFeedback);
1155     JSClass<JSText>::InheritAndBind<JSContainerBase>(globalObj);
1156 }
1157 
CloseSelectionMenu()1158 void JSTextController::CloseSelectionMenu()
1159 {
1160     auto controller = controllerWeak_.Upgrade();
1161     CHECK_NULL_VOID(controller);
1162     controller->CloseSelectionMenu();
1163 }
1164 
GetLayoutManager(const JSCallbackInfo & args)1165 void JSTextController::GetLayoutManager(const JSCallbackInfo& args)
1166 {
1167     JSRef<JSObject> obj = JSClass<JSLayoutManager>::NewInstance();
1168     auto jsLayoutManager = Referenced::Claim(obj->Unwrap<JSLayoutManager>());
1169     CHECK_NULL_VOID(jsLayoutManager);
1170     jsLayoutManager->IncRefCount();
1171     auto controller = controllerWeak_.Upgrade();
1172     CHECK_NULL_VOID(controller);
1173     auto layoutInfoInterface = controller->GetLayoutInfoInterface();
1174     jsLayoutManager->SetLayoutInfoInterface(layoutInfoInterface);
1175     args.SetReturnValue(obj);
1176 }
1177 
SetStyledString(const JSCallbackInfo & info)1178 void JSTextController::SetStyledString(const JSCallbackInfo& info)
1179 {
1180     if (info.Length() != 1 || !info[0]->IsObject()) {
1181         JSException::Throw(ERROR_CODE_PARAM_INVALID, "%s", "Input parameter check failed.");
1182         return;
1183     }
1184     auto* spanString = JSRef<JSObject>::Cast(info[0])->Unwrap<JSSpanString>();
1185     if (!spanString) {
1186         JSException::Throw(ERROR_CODE_PARAM_INVALID, "%s", "Input parameter check failed.");
1187         return;
1188     }
1189     auto spanStringController = spanString->GetController();
1190     CHECK_NULL_VOID(spanStringController);
1191     auto controller = controllerWeak_.Upgrade();
1192     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FIFTEEN) && !controller) {
1193         styledString_ = spanStringController;
1194     }
1195     CHECK_NULL_VOID(controller);
1196     controller->SetStyledString(spanStringController, true);
1197     auto thisObj = info.This();
1198     thisObj->SetPropertyObject("STYLED_STRING_IN_CONTROLLER", info[0]);
1199 }
1200 
JSBind(BindingTarget globalObj)1201 void JSTextController::JSBind(BindingTarget globalObj)
1202 {
1203     JSClass<JSTextController>::Declare("TextController");
1204     JSClass<JSTextController>::Method("closeSelectionMenu", &JSTextController::CloseSelectionMenu);
1205     JSClass<JSTextController>::CustomMethod("setStyledString", &JSTextController::SetStyledString);
1206     JSClass<JSTextController>::CustomMethod("getLayoutManager", &JSTextController::GetLayoutManager);
1207     JSClass<JSTextController>::Bind(globalObj, JSTextController::Constructor, JSTextController::Destructor);
1208 }
1209 
ParseMenuParam(const JSCallbackInfo & info,const JSRef<JSObject> & menuOptions,NG::SelectMenuParam & menuParam)1210 void JSText::ParseMenuParam(
1211     const JSCallbackInfo& info, const JSRef<JSObject>& menuOptions, NG::SelectMenuParam& menuParam)
1212 {
1213     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1214     auto onAppearValue = menuOptions->GetProperty("onAppear");
1215     if (onAppearValue->IsFunction()) {
1216         RefPtr<JsFunction> jsOnAppearFunc =
1217             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAppearValue));
1218         auto onAppear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAppearFunc), node = frameNode](
1219                             int32_t start, int32_t end) {
1220             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1221             ACE_SCORING_EVENT("onAppear");
1222 
1223             JSRef<JSVal> params[2];
1224             params[0] = JSRef<JSVal>::Make(ToJSValue(start));
1225             params[1] = JSRef<JSVal>::Make(ToJSValue(end));
1226             PipelineContext::SetCallBackNode(node);
1227             func->ExecuteJS(2, params);
1228         };
1229         menuParam.onAppear = std::move(onAppear);
1230     }
1231 
1232     auto onDisappearValue = menuOptions->GetProperty("onDisappear");
1233     if (onDisappearValue->IsFunction()) {
1234         RefPtr<JsFunction> jsOnDisAppearFunc =
1235             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDisappearValue));
1236         auto onDisappear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDisAppearFunc),
1237                                node = frameNode]() {
1238             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1239             ACE_SCORING_EVENT("onDisappear");
1240             PipelineContext::SetCallBackNode(node);
1241             func->Execute();
1242         };
1243         menuParam.onDisappear = std::move(onDisappear);
1244     }
1245     menuParam.onMenuShow = ParseMenuCallback(frameNode, menuOptions, info, "onMenuShow");
1246     menuParam.onMenuHide = ParseMenuCallback(frameNode, menuOptions, info, "onMenuHide");
1247 }
1248 
ParseMenuCallback(const WeakPtr<NG::FrameNode> & frameNode,const JSRef<JSObject> & menuOptions,const JSCallbackInfo & info,const std::string & name)1249 std::function<void(int32_t, int32_t)> JSText::ParseMenuCallback(const WeakPtr<NG::FrameNode>& frameNode,
1250     const JSRef<JSObject>& menuOptions, const JSCallbackInfo& info, const std::string& name)
1251 {
1252     auto onMenuCallbackValue = menuOptions->GetProperty(name.c_str());
1253     if (onMenuCallbackValue->IsFunction()) {
1254         RefPtr<JsFunction> jsOnMenuCallbackFunc =
1255             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onMenuCallbackValue));
1256         auto onMenuCallback = [execCtx = info.GetExecutionContext(), func = std::move(jsOnMenuCallbackFunc),
1257                                   node = frameNode, eventName = name](int32_t start, int32_t end) {
1258             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1259             ACE_SCORING_EVENT(eventName);
1260 
1261             JSRef<JSVal> params[2];
1262             params[0] = JSRef<JSVal>::Make(ToJSValue(start));
1263             params[1] = JSRef<JSVal>::Make(ToJSValue(end));
1264             PipelineContext::SetCallBackNode(node);
1265             func->ExecuteJS(2, params);
1266         };
1267         return onMenuCallback;
1268     }
1269     return nullptr;
1270 }
1271 
EditMenuOptions(const JSCallbackInfo & info)1272 void JSText::EditMenuOptions(const JSCallbackInfo& info)
1273 {
1274     NG::OnCreateMenuCallback onCreateMenuCallback;
1275     NG::OnMenuItemClickCallback onMenuItemClick;
1276     JSViewAbstract::ParseEditMenuOptions(info, onCreateMenuCallback, onMenuItemClick);
1277     TextModel::GetInstance()->SetSelectionMenuOptions(std::move(onCreateMenuCallback), std::move(onMenuItemClick));
1278 }
1279 } // namespace OHOS::Ace::Framework
1280