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