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