• 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 "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