1 /*
2 * Copyright (c) 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_symbol_span.h"
17
18 #include <optional>
19 #include <sstream>
20 #include <string>
21 #include <vector>
22
23 #include "base/geometry/dimension.h"
24 #include "base/utils/utils.h"
25 #include "bridge/common/utils/utils.h"
26 #include "bridge/declarative_frontend/jsview/js_utils.h"
27 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
28 #include "bridge/declarative_frontend/jsview/models/span_model_impl.h"
29 #include "bridge/declarative_frontend/jsview/models/text_model_impl.h"
30 #include "bridge/declarative_frontend/jsview/js_text.h"
31 #include "core/common/container.h"
32 #include "core/components_ng/pattern/text/symbol_span_model.h"
33 #include "core/components_ng/pattern/text/symbol_span_model_ng.h"
34 #include "core/components_ng/pattern/text/span_node.h"
35 #include "core/components_ng/pattern/text/text_model.h"
36
37 namespace OHOS::Ace {
38 constexpr int32_t SYSTEM_SYMBOL_BOUNDARY = 0XFFFFF;
39 const std::string DEFAULT_SYMBOL_FONTFAMILY = "HM Symbol";
40
41 std::unique_ptr<SymbolSpanModel> SymbolSpanModel::instance_ = nullptr;
42 std::mutex SymbolSpanModel::mutex_;
43
GetInstance()44 SymbolSpanModel* SymbolSpanModel::GetInstance()
45 {
46 static NG::SymbolSpanModelNG instance;
47 return &instance;
48 }
49
50 } // namespace OHOS::Ace
51
52 namespace OHOS::Ace::Framework {
53
SetFontSize(const JSCallbackInfo & info)54 void JSSymbolSpan::SetFontSize(const JSCallbackInfo& info)
55 {
56 if (info.Length() < 1) {
57 return;
58 }
59 auto theme = GetTheme<TextTheme>();
60 CHECK_NULL_VOID(theme);
61 CalcDimension fontSize = theme->GetTextStyle().GetFontSize();
62
63 RefPtr<ResourceObject> resObj;
64 UnregisterSpanResource("fontSize");
65 if (!ParseJsDimensionFpNG(info[0], fontSize, resObj, false)) {
66 fontSize = theme->GetTextStyle().GetFontSize();
67 SymbolSpanModel::GetInstance()->SetFontSize(fontSize);
68 return;
69 }
70 if (SystemProperties::ConfigChangePerform() && resObj) {
71 RegisterSpanResource<CalcDimension>("fontSize", resObj, fontSize);
72 }
73 if (fontSize.IsNegative()) {
74 fontSize = theme->GetTextStyle().GetFontSize();
75 }
76
77 SymbolSpanModel::GetInstance()->SetFontSize(fontSize);
78 }
79
SetFontWeight(const std::string & value)80 void JSSymbolSpan::SetFontWeight(const std::string& value)
81 {
82 SymbolSpanModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(value));
83 }
84
SetFontColor(const JSCallbackInfo & info)85 void JSSymbolSpan::SetFontColor(const JSCallbackInfo& info)
86 {
87 std::vector<Color> symbolColor;
88 if (SystemProperties::ConfigChangePerform()) {
89 UnregisterSpanResource("symbolColor");
90 std::vector<std::pair<int32_t, RefPtr<ResourceObject>>> resObjArr;
91 bool ret = ParseJsSymbolColor(info[0], symbolColor, true, resObjArr);
92 if (!resObjArr.empty()) {
93 auto spanNode = AceType::DynamicCast<NG::SpanNode>(
94 NG::ViewStackProcessor::GetInstance()->GetMainElementNode());
95 CHECK_NULL_VOID(spanNode);
96 spanNode->RegisterSymbolFontColorResource("symbolColor",
97 symbolColor, resObjArr);
98 }
99 if (ret) {
100 SymbolSpanModel::GetInstance()->SetFontColor(symbolColor);
101 }
102 return;
103 }
104 if (!ParseJsSymbolColor(info[0], symbolColor)) {
105 return;
106 }
107 SymbolSpanModel::GetInstance()->SetFontColor(symbolColor);
108 }
109
SetSymbolRenderingStrategy(const JSCallbackInfo & info)110 void JSSymbolSpan::SetSymbolRenderingStrategy(const JSCallbackInfo& info)
111 {
112 uint32_t strategy = 0;
113 ParseJsInteger(info[0], strategy);
114 SymbolSpanModel::GetInstance()->SetSymbolRenderingStrategy(strategy);
115 }
116
SetSymbolEffect(const JSCallbackInfo & info)117 void JSSymbolSpan::SetSymbolEffect(const JSCallbackInfo& info)
118 {
119 uint32_t strategy = 0;
120 ParseJsInteger(info[0], strategy);
121 SymbolSpanModel::GetInstance()->SetSymbolEffect(strategy);
122 }
123
Create(const JSCallbackInfo & info)124 void JSSymbolSpan::Create(const JSCallbackInfo& info)
125 {
126 uint32_t symbolId = 0;
127 RefPtr<ResourceObject> resourceObject;
128 if (info.Length() > 0) {
129 ParseJsSymbolId(info[0], symbolId, resourceObject);
130 }
131
132 SymbolSpanModel::GetInstance()->Create(symbolId);
133 std::vector<std::string> familyNames;
134 if (symbolId > SYSTEM_SYMBOL_BOUNDARY) {
135 ParseJsSymbolCustomFamilyNames(familyNames, info[0]);
136 SymbolSpanModel::GetInstance()->SetFontFamilies(familyNames);
137 SymbolSpanModel::GetInstance()->SetSymbolType(SymbolType::CUSTOM);
138 } else {
139 familyNames.push_back(DEFAULT_SYMBOL_FONTFAMILY);
140 SymbolSpanModel::GetInstance()->SetFontFamilies(familyNames);
141 SymbolSpanModel::GetInstance()->SetSymbolType(SymbolType::SYSTEM);
142 }
143 }
144
JSBind(BindingTarget globalObj)145 void JSSymbolSpan::JSBind(BindingTarget globalObj)
146 {
147 JSClass<JSSymbolSpan>::Declare("SymbolSpan");
148 MethodOptions opt = MethodOptions::NONE;
149 JSClass<JSSymbolSpan>::StaticMethod("create", &JSSymbolSpan::Create, opt);
150 JSClass<JSSymbolSpan>::StaticMethod("fontSize", &JSSymbolSpan::SetFontSize, opt);
151 JSClass<JSSymbolSpan>::StaticMethod("fontWeight", &JSSymbolSpan::SetFontWeight, opt);
152 JSClass<JSSymbolSpan>::StaticMethod("fontColor", &JSSymbolSpan::SetFontColor, opt);
153 JSClass<JSSymbolSpan>::StaticMethod("renderingStrategy", &JSSymbolSpan::SetSymbolRenderingStrategy, opt);
154 JSClass<JSSymbolSpan>::StaticMethod("effectStrategy", &JSSymbolSpan::SetSymbolEffect, opt);
155 JSClass<JSSymbolSpan>::InheritAndBind<JSContainerBase>(globalObj);
156 }
157
158 template<typename T>
RegisterSpanResource(const std::string & key,const RefPtr<ResourceObject> & resObj,T value)159 void JSSymbolSpan::RegisterSpanResource(const std::string& key, const RefPtr<ResourceObject>& resObj, T value)
160 {
161 auto uiNode = NG::ViewStackProcessor::GetInstance()->GetMainElementNode();
162 CHECK_NULL_VOID(uiNode);
163 auto spanNode = AceType::DynamicCast<NG::SpanNode>(uiNode);
164 if (spanNode) {
165 spanNode->RegisterResource<T>(key, resObj, value);
166 }
167 }
168
UnregisterSpanResource(const std::string & key)169 void JSSymbolSpan::UnregisterSpanResource(const std::string& key)
170 {
171 auto uiNode = NG::ViewStackProcessor::GetInstance()->GetMainElementNode();
172 CHECK_NULL_VOID(uiNode);
173 auto spanNode = AceType::DynamicCast<NG::SpanNode>(uiNode);
174 if (spanNode) {
175 spanNode->UnregisterResource(key);
176 }
177 }
178 } // namespace OHOS::Ace::Framework
179