1 /*
2 * Copyright (c) 2021 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 "core/components/declaration/text/text_declaration.h"
17
18 #include "core/components/common/properties/text_style_parser.h"
19 #include "core/components/declaration/common/declaration_constants.h"
20 #include "core/components/text/text_theme.h"
21 #include "frameworks/bridge/common/utils/utils.h"
22
23 namespace OHOS::Ace {
24 namespace {
25
26 constexpr Dimension DEFAULT_LETTER_SPACING = 0.0_px; // unit is px
27 constexpr Dimension DEFAULT_LINE_HEIGHT = 0.0_px; // unit is px
28 constexpr Dimension DEFAULT_FONT_SIZE = 14.0_px;
29 const char DEFAULT_FONT_FAMILY[] = "sans-serif";
30
31 } // namespace
32
33 using namespace Framework;
34
InitSpecialized()35 void TextDeclaration::InitSpecialized()
36 {
37 AddSpecializedAttribute(DeclarationConstants::DEFAULT_TEXT_ATTR);
38 AddSpecializedStyle(DeclarationConstants::DEFAULT_TEXT_STYLE);
39 }
40
InitializeStyle()41 void TextDeclaration::InitializeStyle()
42 {
43 auto& style = MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
44 if (!style.IsValid()) {
45 return;
46 }
47
48 RefPtr<TextTheme> theme = GetTheme<TextTheme>();
49 if (theme) {
50 style.textStyle = theme->GetTextStyle();
51 style.focusColor = theme->GetTextStyle().GetTextColor();
52 std::vector<std::string> defaultFontFamilis;
53 defaultFontFamilis.emplace_back(DEFAULT_FONT_FAMILY);
54 style.textStyle.SetFontFamilies(defaultFontFamilis);
55 style.textStyle.SetLetterSpacing(DEFAULT_LETTER_SPACING);
56 style.textStyle.SetLineHeight(DEFAULT_LINE_HEIGHT, false);
57 }
58 }
59
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)60 bool TextDeclaration::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
61 {
62 if (attr.first == DOM_VALUE) {
63 SetData(attr.second);
64 return true;
65 }
66 return false;
67 }
68
SetSpecializedStyle(const std::pair<std::string,std::string> & style)69 bool TextDeclaration::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
70 {
71 // static linear map must be sorted by key.
72 static const LinearMapNode<void (*)(const std::string&, TextDeclaration&)> textStyleOperators[] = {
73 { DOM_TEXT_ADAPT_HEIGHT,
74 [](const std::string& val, TextDeclaration& declaration) {
75 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
76 if (specializedStyle.IsValid()) {
77 specializedStyle.textStyle.SetAdaptHeight(StringToBool(val));
78 }
79 } },
80 { DOM_TEXT_ALLOW_SCALE,
81 [](const std::string& val, TextDeclaration& declaration) {
82 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
83 if (specializedStyle.IsValid()) {
84 specializedStyle.textStyle.SetAllowScale(StringToBool(val));
85 }
86 } },
87 { DOM_TEXT_COLOR,
88 [](const std::string& val, TextDeclaration& declaration) {
89 declaration.hasSetTextColor_ = true;
90 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
91 if (specializedStyle.IsValid()) {
92 const auto& color = val.empty() ? Color::BLACK : declaration.ParseColor(val);
93 specializedStyle.textStyle.SetTextColor(color);
94 specializedStyle.focusColor = color;
95 }
96 } },
97 { DOM_TEXT_FONT_FAMILY,
98 [](const std::string& val, TextDeclaration& declaration) {
99 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
100 if (specializedStyle.IsValid()) {
101 specializedStyle.textStyle.SetFontFamilies(declaration.ParseFontFamilies(val));
102 }
103 } },
104 { DOM_TEXT_FONT_FEATURE_SETTINGS,
105 [](const std::string& val, TextDeclaration& declaration) {
106 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
107 if (specializedStyle.IsValid()) {
108 specializedStyle.textStyle.SetFontFeatures(ParseFontFeatureSettings(val));
109 }
110 } },
111 { DOM_TEXT_FONT_SIZE,
112 [](const std::string& val, TextDeclaration& declaration) {
113 declaration.hasSetTextFontSize_ = true;
114 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
115 if (specializedStyle.IsValid()) {
116 auto fontSize = val.empty() ? DEFAULT_FONT_SIZE : declaration.ParseDimension(val);
117 specializedStyle.textStyle.SetFontSize(fontSize);
118 }
119 } },
120 { DOM_TEXT_FONT_SIZE_STEP,
121 [](const std::string& val, TextDeclaration& declaration) {
122 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
123 if (specializedStyle.IsValid()) {
124 specializedStyle.textStyle.SetAdaptFontSizeStep(declaration.ParseDimension(val));
125 }
126 } },
127 { DOM_TEXT_FONT_STYLE,
128 [](const std::string& val, TextDeclaration& declaration) {
129 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
130 if (specializedStyle.IsValid()) {
131 specializedStyle.textStyle.SetFontStyle(ConvertStrToFontStyle(val));
132 }
133 } },
134 { DOM_TEXT_FONT_VARIANT,
135 [](const std::string& val, TextDeclaration& declaration) {
136 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
137 if (specializedStyle.IsValid()) {
138 specializedStyle.textStyle.SetFontFeatures(ParseFontVariants(val));
139 }
140 } },
141 { DOM_TEXT_FONT_WEIGHT,
142 [](const std::string& val, TextDeclaration& declaration) {
143 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
144 if (specializedStyle.IsValid()) {
145 specializedStyle.textStyle.SetFontWeight(ConvertStrToFontWeight(val));
146 }
147 } },
148 { DOM_TEXT_LETTER_SPACING,
149 [](const std::string& val, TextDeclaration& declaration) {
150 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
151 if (specializedStyle.IsValid()) {
152 specializedStyle.textStyle.SetLetterSpacing(declaration.ParseDimension(val));
153 }
154 } },
155 { DOM_TEXT_LINE_HEIGHT,
156 [](const std::string& val, TextDeclaration& declaration) {
157 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
158 if (specializedStyle.IsValid()) {
159 if (val == "normal") {
160 specializedStyle.textStyle.SetLineHeight(Dimension(0.0));
161 } else {
162 specializedStyle.textStyle.SetLineHeight(declaration.ParseLineHeight(val));
163 }
164 }
165 } },
166 { DOM_TEXT_LINES,
167 [](const std::string& val, TextDeclaration& declaration) {
168 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
169 if (specializedStyle.IsValid()) {
170 specializedStyle.textStyle.SetMaxLines(StringUtils::StringToInt(val));
171 }
172 } },
173 { DOM_TEXT_MAX_FONT_SIZE,
174 [](const std::string& val, TextDeclaration& declaration) {
175 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
176 if (specializedStyle.IsValid()) {
177 specializedStyle.textStyle.SetAdaptMaxFontSize(declaration.ParseDimension(val));
178 }
179 } },
180 { DOM_TEXT_MAX_LINES,
181 [](const std::string& val, TextDeclaration& declaration) {
182 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
183 if (specializedStyle.IsValid()) {
184 specializedStyle.textStyle.SetMaxLines(StringUtils::StringToUint(val, UINT32_MAX));
185 declaration.SetAutoMaxLines(val == DOM_AUTO);
186 }
187 } },
188 { DOM_TEXT_MIN_FONT_SIZE,
189 [](const std::string& val, TextDeclaration& declaration) {
190 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
191 if (specializedStyle.IsValid()) {
192 specializedStyle.textStyle.SetAdaptMinFontSize(declaration.ParseDimension(val));
193 }
194 } },
195 { DOM_TEXT_PREFER_FONT_SIZES,
196 [](const std::string& val, TextDeclaration& declaration) {
197 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
198 if (specializedStyle.IsValid()) {
199 specializedStyle.textStyle.SetPreferFontSizes(declaration.ParsePreferFontSizes(val));
200 }
201 } },
202 { DOM_TEXT_ALIGN,
203 [](const std::string& val, TextDeclaration& declaration) {
204 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
205 if (specializedStyle.IsValid()) {
206 specializedStyle.textStyle.SetTextAlign(ConvertStrToTextAlign(val));
207 }
208 } },
209 { DOM_TEXT_DECORATION,
210 [](const std::string& val, TextDeclaration& declaration) {
211 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
212 if (specializedStyle.IsValid()) {
213 specializedStyle.textStyle.SetTextDecoration(ConvertStrToTextDecoration(val));
214 }
215 } },
216 { DOM_TEXT_DECORATION_COLOR,
217 [](const std::string& val, TextDeclaration& declaration) {
218 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
219 if (specializedStyle.IsValid()) {
220 specializedStyle.textStyle.SetTextDecorationColor(declaration.ParseColor(val));
221 }
222 } },
223 { DOM_TEXT_DECORATION_STYLE,
224 [](const std::string& val, TextDeclaration& declaration) {
225 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
226 if (specializedStyle.IsValid()) {
227 specializedStyle.textStyle.SetTextDecorationStyle(ConvertStrToTextDecorationStyle(val));
228 }
229 } },
230 { DOM_TEXT_INDENT, [](const std::string& val, TextDeclaration& declaration) {
231 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
232 if (specializedStyle.IsValid()) {
233 specializedStyle.textStyle.SetTextIndent(StringToDimension(val));
234 }
235 } },
236 { DOM_TEXT_OVERFLOW,
237 [](const std::string& val, TextDeclaration& declaration) {
238 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
239 if (specializedStyle.IsValid()) {
240 specializedStyle.textStyle.SetTextOverflow(ConvertStrToTextOverflow(val));
241 }
242 } },
243 { DOM_TEXT_SHADOW,
244 [](const std::string& val, TextDeclaration& declaration) {
245 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
246 if (specializedStyle.IsValid()) {
247 specializedStyle.textStyle.SetTextShadows(TextDeclaration::ParseTextShadow(val, declaration));
248 }
249 } },
250 { DOM_TEXT_VERTICAL_ALIGN,
251 [](const std::string& val, TextDeclaration& declaration) {
252 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
253 if (specializedStyle.IsValid()) {
254 specializedStyle.textStyle.SetTextVerticalAlign(ConvertStrToTextVerticalAlign(val));
255 }
256 } },
257 { DOM_TEXT_WHITE_SPACE, [](const std::string& val, TextDeclaration& declaration) {
258 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
259 if (specializedStyle.IsValid()) {
260 specializedStyle.textStyle.SetWhiteSpace(ConvertStrToWhiteSpace(val));
261 }
262 } },
263 { DOM_TEXT_WORD_BREAK,
264 [](const std::string& val, TextDeclaration& declaration) {
265 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
266 if (specializedStyle.IsValid()) {
267 specializedStyle.textStyle.SetWordBreak(ConvertStrToWordBreak(val));
268 }
269 } },
270 { DOM_TEXT_WORD_SPACING,
271 [](const std::string& val, TextDeclaration& declaration) {
272 auto& specializedStyle = declaration.MaybeResetStyle<TextSpecializedStyle>(StyleTag::SPECIALIZED_STYLE);
273 if (specializedStyle.IsValid()) {
274 if (val == "normal") {
275 specializedStyle.textStyle.SetWordSpacing(Dimension(0.0));
276 } else {
277 specializedStyle.textStyle.SetWordSpacing(StringToDimension(val));
278 }
279 }
280 } },
281 };
282 auto operatorIter = BinarySearchFindIndex(textStyleOperators, ArraySize(textStyleOperators), style.first.c_str());
283 if (operatorIter != -1) {
284 textStyleOperators[operatorIter].value(style.second, *this);
285 return true;
286 }
287 return false;
288 }
289
ParseTextShadow(const std::string & val,TextDeclaration & declaration)290 std::vector<Shadow> TextDeclaration::ParseTextShadow(const std::string& val, TextDeclaration& declaration)
291 {
292 std::vector<Shadow> textShadowList;
293 std::vector<std::string> textShadowValues;
294 StringUtils::SplitStr(val, ",", textShadowValues);
295 auto IsValidDimension = [](const std::string& str) {
296 return str.find("px") != std::string::npos || str == "0";
297 };
298
299 for (auto &textShadowValue : textShadowValues) {
300 std::vector<std::string> textShadowProps;
301 StringUtils::SplitStr(textShadowValue, " ", textShadowProps);
302 Shadow textShadow;
303 size_t pos = 0;
304 switch (static_cast<TextShadowSettings>(textShadowProps.size())) {
305 case TextShadowSettings::OFFSET_ONLY:
306 // text shadow values format:offsetx, offsety
307 textShadow.SetOffsetX(declaration.ParseDouble(textShadowProps[pos++]));
308 textShadow.SetOffsetY(declaration.ParseDouble(textShadowProps[pos]));
309 break;
310 case TextShadowSettings::OFFSET_EXTRA:
311 // support text shadow values format: offsetx offsety [blur-radius | color]
312 if (IsValidDimension(textShadowProps[0])) {
313 textShadow.SetOffsetX(declaration.ParseDouble(textShadowProps[pos++]));
314 textShadow.SetOffsetY(declaration.ParseDouble(textShadowProps[pos++]));
315 if (IsValidDimension(textShadowProps[pos])) {
316 // text shadow values format: offsetx offsety blur-radius
317 textShadow.SetBlurRadius(declaration.ParseDouble(textShadowProps[pos]));
318 } else {
319 // text shadow values format: offsetx offsety color
320 textShadow.SetColor(declaration.ParseColor(textShadowProps[pos]));
321 }
322 } else {
323 // text shadow values format:color offsetx offsety
324 textShadow.SetColor(declaration.ParseColor(textShadowProps[pos++]));
325 textShadow.SetOffsetX(declaration.ParseDouble(textShadowProps[pos++]));
326 textShadow.SetOffsetY(declaration.ParseDouble(textShadowProps[pos]));
327 }
328 break;
329 case TextShadowSettings::OFFSET_BLUR_CLOR:
330 if (IsValidDimension(textShadowProps[pos])) {
331 // text shadow values format: offsetx offsety blur-radius color
332 textShadow.SetOffsetX(declaration.ParseDouble(textShadowProps[pos++]));
333 textShadow.SetOffsetY(declaration.ParseDouble(textShadowProps[pos++]));
334 textShadow.SetBlurRadius(declaration.ParseDouble(textShadowProps[pos++]));
335 textShadow.SetColor(declaration.ParseColor(textShadowProps[pos]));
336 } else {
337 // text shadow values format:color offsetx offsety
338 textShadow.SetColor(declaration.ParseColor(textShadowProps[pos++]));
339 textShadow.SetOffsetX(declaration.ParseDouble(textShadowProps[pos++]));
340 textShadow.SetOffsetY(declaration.ParseDouble(textShadowProps[pos++]));
341 textShadow.SetBlurRadius(declaration.ParseDouble(textShadowProps[pos]));
342 }
343 break;
344 default:
345 break;
346 }
347 textShadowList.emplace_back(textShadow);
348 }
349 return textShadowList;
350 }
351
352 } // namespace OHOS::Ace
353