1 /*
2 * Copyright (c) 2022 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 "base/utils/utf_helper.h"
17 #include "core/components_ng/pattern/text/text_layout_property.h"
18
19 namespace OHOS::Ace::NG {
20 namespace {
21 constexpr float MINFONTSCALE = 0.85f;
22 constexpr float MAXFONTSCALE = 3.20f;
23 constexpr Dimension DEFAULT_MARQUEE_STEP_VP = 4.0_vp;
24 static const std::array<std::string, 6> TEXT_BASE_LINE_TO_STRING = {
25 "textBaseline.ALPHABETIC",
26 "textBaseline.IDEOGRAPHIC",
27 "textBaseline.TOP",
28 "textBaseline.BOTTOM",
29 "textBaseline.MIDDLE",
30 "textBaseline.HANGING",
31 };
32
CovertShadowToJson(const Shadow & shadow)33 inline std::unique_ptr<JsonValue> CovertShadowToJson(const Shadow& shadow)
34 {
35 auto jsonShadow = JsonUtil::Create(true);
36 jsonShadow->Put("radius", std::to_string(shadow.GetBlurRadius()).c_str());
37 jsonShadow->Put("color", shadow.GetColor().ColorToString().c_str());
38 jsonShadow->Put("offsetX", std::to_string(shadow.GetOffset().GetX()).c_str());
39 jsonShadow->Put("offsetY", std::to_string(shadow.GetOffset().GetY()).c_str());
40 jsonShadow->Put("type", std::to_string(static_cast<int32_t>(shadow.GetShadowType())).c_str());
41 return jsonShadow;
42 }
43
CovertShadowsToJson(const std::vector<Shadow> & shadows)44 std::unique_ptr<JsonValue> CovertShadowsToJson(const std::vector<Shadow>& shadows)
45 {
46 auto jsonShadows = JsonUtil::CreateArray(true);
47 for (const auto& shadow : shadows) {
48 jsonShadows->Put(CovertShadowToJson(shadow));
49 }
50 return jsonShadows;
51 }
52 } // namespace
53
GetCopyOptionString() const54 std::string TextLayoutProperty::GetCopyOptionString() const
55 {
56 std::string copyOptionString = "CopyOptions.None";
57 switch (GetCopyOptionValue(CopyOptions::None)) {
58 case CopyOptions::InApp:
59 copyOptionString = "CopyOptions.InApp";
60 break;
61 case CopyOptions::Local:
62 copyOptionString = "CopyOptions.Local";
63 break;
64 case CopyOptions::Distributed:
65 copyOptionString = "CopyOptions.Distributed";
66 break;
67 case CopyOptions::None:
68 default:
69 break;
70 }
71 return copyOptionString;
72 }
73
GetTextMarqueeOptionsString() const74 std::string TextLayoutProperty::GetTextMarqueeOptionsString() const
75 {
76 auto jsonValue = JsonUtil::Create(true);
77
78 jsonValue->Put("start", GetTextMarqueeStart().value_or(true));
79 jsonValue->Put("step",
80 StringUtils::DoubleToString(GetTextMarqueeStep().value_or(DEFAULT_MARQUEE_STEP_VP.ConvertToPx())).c_str());
81 jsonValue->Put("loop", std::to_string(GetTextMarqueeLoop().value_or(-1)).c_str());
82 jsonValue->Put(
83 "direction", GetTextMarqueeDirection().value_or(MarqueeDirection::DEFAULT) == MarqueeDirection::DEFAULT
84 ? "MarqueeDirection.DEFAULT"
85 : "MarqueeDirection.DEFAULT_REVERSE");
86 jsonValue->Put("delay", std::to_string(GetTextMarqueeDelay().value_or(0)).c_str());
87 jsonValue->Put("fadeout", GetTextMarqueeFadeout().value_or(false));
88 jsonValue->Put(
89 "startPolicy", GetTextMarqueeStartPolicy().value_or(MarqueeStartPolicy::DEFAULT) == MarqueeStartPolicy::DEFAULT
90 ? "MarqueeStartPolicy.DEFAULT"
91 : "MarqueeStartPolicy.ON_FOCUS");
92
93 return jsonValue->ToString();
94 }
95
UpdateMarqueeOptionsFromJson(const std::unique_ptr<JsonValue> & json)96 void TextLayoutProperty::UpdateMarqueeOptionsFromJson(const std::unique_ptr<JsonValue>& json)
97 {
98 UpdateTextMarqueeStart(json->GetBool("start"));
99 UpdateTextMarqueeStep(json->GetDouble("step"));
100 UpdateTextMarqueeLoop(json->GetInt("loop"));
101 UpdateTextMarqueeDirection(V2::ConvertWrapStringToMarqueeDirection(json->GetString("direction")));
102 UpdateTextMarqueeDelay(json->GetInt("delay"));
103 UpdateTextMarqueeFadeout(json->GetBool("fadeout"));
104 UpdateTextMarqueeStartPolicy(V2::ConvertWrapStringToMarqueeStartPolicy(json->GetString("startPolicy")));
105 }
106
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const107 void TextLayoutProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
108 {
109 LayoutProperty::ToJsonValue(json, filter);
110 /* no fixed attr below, just return */
111 if (filter.IsFastFilter()) {
112 return;
113 }
114 auto host = GetHost();
115 CHECK_NULL_VOID(host);
116 auto themeScopeId = host->GetThemeScopeId();
117 auto context = host->GetContext();
118 CHECK_NULL_VOID(context);
119 auto theme = context->GetTheme<TextTheme>(themeScopeId);
120 auto defaultColor = theme ? theme->GetTextStyle().GetTextColor() : Color::BLACK;
121 /* distinguish SymbolGlyph font color list and Text font color in "fontColor" */
122 if (host->GetTag() == V2::SYMBOL_ETS_TAG) {
123 const std::optional<std::vector<Color>>& colorListOptional = GetSymbolColorList();
124 if (colorListOptional.has_value()) {
125 json->PutExtAttr("fontColor", StringUtils::SymbolColorListToString(colorListOptional.value())
126 .c_str(), filter);
127 } else {
128 json->PutExtAttr("fontColor", StringUtils::SymbolColorListToString(std::vector<Color>()).c_str(), filter);
129 }
130 } else {
131 json->PutExtAttr("fontColor", GetTextColor().value_or(defaultColor).ColorToString().c_str(), filter);
132 }
133 json->PutExtAttr("fontStyle", GetFontStyleInJson(GetItalicFontStyle()).c_str(), filter);
134 json->PutExtAttr("fontWeight", GetFontWeightInJson(GetFontWeight()).c_str(), filter);
135 json->PutExtAttr("fontFamily", GetFontFamilyInJson(GetFontFamily()).c_str(), filter);
136 json->PutExtAttr("renderingStrategy",
137 GetSymbolRenderingStrategyInJson(GetSymbolRenderingStrategy()).c_str(), filter);
138 json->PutExtAttr("effectStrategy", GetSymbolEffectStrategyInJson(GetSymbolEffectStrategy()).c_str(), filter);
139 json->Put("symbolEffect", GetSymbolEffectOptionsInJson(
140 GetSymbolEffectOptions().value_or(SymbolEffectOptions())).c_str());
141 json->PutExtAttr("symbolShadow", GetSymbolShadowInJson(GetSymbolShadow()), filter);
142
143 auto jsonDecoration = JsonUtil::Create(true);
144 std::string type = V2::ConvertWrapTextDecorationToStirng(GetTextDecorationFirst());
145 jsonDecoration->Put("type", type.c_str());
146 jsonDecoration->Put("color", GetTextDecorationColor().value_or(Color::BLACK).ColorToString().c_str());
147 std::string style =
148 V2::ConvertWrapTextDecorationStyleToString(GetTextDecorationStyle().value_or(TextDecorationStyle::SOLID));
149 jsonDecoration->Put("style", style.c_str());
150 json->PutExtAttr("decoration", jsonDecoration->ToString().c_str(), filter);
151
152 json->PutExtAttr("textCase",
153 V2::ConvertWrapTextCaseToStirng(GetTextCase().value_or(TextCase::NORMAL)).c_str(), filter);
154 json->PutExtAttr("minFontSize", GetAdaptMinFontSize().value_or(Dimension()).ToString().c_str(), filter);
155 json->PutExtAttr("maxFontSize", GetAdaptMaxFontSize().value_or(Dimension()).ToString().c_str(), filter);
156 json->PutExtAttr("letterSpacing", GetLetterSpacing().value_or(Dimension()).ToString().c_str(), filter);
157 json->PutExtAttr("lineHeight", GetLineHeight().value_or(0.0_vp).ToString().c_str(), filter);
158 json->PutExtAttr("textBaseline",
159 TEXT_BASE_LINE_TO_STRING.at(static_cast<int32_t>(GetTextBaseline().value_or(TextBaseline::ALPHABETIC)))
160 .c_str(), filter);
161 json->PutExtAttr("baselineOffset",
162 std::to_string(static_cast<int32_t>(GetBaselineOffset().value_or(0.0_vp).Value())).c_str(), filter);
163 json->PutExtAttr("textAlign",
164 V2::ConvertWrapTextAlignToString(GetTextAlign().value_or(TextAlign::START)).c_str(), filter);
165 json->PutExtAttr("textVerticalAlign", V2::ConvertWrapTextVerticalAlignToString(
166 GetTextVerticalAlign().value_or(TextVerticalAlign::BASELINE)).c_str(), filter);
167 json->PutExtAttr("textOverflow",
168 V2::ConvertWrapTextOverflowToString(GetTextOverflow().value_or(TextOverflow::CLIP)).c_str(), filter);
169 json->PutExtAttr("maxLines", std::to_string(GetMaxLines().value_or(UINT32_MAX)).c_str(), filter);
170 json->PutExtAttr("enableAutoSpacing", std::to_string(GetEnableAutoSpacing().value_or(false)).c_str(), filter);
171
172 auto shadow = GetTextShadow().value_or(std::vector<Shadow> { Shadow() });
173 // Determines if there are multiple textShadows
174 auto jsonShadow = (shadow.size() == 1) ? CovertShadowToJson(shadow.front()) : CovertShadowsToJson(shadow);
175 json->PutExtAttr("textShadow", jsonShadow, filter);
176 json->PutExtAttr("heightAdaptivePolicy", V2::ConvertWrapTextHeightAdaptivePolicyToString(
177 GetHeightAdaptivePolicy().value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST)).c_str(), filter);
178 json->PutExtAttr("copyOption", GetCopyOptionString().c_str(), filter);
179 json->PutExtAttr("wordBreak",
180 V2::ConvertWrapWordBreakToString(GetWordBreak().value_or(WordBreak::BREAK_WORD)).c_str(), filter);
181 json->PutExtAttr("lineBreakStrategy", V2::ConvertWrapLineBreakStrategyToString(
182 GetLineBreakStrategy().value_or(LineBreakStrategy::GREEDY)).c_str(), filter);
183 json->PutExtAttr("ellipsisMode",
184 V2::ConvertEllipsisModeToString(GetEllipsisMode().value_or(EllipsisMode::TAIL)).c_str(), filter);
185 json->PutExtAttr("textSelectable", V2::ConvertWrapTextSelectableToString(
186 GetTextSelectableMode().value_or(TextSelectableMode::SELECTABLE_UNFOCUSABLE)).c_str(), filter);
187 json->PutExtAttr("marqueeOptions", GetTextMarqueeOptionsString().c_str(), filter);
188 json->PutExtAttr("privacySensitive", host ? host->IsPrivacySensitive() : false, filter);
189 json->PutExtAttr("minFontScale", std::to_string(GetMinFontScale().value_or(MINFONTSCALE)).c_str(), filter);
190 json->PutExtAttr("maxFontScale", std::to_string(GetMaxFontScale().value_or(MAXFONTSCALE)).c_str(), filter);
191 json->PutExtAttr("lineSpacing", GetLineSpacing().value_or(0.0_vp).ToString().c_str(), filter);
192 json->PutExtAttr("onlyBetweenLines", GetIsOnlyBetweenLines().value_or(false) ? "true" : "false", filter);
193 json->PutExtAttr("optimizeTrailingSpace", GetOptimizeTrailingSpace().value_or(false) ? "true" : "false", filter);
194
195 if (GetTextEffectStrategyValue(TextEffectStrategy::NONE) != TextEffectStrategy::NONE) {
196 auto jsonNumericTransiton = JsonUtil::Create(true);
197 std::string direction = StringUtils::ToString(GetTextFlipDirectionValue(TextFlipDirection::DOWN));
198 std::string enableBlur = GetTextFlipEnableBlurValue(false) ? "true" : "false";
199 jsonNumericTransiton->Put("flipDirection", direction.c_str());
200 jsonNumericTransiton->Put("enableBlur", enableBlur.c_str());
201 json->PutExtAttr("numericTextTransitionOptions", jsonNumericTransiton->ToString().c_str(), filter);
202 }
203 }
204
FromJson(const std::unique_ptr<JsonValue> & json)205 void TextLayoutProperty::FromJson(const std::unique_ptr<JsonValue>& json)
206 {
207 UpdateContent(json->GetString("content"));
208 UpdateFontSize(Dimension::FromString(json->GetString("fontSize")));
209 UpdateTextColor(Color::ColorFromString(json->GetString("fontColor")));
210 UpdateFontWeight(V2::ConvertWrapStringToFontWeight(json->GetString("fontWeight")));
211 UpdateTextAlign(V2::ConvertWrapStringToTextAlign(json->GetString("textAlign")));
212 UpdateTextVerticalAlign(V2::ConvertWrapStringToTextVerticalAlign(json->GetString("textAlign")));
213 UpdateTextOverflow(V2::ConvertWrapStringToTextOverflow(json->GetString("textOverflow")));
214 UpdateMaxLines(StringUtils::StringToUint(json->GetString("maxLines")));
215 UpdateMarqueeOptionsFromJson(json->GetObject("marqueeOptions"));
216 LayoutProperty::FromJson(json);
217 }
218 } // namespace OHOS::Ace::NG
219