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 #include "frameworks/bridge/declarative_frontend/jsview/js_symbol.h"
16
17 #include "core/components_ng/pattern/symbol/constants.h"
18 #include "frameworks/bridge/declarative_frontend/engine/bindings.h"
19 #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h"
20 #include "frameworks/bridge/declarative_frontend/jsview/js_interactable_view.h"
21 #include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h"
22 #include "frameworks/core/components_ng/pattern/symbol/symbol_model.h"
23 #include "frameworks/core/components_ng/pattern/symbol/symbol_model_ng.h"
24
25 namespace OHOS::Ace {
26 constexpr int32_t SYSTEM_SYMBOL_BOUNDARY = 0XFFFFF;
27 const std::string DEFAULT_SYMBOL_FONTFAMILY = "HM Symbol";
28
29 std::unique_ptr<SymbolModel> SymbolModel::instance_ = nullptr;
30 std::mutex SymbolModel::mutex_;
31
GetInstance()32 SymbolModel* SymbolModel::GetInstance()
33 {
34 static NG::SymbolModelNG instance;
35 return &instance;
36 }
37
38 } // namespace OHOS::Ace
39
40 namespace OHOS::Ace::Framework {
41
42 const std::map<std::string, Ace::SymbolEffectType> SYMBOL_EFFECT_TYPE_MAP = {
43 { "ScaleSymbolEffect", SymbolEffectType::SCALE },
44 { "HierarchicalSymbolEffect", SymbolEffectType::HIERARCHICAL },
45 { "AppearSymbolEffect", SymbolEffectType::APPEAR },
46 { "DisappearSymbolEffect", SymbolEffectType::DISAPPEAR },
47 { "BounceSymbolEffect", SymbolEffectType::BOUNCE },
48 { "ReplaceSymbolEffect", SymbolEffectType::REPLACE },
49 { "PulseSymbolEffect", SymbolEffectType::PULSE },
50 };
51
JSBind(BindingTarget globalObj)52 void JSSymbol::JSBind(BindingTarget globalObj)
53 {
54 JSClass<JSSymbol>::Declare("SymbolGlyph");
55
56 MethodOptions opt = MethodOptions::NONE;
57 JSClass<JSSymbol>::StaticMethod("create", &JSSymbol::Create, opt);
58 JSClass<JSSymbol>::StaticMethod("fontWeight", &JSSymbol::SetFontWeight, opt);
59 JSClass<JSSymbol>::StaticMethod("fontSize", &JSSymbol::SetFontSize, opt);
60 JSClass<JSSymbol>::StaticMethod("renderingStrategy", &JSSymbol::SetSymbolRenderingStrategy, opt);
61 JSClass<JSSymbol>::StaticMethod("fontColor", &JSSymbol::SetFontColor, opt);
62 JSClass<JSSymbol>::StaticMethod("effectStrategy", &JSSymbol::SetSymbolEffect, opt);
63 JSClass<JSSymbol>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
64 JSClass<JSSymbol>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
65 JSClass<JSSymbol>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
66 JSClass<JSSymbol>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
67 JSClass<JSSymbol>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
68 JSClass<JSSymbol>::StaticMethod("clip", &JSSymbol::JsClip);
69 JSClass<JSSymbol>::StaticMethod("symbolEffect", &JSSymbol::SetSymbolEffectOptions, opt);
70 JSClass<JSSymbol>::StaticMethod("minFontScale", &JSSymbol::SetMinFontScale);
71 JSClass<JSSymbol>::StaticMethod("maxFontScale", &JSSymbol::SetMaxFontScale);
72 JSClass<JSSymbol>::InheritAndBind<JSViewAbstract>(globalObj);
73 }
74
Create(const JSCallbackInfo & info)75 void JSSymbol::Create(const JSCallbackInfo& info)
76 {
77 if (info[0]->IsUndefined()) {
78 SymbolModel::GetInstance()->Create(0);
79 return;
80 }
81 uint32_t symbolId;
82 RefPtr<ResourceObject> resourceObject;
83 ParseJsSymbolId(info[0], symbolId, resourceObject);
84 SymbolModel::GetInstance()->Create(symbolId);
85 std::vector<std::string> familyNames;
86 if (symbolId > SYSTEM_SYMBOL_BOUNDARY) {
87 ParseJsSymbolCustomFamilyNames(familyNames, info[0]);
88 SymbolModel::GetInstance()->SetFontFamilies(familyNames);
89 SymbolModel::GetInstance()->SetSymbolType(SymbolType::CUSTOM);
90 } else {
91 familyNames.push_back(DEFAULT_SYMBOL_FONTFAMILY);
92 SymbolModel::GetInstance()->SetFontFamilies(familyNames);
93 SymbolModel::GetInstance()->SetSymbolType(SymbolType::SYSTEM);
94 }
95 }
96
SetFontSize(const JSCallbackInfo & info)97 void JSSymbol::SetFontSize(const JSCallbackInfo& info)
98 {
99 if (info.Length() < 1) {
100 return;
101 }
102 auto theme = GetTheme<TextTheme>();
103 CHECK_NULL_VOID(theme);
104 CalcDimension fontSize = theme->GetTextStyle().GetFontSize();
105 if (!ParseJsDimensionFpNG(info[0], fontSize, false)) {
106 fontSize = theme->GetTextStyle().GetFontSize();
107 SymbolModel::GetInstance()->SetFontSize(fontSize);
108 return;
109 }
110 if (fontSize.IsNegative()) {
111 fontSize = theme->GetTextStyle().GetFontSize();
112 }
113
114 SymbolModel::GetInstance()->SetFontSize(fontSize);
115 }
116
SetFontWeight(const std::string & value)117 void JSSymbol::SetFontWeight(const std::string& value)
118 {
119 SymbolModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(value));
120 }
121
SetSymbolRenderingStrategy(const JSCallbackInfo & info)122 void JSSymbol::SetSymbolRenderingStrategy(const JSCallbackInfo& info)
123 {
124 uint32_t strategy = 0;
125 ParseJsInteger(info[0], strategy);
126 SymbolModel::GetInstance()->SetSymbolRenderingStrategy(strategy);
127 }
128
SetFontColor(const JSCallbackInfo & info)129 void JSSymbol::SetFontColor(const JSCallbackInfo& info)
130 {
131 std::vector<Color> symbolColor;
132 if (!ParseJsSymbolColor(info[0], symbolColor)) {
133 return;
134 }
135 SymbolModel::GetInstance()->SetFontColor(symbolColor);
136 }
137
SetSymbolEffect(const JSCallbackInfo & info)138 void JSSymbol::SetSymbolEffect(const JSCallbackInfo& info)
139 {
140 uint32_t strategy = 0;
141 ParseJsInteger(info[0], strategy);
142 SymbolModel::GetInstance()->SetSymbolEffect(strategy);
143 }
144
JsClip(const JSCallbackInfo & info)145 void JSSymbol::JsClip(const JSCallbackInfo& info)
146 {
147 JSViewAbstract::JsClip(info);
148 if (info[0]->IsBoolean()) {
149 SymbolModel::GetInstance()->SetClipEdge();
150 }
151 }
152
SetSymbolEffectOptions(const JSCallbackInfo & info)153 void JSSymbol::SetSymbolEffectOptions(const JSCallbackInfo& info)
154 {
155 if (info.Length() < 1 || !info[0]->IsObject()) {
156 return;
157 }
158
159 auto symbolEffectObj = JSRef<JSObject>::Cast(info[0]);
160 NG::SymbolEffectOptions symbolEffectOptions;
161 parseSymbolEffect(symbolEffectObj, symbolEffectOptions);
162
163 if (info.Length() > 1 && !info[1]->IsUndefined()) {
164 parseSymbolSwitch(info[1], symbolEffectOptions);
165 }
166
167 SymbolModel::GetInstance()->SetSymbolEffectOptions(symbolEffectOptions);
168 }
169
SetMinFontScale(const JSCallbackInfo & info)170 void JSSymbol::SetMinFontScale(const JSCallbackInfo& info)
171 {
172 double minFontScale;
173 if (info.Length() < 1 || !ParseJsDouble(info[0], minFontScale)) {
174 return;
175 }
176 if (LessOrEqual(minFontScale, 0.0f)) {
177 SymbolModel::GetInstance()->SetMinFontScale(0.0f);
178 return;
179 }
180 if (GreatOrEqual(minFontScale, 1.0f)) {
181 SymbolModel::GetInstance()->SetMinFontScale(1.0f);
182 return;
183 }
184 SymbolModel::GetInstance()->SetMinFontScale(static_cast<float>(minFontScale));
185 }
186
SetMaxFontScale(const JSCallbackInfo & info)187 void JSSymbol::SetMaxFontScale(const JSCallbackInfo& info)
188 {
189 double maxFontScale;
190 if (info.Length() < 1 || !ParseJsDouble(info[0], maxFontScale)) {
191 return;
192 }
193 if (LessOrEqual(maxFontScale, 1.0f)) {
194 SymbolModel::GetInstance()->SetMaxFontScale(1.0f);
195 return;
196 }
197 SymbolModel::GetInstance()->SetMaxFontScale(static_cast<float>(maxFontScale));
198 }
199
parseSymbolEffect(const JSRef<JSObject> symbolEffectObj,NG::SymbolEffectOptions & symbolEffectOptions)200 void JSSymbol::parseSymbolEffect(const JSRef<JSObject> symbolEffectObj, NG::SymbolEffectOptions& symbolEffectOptions)
201 {
202 auto typeParam = symbolEffectObj->GetProperty("type");
203 if (typeParam->IsString()) {
204 auto type = typeParam->ToString();
205 auto iter = SYMBOL_EFFECT_TYPE_MAP.find(type);
206 if (iter != SYMBOL_EFFECT_TYPE_MAP.end()) {
207 symbolEffectOptions.SetEffectType(iter->second);
208 }
209 }
210
211 auto scopeTypeProperty = symbolEffectObj->GetProperty("scope");
212 if (scopeTypeProperty->IsNumber()) {
213 auto scopeTypeNum = scopeTypeProperty->ToNumber<uint32_t>();
214 if (scopeTypeNum >= static_cast<uint32_t>(ScopeType::LAYER) &&
215 scopeTypeNum <= static_cast<uint32_t>(ScopeType::WHOLE)) {
216 symbolEffectOptions.SetScopeType(static_cast<ScopeType>(scopeTypeNum));
217 }
218 }
219
220 auto commonSubTypeProperty = symbolEffectObj->GetProperty("direction");
221 if (commonSubTypeProperty->IsNumber()) {
222 auto commonSubTypeNum = commonSubTypeProperty->ToNumber<uint32_t>();
223 if (commonSubTypeNum >= static_cast<uint32_t>(CommonSubType::DOWN) &&
224 commonSubTypeNum <= static_cast<uint32_t>(CommonSubType::UP)) {
225 symbolEffectOptions.SetCommonSubType(static_cast<CommonSubType>(commonSubTypeNum));
226 }
227 }
228
229 auto fillStyleProperty = symbolEffectObj->GetProperty("fillStyle");
230 if (fillStyleProperty->IsNumber()) {
231 auto fillStyleNum = fillStyleProperty->ToNumber<uint32_t>();
232 if (fillStyleNum >= static_cast<uint32_t>(FillStyle::CUMULATIVE) &&
233 fillStyleNum <= static_cast<uint32_t>(FillStyle::ITERATIVE)) {
234 symbolEffectOptions.SetFillStyle(static_cast<FillStyle>(fillStyleNum));
235 }
236 }
237 }
238
parseSymbolSwitch(const JSRef<JSVal> jsVal,NG::SymbolEffectOptions & symbolEffectOptions)239 void JSSymbol::parseSymbolSwitch(const JSRef<JSVal> jsVal, NG::SymbolEffectOptions& symbolEffectOptions)
240 {
241 if (jsVal->IsBoolean()) {
242 symbolEffectOptions.SetIsActive(jsVal->ToBoolean());
243 }
244
245 if (jsVal->IsNumber()) {
246 int32_t triggerValue = -1;
247 ParseJsInteger(jsVal, triggerValue);
248 symbolEffectOptions.SetTriggerNum(triggerValue);
249 }
250 }
251 } // namespace OHOS::Ace::Framework