1 /*
2 * Copyright (c) 2022-2023 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_ng/pattern/text/text_styles.h"
17 #include "core/components_ng/pattern/text/text_layout_property.h"
18
19 namespace {
20 constexpr uint32_t RENDERINGSTRATEGY_MULTIPLE_COLOR = 1;
21 constexpr uint32_t RENDERINGSTRATEGY_MULTIPLE_OPACITY = 2;
22 }; // namespace
23
24 namespace OHOS::Ace::NG {
25 #define UPDATE_TEXT_STYLE(group, name, func) \
26 do { \
27 if ((group)->prop##name.has_value()) { \
28 textStyle.func((group)->prop##name.value()); \
29 } \
30 } while (false)
31
32 #define UPDATE_TEXT_STYLE_WITH_THEME(group, name, styleName) \
33 do { \
34 if (group && (group)->prop##name.has_value()) { \
35 textStyle.Set##styleName((group)->prop##name.value()); \
36 } else if (textTheme) { \
37 textStyle.Set##styleName(textTheme->GetTextStyle().Get##styleName()); \
38 } \
39 } while (false)
40
CreateTextStyleUsingTheme(const std::unique_ptr<FontStyle> & fontStyle,const std::unique_ptr<TextLineStyle> & textLineStyle,const RefPtr<TextTheme> & textTheme,bool isSymbol)41 TextStyle CreateTextStyleUsingTheme(const std::unique_ptr<FontStyle>& fontStyle,
42 const std::unique_ptr<TextLineStyle>& textLineStyle, const RefPtr<TextTheme>& textTheme, bool isSymbol)
43 {
44 TextStyle textStyle = textTheme ? textTheme->GetTextStyle() : TextStyle();
45 #ifndef OHOS_STANDARD_SYSTEM
46 const std::vector<std::string> defaultFontFamily = { "sans-serif" };
47 textStyle.SetFontFamilies(defaultFontFamily);
48 #endif
49 UseSelfStyle(fontStyle, textLineStyle, textStyle, isSymbol);
50 return textStyle;
51 }
52
CreateTextStyleUsingTheme(const RefPtr<TextLayoutProperty> & property,const RefPtr<TextTheme> & textTheme,TextStyle & textStyle,bool isSymbol)53 void CreateTextStyleUsingTheme(const RefPtr<TextLayoutProperty>& property, const RefPtr<TextTheme>& textTheme,
54 TextStyle& textStyle, bool isSymbol)
55 {
56 UseSelfStyleWithTheme(property, textStyle, textTheme, isSymbol);
57 }
58
UseSelfStyleWithTheme(const RefPtr<TextLayoutProperty> & property,TextStyle & textStyle,const RefPtr<TextTheme> & textTheme,bool isSymbol)59 void UseSelfStyleWithTheme(const RefPtr<TextLayoutProperty>& property, TextStyle& textStyle,
60 const RefPtr<TextTheme>& textTheme, bool isSymbol)
61 {
62 CHECK_NULL_VOID(textTheme);
63 auto& fontStyle = property->GetFontStyle();
64 auto& textLineStyle = property->GetTextLineStyle();
65 // The setting of AllowScale, MinFontScale, MaxFontScale must be done before any Dimension-type properties that
66 // depend on its value.
67 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, AllowScale, AllowScale);
68 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, MinFontScale, MinFontScale);
69 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, MaxFontScale, MaxFontScale);
70
71 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, FontSize, FontSize);
72 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, AdaptMinFontSize, AdaptMinFontSize);
73 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, AdaptMaxFontSize, AdaptMaxFontSize);
74 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, LetterSpacing, LetterSpacing);
75
76 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, TextShadow, TextShadows);
77 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, ItalicFontStyle, FontStyle);
78 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, FontWeight, FontWeight);
79 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, FontFeature, FontFeatures);
80 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, TextDecoration, TextDecoration);
81 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, TextDecorationColor, TextDecorationColor);
82 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, TextDecorationStyle, TextDecorationStyle);
83 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, TextCase, TextCase);
84 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, VariableFontWeight, VariableFontWeight);
85 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, EnableVariableFontWeight, EnableVariableFontWeight);
86
87 if (isSymbol) {
88 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, SymbolColorList, SymbolColorList);
89 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, SymbolRenderingStrategy, RenderStrategy);
90 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, SymbolEffectStrategy, EffectStrategy);
91 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, SymbolEffectOptions, SymbolEffectOptions);
92 UPDATE_TEXT_STYLE_WITH_THEME(fontStyle, SymbolType, SymbolType);
93 textStyle.SetSymbolShadow(property->GetSymbolShadowValue(textTheme->GetTextStyle().GetSymbolShadow()));
94 textStyle.SetShaderStyle(property->GetShaderStyleValue(textTheme->GetTextStyle().GetShaderStyle()));
95 }
96
97 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, LineHeight, LineHeight);
98 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, BaselineOffset, BaselineOffset);
99 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, TextIndent, TextIndent);
100 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, LineSpacing, LineSpacing);
101 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, TextBaseline, TextBaseline);
102 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, TextOverflow, TextOverflow);
103 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, TextAlign, TextAlign);
104 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, TextVerticalAlign, ParagraphVerticalAlign);
105 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, MaxLines, MaxLines);
106 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, WordBreak, WordBreak);
107 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, EllipsisMode, EllipsisMode);
108 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, LineBreakStrategy, LineBreakStrategy);
109 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, IsOnlyBetweenLines, IsOnlyBetweenLines);
110 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, ParagraphSpacing, ParagraphSpacing);
111 UPDATE_TEXT_STYLE_WITH_THEME(textLineStyle, OptimizeTrailingSpace, OptimizeTrailingSpace);
112 }
113
UseSelfStyle(const std::unique_ptr<FontStyle> & fontStyle,const std::unique_ptr<TextLineStyle> & textLineStyle,TextStyle & textStyle,bool isSymbol)114 void UseSelfStyle(const std::unique_ptr<FontStyle>& fontStyle, const std::unique_ptr<TextLineStyle>& textLineStyle,
115 TextStyle& textStyle, bool isSymbol)
116 {
117 if (textLineStyle) {
118 UPDATE_TEXT_STYLE(textLineStyle, AllowScale, SetAllowScale);
119 }
120 if (fontStyle) {
121 UPDATE_TEXT_STYLE(fontStyle, MinFontScale, SetMinFontScale);
122 UPDATE_TEXT_STYLE(fontStyle, MaxFontScale, SetMaxFontScale);
123
124 UPDATE_TEXT_STYLE(fontStyle, FontSize, SetFontSize);
125 UPDATE_TEXT_STYLE(fontStyle, AdaptMinFontSize, SetAdaptMinFontSize);
126 UPDATE_TEXT_STYLE(fontStyle, AdaptMaxFontSize, SetAdaptMaxFontSize);
127 UPDATE_TEXT_STYLE(fontStyle, LetterSpacing, SetLetterSpacing);
128
129 UPDATE_TEXT_STYLE(fontStyle, TextColor, SetTextColor);
130 UPDATE_TEXT_STYLE(fontStyle, TextShadow, SetTextShadows);
131 UPDATE_TEXT_STYLE(fontStyle, ItalicFontStyle, SetFontStyle);
132 UPDATE_TEXT_STYLE(fontStyle, FontWeight, SetFontWeight);
133 UPDATE_TEXT_STYLE(fontStyle, FontFamily, SetFontFamilies);
134 UPDATE_TEXT_STYLE(fontStyle, FontFeature, SetFontFeatures);
135 UPDATE_TEXT_STYLE(fontStyle, StrokeWidth, SetStrokeWidth);
136 UPDATE_TEXT_STYLE(fontStyle, StrokeColor, SetStrokeColor);
137 UPDATE_TEXT_STYLE(fontStyle, Superscript, SetSuperscript);
138 UPDATE_TEXT_STYLE(fontStyle, TextDecoration, SetTextDecoration);
139 UPDATE_TEXT_STYLE(fontStyle, TextDecorationColor, SetTextDecorationColor);
140 UPDATE_TEXT_STYLE(fontStyle, TextDecorationStyle, SetTextDecorationStyle);
141 UPDATE_TEXT_STYLE(fontStyle, LineThicknessScale, SetLineThicknessScale);
142 UPDATE_TEXT_STYLE(fontStyle, TextCase, SetTextCase);
143
144 UPDATE_TEXT_STYLE(fontStyle, VariableFontWeight, SetVariableFontWeight);
145 UPDATE_TEXT_STYLE(fontStyle, EnableVariableFontWeight, SetEnableVariableFontWeight);
146
147 if (isSymbol) {
148 UPDATE_TEXT_STYLE(fontStyle, SymbolColorList, SetSymbolColorList);
149 UPDATE_TEXT_STYLE(fontStyle, SymbolRenderingStrategy, SetRenderStrategy);
150 UPDATE_TEXT_STYLE(fontStyle, SymbolEffectStrategy, SetEffectStrategy);
151 UPDATE_TEXT_STYLE(fontStyle, SymbolEffectOptions, SetSymbolEffectOptions);
152 UPDATE_TEXT_STYLE(fontStyle, SymbolType, SetSymbolType);
153 }
154 }
155 if (textLineStyle) {
156 UPDATE_TEXT_STYLE(textLineStyle, LineHeight, SetLineHeight);
157 UPDATE_TEXT_STYLE(textLineStyle, BaselineOffset, SetBaselineOffset);
158 UPDATE_TEXT_STYLE(textLineStyle, TextIndent, SetTextIndent);
159 UPDATE_TEXT_STYLE(textLineStyle, LineSpacing, SetLineSpacing);
160
161 UPDATE_TEXT_STYLE(textLineStyle, HalfLeading, SetHalfLeading);
162 UPDATE_TEXT_STYLE(textLineStyle, TextBaseline, SetTextBaseline);
163 UPDATE_TEXT_STYLE(textLineStyle, TextOverflow, SetTextOverflow);
164 UPDATE_TEXT_STYLE(textLineStyle, TextAlign, SetTextAlign);
165 UPDATE_TEXT_STYLE(textLineStyle, TextVerticalAlign, SetParagraphVerticalAlign);
166 UPDATE_TEXT_STYLE(textLineStyle, MaxLines, SetMaxLines);
167 UPDATE_TEXT_STYLE(textLineStyle, WordBreak, SetWordBreak);
168 UPDATE_TEXT_STYLE(textLineStyle, EllipsisMode, SetEllipsisMode);
169 UPDATE_TEXT_STYLE(textLineStyle, LineBreakStrategy, SetLineBreakStrategy);
170 UPDATE_TEXT_STYLE(textLineStyle, IsOnlyBetweenLines, SetIsOnlyBetweenLines);
171 UPDATE_TEXT_STYLE(textLineStyle, ParagraphSpacing, SetParagraphSpacing);
172 UPDATE_TEXT_STYLE(textLineStyle, OptimizeTrailingSpace, SetOptimizeTrailingSpace);
173 }
174 }
175
GetFontSizeInJson(const std::optional<Dimension> & value)176 std::string GetFontSizeInJson(const std::optional<Dimension>& value)
177 {
178 return value.value_or(TEXT_DEFAULT_FONT_SIZE).ToString();
179 }
GetFontStyleInJson(const std::optional<Ace::FontStyle> & value)180 std::string GetFontStyleInJson(const std::optional<Ace::FontStyle>& value)
181 {
182 return value.value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL ? "FontStyle.Normal" : "FontStyle.Italic";
183 }
GetFontWeightInJson(const std::optional<FontWeight> & value)184 std::string GetFontWeightInJson(const std::optional<FontWeight>& value)
185 {
186 return V2::ConvertWrapFontWeightToStirng(value.value_or(FontWeight::NORMAL));
187 }
GetFontFamilyInJson(const std::optional<std::vector<std::string>> & value)188 std::string GetFontFamilyInJson(const std::optional<std::vector<std::string>>& value)
189 {
190 std::vector<std::string> fontFamilyVector = value.value_or<std::vector<std::string>>({ "HarmonyOS Sans" });
191 if (fontFamilyVector.empty()) {
192 fontFamilyVector = std::vector<std::string>({ "HarmonyOS Sans" });
193 }
194 std::string fontFamily = fontFamilyVector.at(0);
195 for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
196 fontFamily += ',' + fontFamilyVector.at(i);
197 }
198 return fontFamily;
199 }
GetFontFamilyInJson(const std::vector<std::string> & fontFamilyVector)200 std::string GetFontFamilyInJson(const std::vector<std::string>& fontFamilyVector)
201 {
202 std::string fontFamily;
203 if (fontFamilyVector.empty()) {
204 return fontFamily;
205 }
206 fontFamily = fontFamilyVector.at(0);
207 for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
208 fontFamily += ',' + fontFamilyVector.at(i);
209 }
210 return fontFamily;
211 }
GetSymbolRenderingStrategyInJson(const std::optional<uint32_t> & value)212 std::string GetSymbolRenderingStrategyInJson(const std::optional<uint32_t>& value)
213 {
214 std::string text;
215 if (value == RENDERINGSTRATEGY_MULTIPLE_COLOR) {
216 text = "SymbolRenderingStrategy.MULTIPLE_COLOR";
217 } else if (value == RENDERINGSTRATEGY_MULTIPLE_OPACITY) {
218 text = "SymbolRenderingStrategy.MULTIPLE_OPACITY";
219 } else {
220 text = "SymbolRenderingStrategy.SINGLE";
221 }
222 return text;
223 }
GetSymbolEffectStrategyInJson(const std::optional<uint32_t> & value)224 std::string GetSymbolEffectStrategyInJson(const std::optional<uint32_t>& value)
225 {
226 std::string text;
227 SymbolEffectType type = static_cast<SymbolEffectType>(value.value_or(0));
228 if (type == SymbolEffectType::SCALE) {
229 text = "SymbolEffectStrategy.SCALE";
230 } else if (type == SymbolEffectType::HIERARCHICAL) {
231 text = "SymbolEffectStrategy.HIERARCHICAL";
232 } else {
233 text = "SymbolEffectStrategy.NONE";
234 }
235 return text;
236 }
237
GetLineBreakStrategyInJson(const std::optional<Ace::LineBreakStrategy> & value)238 std::string GetLineBreakStrategyInJson(const std::optional<Ace::LineBreakStrategy>& value)
239 {
240 std::string text;
241 if (value == LineBreakStrategy::HIGH_QUALITY) {
242 text = "HIGH_QUALITY";
243 } else if (value == LineBreakStrategy::BALANCED) {
244 text = "BALANCED";
245 } else {
246 text = "GREEDY";
247 }
248 return text;
249 }
250
GetSymbolEffectOptionsInJson(const std::optional<SymbolEffectOptions> & value)251 std::string GetSymbolEffectOptionsInJson(const std::optional<SymbolEffectOptions>& value)
252 {
253 std::string text = "";
254 if (value.has_value()) {
255 text = value.value().ToString();
256 }
257 return text;
258 }
259
GetSymbolShadowInJson(const std::optional<SymbolShadow> & value)260 std::unique_ptr<JsonValue> GetSymbolShadowInJson(const std::optional<SymbolShadow>& value)
261 {
262 auto res = JsonUtil::Create(true);
263 if (!value.has_value()) {
264 return res;
265 }
266 const auto& shadow = value.value();
267 res->Put("color", (shadow.color).ColorToString().c_str());
268 std::string offsetStr = "[" + std::to_string(shadow.offset.first) + ", "
269 + std::to_string(shadow.offset.second) + "]";
270 res->Put("offset", offsetStr.c_str());
271 res->Put("radius", std::to_string(shadow.radius).c_str());
272 return res;
273 }
274
GradientTypeToString(SymbolGradientType type)275 std::string GradientTypeToString(SymbolGradientType type)
276 {
277 switch (type) {
278 case SymbolGradientType::COLOR_SHADER:
279 return "COLOR_SHADER";
280 case SymbolGradientType::RADIAL_GRADIENT:
281 return "RADIAL_GRADIENT";
282 case SymbolGradientType::LINEAR_GRADIENT:
283 return "LINEAR_GRADIENT";
284 default:
285 return "UNKNOWN";
286 }
287 }
288
GetShaderStyleInJson(const std::optional<std::vector<SymbolGradient>> & value)289 std::unique_ptr<JsonValue> GetShaderStyleInJson(const std::optional<std::vector<SymbolGradient>>& value)
290 {
291 auto array = JsonUtil::CreateArray(true);
292 if (!value.has_value() || value->empty()) {
293 return array;
294 }
295 for (const auto& gradient : *value) {
296 auto obj = JsonUtil::Create(true);
297 obj->Put("type", GradientTypeToString(gradient.type).c_str());
298 auto colorsArray = JsonUtil::CreateArray(true);
299 for (const auto& color : gradient.symbolColor) {
300 colorsArray->Put("", color.ColorToString().c_str());
301 }
302 obj->Put("symbolColor", colorsArray);
303 auto opacitiesArray = JsonUtil::CreateArray(true);
304 for (float opacity : gradient.symbolOpacities) {
305 opacitiesArray->Put("", std::to_string(opacity).c_str());
306 }
307 obj->Put("symbolOpacities", opacitiesArray);
308 obj->Put("repeating", gradient.repeating ? "true" : "false");
309 if (gradient.angle.has_value()) {
310 obj->Put("angle", std::to_string(*gradient.angle).c_str());
311 }
312 if (gradient.radius.has_value()) {
313 obj->Put("radius", gradient.radius->ToString().c_str());
314 }
315 if (gradient.radialCenterX.has_value()) {
316 obj->Put("radialCenterX", gradient.radialCenterX->ToString().c_str());
317 }
318 if (gradient.radialCenterY.has_value()) {
319 obj->Put("radialCenterY", gradient.radialCenterY->ToString().c_str());
320 }
321 array->Put(obj);
322 }
323 return array;
324 }
325
UpdateColorByResourceId()326 void FontStyle::UpdateColorByResourceId()
327 {
328 if (propTextColor) {
329 propTextColor->UpdateColorByResourceId();
330 }
331 if (propTextDecorationColor) {
332 propTextDecorationColor->UpdateColorByResourceId();
333 }
334 if (propTextShadow) {
335 auto& shadows = propTextShadow.value();
336 std::for_each(shadows.begin(), shadows.end(), [](Shadow& sd) { sd.UpdateColorByResourceId(); });
337 }
338 if (propSymbolColorList) {
339 auto& colors = propSymbolColorList.value();
340 std::for_each(colors.begin(), colors.end(), [](Color& cl) { cl.UpdateColorByResourceId(); });
341 }
342 }
343
GetPlaceHolderAlignmentFromVerticalAlign(VerticalAlign verticalAlign)344 PlaceholderAlignment GetPlaceHolderAlignmentFromVerticalAlign(VerticalAlign verticalAlign)
345 {
346 PlaceholderAlignment alignment;
347 switch (verticalAlign) {
348 case VerticalAlign::TOP:
349 alignment = PlaceholderAlignment::TOP;
350 break;
351 case VerticalAlign::CENTER:
352 alignment = PlaceholderAlignment::MIDDLE;
353 break;
354 case VerticalAlign::BOTTOM:
355 case VerticalAlign::NONE:
356 alignment = PlaceholderAlignment::BOTTOM;
357 break;
358 case VerticalAlign::BASELINE:
359 alignment = PlaceholderAlignment::ABOVEBASELINE;
360 break;
361 case VerticalAlign::FOLLOW_PARAGRAPH:
362 alignment = PlaceholderAlignment::FOLLOW_PARAGRAPH;
363 break;
364 default:
365 alignment = PlaceholderAlignment::BOTTOM;
366 }
367 return alignment;
368 }
369 } // namespace OHOS::Ace::NG
370