1 /*
2 * Copyright (c) 2021-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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_TEXT_STYLE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_TEXT_STYLE_H
18
19 #include <string>
20 #include <unordered_map>
21 #include <vector>
22
23 #include "base/geometry/dimension.h"
24 #include "base/utils/linear_map.h"
25 #include "core/components/common/layout/constants.h"
26 #include "core/components/common/properties/color.h"
27 #include "core/components/common/properties/shadow.h"
28 #include "core/pipeline/base/render_component.h"
29
30 namespace OHOS::Ace {
31
32 // The normal weight is W400, the larger the number after W, the thicker the font will be.
33 // BOLD is equal to W700 and NORMAL is equal to W400, lighter is W100, BOLDER is W900.
34 enum class FontWeight {
35 W100 = 0,
36 W200,
37 W300,
38 W400,
39 W500,
40 W600,
41 W700,
42 W800,
43 W900,
44 BOLD,
45 NORMAL,
46 BOLDER,
47 LIGHTER,
48 MEDIUM,
49 REGULAR,
50 };
51
52 enum class FontStyle {
53 NORMAL,
54 ITALIC,
55 };
56
57 enum class TextBaseline {
58 ALPHABETIC,
59 IDEOGRAPHIC,
60 TOP,
61 BOTTOM,
62 MIDDLE,
63 HANGING,
64 };
65
66 enum class TextCase {
67 NORMAL = 0,
68 LOWERCASE,
69 UPPERCASE,
70 };
71
72 enum class WordBreak { NORMAL = 0, BREAK_ALL, BREAK_WORD };
73
74 /// Where to vertically align the placeholder relative to the surrounding text.
75 enum class PlaceholderAlignment {
76 /// Match the baseline of the placeholder with the baseline.
77 BASELINE,
78
79 /// Align the bottom edge of the placeholder with the baseline such that the
80 /// placeholder sits on top of the baseline.
81 ABOVEBASELINE,
82
83 /// Align the top edge of the placeholder with the baseline specified in
84 /// such that the placeholder hangs below the baseline.
85 BELOWBASELINE,
86
87 /// Align the top edge of the placeholder with the top edge of the font.
88 /// When the placeholder is very tall, the extra space will hang from
89 /// the top and extend through the bottom of the line.
90 TOP,
91
92 /// Align the bottom edge of the placeholder with the top edge of the font.
93 /// When the placeholder is very tall, the extra space will rise from
94 /// the bottom and extend through the top of the line.
95 BOTTOM,
96
97 /// Align the middle of the placeholder with the middle of the text. When the
98 /// placeholder is very tall, the extra space will grow equally from
99 /// the top and bottom of the line.
100 MIDDLE,
101 };
102
103 struct TextSizeGroup {
104 Dimension fontSize = 14.0_px;
105 uint32_t maxLines = INT32_MAX;
106 TextOverflow textOverflow = TextOverflow::CLIP;
107 };
108
109 /// Placeholder properties
110 struct PlaceholderRun {
111 /// Placeholder's width
112 float width = 0.0f;
113
114 /// Placeholder's height
115 float height = 0.0f;
116
117 /// Vertically alignment the placeholder relative to the surrounding text.
118 PlaceholderAlignment alignment = PlaceholderAlignment::BOTTOM;
119
120 /// The placeholder with the baseline styles
121 TextBaseline baseline = TextBaseline::ALPHABETIC;
122
123 /// The baseline offset
124 float baseline_offset = 0.0f;
125 };
126
127 class ACE_EXPORT TextStyle final {
128 public:
129 TextStyle() = default;
130 TextStyle(const std::vector<std::string>& fontFamilies, double fontSize, FontWeight fontWeight, FontStyle fontStyle,
131 const Color& textColor);
132 ~TextStyle() = default;
133
134 bool operator==(const TextStyle& rhs) const;
135 bool operator!=(const TextStyle& rhs) const;
136
GetTextBaseline()137 TextBaseline GetTextBaseline() const
138 {
139 return textBaseline_;
140 }
141
GetBaselineOffset()142 const Dimension& GetBaselineOffset() const
143 {
144 return baselineOffset_;
145 }
146
SetBaselineOffset(const Dimension & baselineOffset)147 void SetBaselineOffset(const Dimension& baselineOffset)
148 {
149 baselineOffset_ = baselineOffset;
150 }
151
SetTextBaseline(TextBaseline baseline)152 void SetTextBaseline(TextBaseline baseline)
153 {
154 textBaseline_ = baseline;
155 }
156
SetTextDecoration(TextDecoration textDecoration)157 void SetTextDecoration(TextDecoration textDecoration)
158 {
159 textDecoration_ = textDecoration;
160 }
161
GetFontStyle()162 FontStyle GetFontStyle() const
163 {
164 return fontStyle_;
165 }
166
SetFontStyle(FontStyle fontStyle)167 void SetFontStyle(FontStyle fontStyle)
168 {
169 fontStyle_ = fontStyle;
170 }
171
GetFontSize()172 const Dimension& GetFontSize() const
173 {
174 return fontSize_;
175 }
176
GetWhiteSpace()177 WhiteSpace GetWhiteSpace() const
178 {
179 return whiteSpace_;
180 }
181
SetWhiteSpace(WhiteSpace whiteSpace)182 void SetWhiteSpace(WhiteSpace whiteSpace)
183 {
184 whiteSpace_ = whiteSpace;
185 }
186
SetFontSize(const Dimension & fontSize)187 void SetFontSize(const Dimension& fontSize)
188 {
189 fontSize_ = fontSize;
190 }
191
GetFontWeight()192 FontWeight GetFontWeight() const
193 {
194 return fontWeight_;
195 }
196
SetFontWeight(FontWeight fontWeight)197 void SetFontWeight(FontWeight fontWeight)
198 {
199 fontWeight_ = fontWeight;
200 }
201
GetTextColor()202 const Color& GetTextColor() const
203 {
204 return textColor_;
205 }
206
SetTextColor(const Color & textColor)207 void SetTextColor(const Color& textColor)
208 {
209 textColor_ = textColor;
210 }
211
GetTextDecoration()212 TextDecoration GetTextDecoration() const
213 {
214 return textDecoration_;
215 }
216
GetWordSpacing()217 const Dimension& GetWordSpacing() const
218 {
219 return wordSpacing_;
220 }
221
SetWordSpacing(const Dimension & wordSpacing)222 void SetWordSpacing(const Dimension& wordSpacing)
223 {
224 wordSpacing_ = wordSpacing;
225 }
226
GetTextDecorationColor()227 const Color& GetTextDecorationColor() const
228 {
229 return textDecorationColor_;
230 }
231
SetTextDecorationColor(const Color & textDecorationColor)232 void SetTextDecorationColor(const Color& textDecorationColor)
233 {
234 textDecorationColor_ = textDecorationColor;
235 }
236
GetFontFamilies()237 const std::vector<std::string>& GetFontFamilies() const
238 {
239 return fontFamilies_;
240 }
241
SetFontFamilies(const std::vector<std::string> & fontFamilies)242 void SetFontFamilies(const std::vector<std::string>& fontFamilies)
243 {
244 fontFamilies_ = fontFamilies;
245 }
246
GetTextIndent()247 Dimension GetTextIndent() const
248 {
249 return textIndent_;
250 }
251
SetTextIndent(const Dimension & textIndent)252 void SetTextIndent(const Dimension& textIndent)
253 {
254 textIndent_ = textIndent;
255 }
256
GetFontFeatures()257 const std::unordered_map<std::string, int32_t>& GetFontFeatures() const
258 {
259 return fontFeatures_;
260 }
261
SetFontFeatures(const std::unordered_map<std::string,int32_t> & fontFeatures)262 void SetFontFeatures(const std::unordered_map<std::string, int32_t>& fontFeatures)
263 {
264 fontFeatures_ = fontFeatures;
265 }
266
GetLineHeight()267 const Dimension& GetLineHeight() const
268 {
269 return lineHeight_;
270 }
271
272 void SetLineHeight(const Dimension& lineHeight, bool hasHeightOverride = true)
273 {
274 lineHeight_ = lineHeight;
275 hasHeightOverride_ = hasHeightOverride;
276 }
277
HasHeightOverride()278 bool HasHeightOverride() const
279 {
280 return hasHeightOverride_;
281 }
282
GetLetterSpacing()283 const Dimension& GetLetterSpacing() const
284 {
285 return letterSpacing_;
286 }
287
SetLetterSpacing(const Dimension & letterSpacing)288 void SetLetterSpacing(const Dimension& letterSpacing)
289 {
290 letterSpacing_ = letterSpacing;
291 }
292
GetAdaptTextSize()293 bool GetAdaptTextSize() const
294 {
295 return adaptTextSize_;
296 }
297
298 void SetAdaptTextSize(
299 const Dimension& maxFontSize, const Dimension& minFontSize, const Dimension& fontSizeStep = 1.0_px);
300
GetAdaptHeight()301 bool GetAdaptHeight() const
302 {
303 return adaptHeight_;
304 }
305
SetAdaptHeight(bool adaptHeight)306 void SetAdaptHeight(bool adaptHeight)
307 {
308 adaptHeight_ = adaptHeight;
309 }
310
DisableAdaptTextSize()311 void DisableAdaptTextSize()
312 {
313 adaptTextSize_ = false;
314 }
315
GetMaxLines()316 uint32_t GetMaxLines() const
317 {
318 return maxLines_;
319 }
320
SetMaxLines(uint32_t maxLines)321 void SetMaxLines(uint32_t maxLines)
322 {
323 maxLines_ = maxLines;
324 }
325
SetPreferFontSizes(const std::vector<Dimension> & preferFontSizes)326 void SetPreferFontSizes(const std::vector<Dimension>& preferFontSizes)
327 {
328 preferFontSizes_ = preferFontSizes;
329 adaptTextSize_ = true;
330 }
331
GetPreferFontSizes()332 const std::vector<Dimension>& GetPreferFontSizes() const
333 {
334 return preferFontSizes_;
335 }
336
337 // Must use with SetAdaptMinFontSize and SetAdaptMaxFontSize.
SetAdaptFontSizeStep(const Dimension & adaptTextSizeStep)338 void SetAdaptFontSizeStep(const Dimension& adaptTextSizeStep)
339 {
340 adaptFontSizeStep_ = adaptTextSizeStep;
341 }
342 // Must use with SetAdaptMaxFontSize.
SetAdaptMinFontSize(const Dimension & adaptMinFontSize)343 void SetAdaptMinFontSize(const Dimension& adaptMinFontSize)
344 {
345 adaptMinFontSize_ = adaptMinFontSize;
346 adaptTextSize_ = true;
347 }
348 // Must use with SetAdaptMinFontSize.
SetAdaptMaxFontSize(const Dimension & adaptMaxFontSize)349 void SetAdaptMaxFontSize(const Dimension& adaptMaxFontSize)
350 {
351 adaptMaxFontSize_ = adaptMaxFontSize;
352 adaptTextSize_ = true;
353 }
354
GetAdaptFontSizeStep()355 const Dimension& GetAdaptFontSizeStep() const
356 {
357 return adaptFontSizeStep_;
358 }
359
GetAdaptMinFontSize()360 const Dimension& GetAdaptMinFontSize() const
361 {
362 return adaptMinFontSize_;
363 }
364
GetAdaptMaxFontSize()365 const Dimension& GetAdaptMaxFontSize() const
366 {
367 return adaptMaxFontSize_;
368 }
369
GetPreferTextSizeGroups()370 const std::vector<TextSizeGroup>& GetPreferTextSizeGroups() const
371 {
372 return preferTextSizeGroups_;
373 }
SetPreferTextSizeGroups(const std::vector<TextSizeGroup> & preferTextSizeGroups)374 void SetPreferTextSizeGroups(const std::vector<TextSizeGroup>& preferTextSizeGroups)
375 {
376 preferTextSizeGroups_ = preferTextSizeGroups;
377 adaptTextSize_ = true;
378 }
379
IsAllowScale()380 bool IsAllowScale() const
381 {
382 return allowScale_;
383 }
384
SetAllowScale(bool allowScale)385 void SetAllowScale(bool allowScale)
386 {
387 allowScale_ = allowScale;
388 }
389
GetTextOverflow()390 TextOverflow GetTextOverflow() const
391 {
392 return textOverflow_;
393 }
SetTextOverflow(TextOverflow textOverflow)394 void SetTextOverflow(TextOverflow textOverflow)
395 {
396 textOverflow_ = textOverflow;
397 }
GetTextAlign()398 TextAlign GetTextAlign() const
399 {
400 return textAlign_;
401 }
SetTextAlign(TextAlign textAlign)402 void SetTextAlign(TextAlign textAlign)
403 {
404 textAlign_ = textAlign;
405 }
SetTextVerticalAlign(VerticalAlign verticalAlign)406 void SetTextVerticalAlign(VerticalAlign verticalAlign)
407 {
408 verticalAlign_ = verticalAlign;
409 }
410
GetTextVerticalAlign()411 VerticalAlign GetTextVerticalAlign() const
412 {
413 return verticalAlign_;
414 }
415
GetWordBreak()416 WordBreak GetWordBreak() const
417 {
418 return wordBreak_;
419 }
420
SetWordBreak(WordBreak wordBreak)421 void SetWordBreak(WordBreak wordBreak)
422 {
423 wordBreak_ = wordBreak;
424 }
425
GetTextCase()426 TextCase GetTextCase() const
427 {
428 return textCase_;
429 }
430
SetTextCase(TextCase textCase)431 void SetTextCase(TextCase textCase)
432 {
433 textCase_ = textCase;
434 }
435
GetTextShadows()436 const std::vector<Shadow>& GetTextShadows() const
437 {
438 return textShadows_;
439 }
440
SetTextShadows(std::vector<Shadow> && textShadows)441 void SetTextShadows(std::vector<Shadow>&& textShadows)
442 {
443 textShadows_ = textShadows;
444 }
445
SetShadow(Shadow & shadow)446 void SetShadow(Shadow &shadow)
447 {
448 textShadows_.emplace_back(shadow);
449 }
450
451 private:
452 std::vector<std::string> fontFamilies_;
453 std::unordered_map<std::string, int32_t> fontFeatures_;
454 std::vector<Dimension> preferFontSizes_;
455 std::vector<TextSizeGroup> preferTextSizeGroups_;
456 // use 14px for normal font size.
457 Dimension fontSize_ { 14, DimensionUnit::PX };
458 Dimension adaptMinFontSize_;
459 Dimension adaptMaxFontSize_;
460 Dimension adaptFontSizeStep_;
461 Dimension lineHeight_;
462 bool hasHeightOverride_ = false;
463 FontWeight fontWeight_ { FontWeight::NORMAL };
464 FontStyle fontStyle_ { FontStyle::NORMAL };
465 TextBaseline textBaseline_ { TextBaseline::ALPHABETIC };
466 Dimension baselineOffset_;
467 TextOverflow textOverflow_ { TextOverflow::CLIP };
468 VerticalAlign verticalAlign_ { VerticalAlign::NONE };
469 TextAlign textAlign_ { TextAlign::START };
470 Color textColor_ { Color::BLACK };
471 Color textDecorationColor_ { Color::BLACK };
472 TextDecoration textDecoration_ { TextDecoration::NONE };
473 std::vector<Shadow> textShadows_;
474 WhiteSpace whiteSpace_{ WhiteSpace::PRE };
475 Dimension wordSpacing_;
476 Dimension textIndent_ { 0.0f, DimensionUnit::PX };
477 Dimension letterSpacing_;
478 uint32_t maxLines_ = UINT32_MAX;
479 bool adaptTextSize_ = false;
480 bool adaptHeight_ = false; // whether adjust text size with height.
481 bool allowScale_ = true;
482 WordBreak wordBreak_ { WordBreak::BREAK_WORD };
483 TextCase textCase_ { TextCase::NORMAL };
484 };
485
486 namespace StringUtils {
487
488 inline FontWeight StringToFontWeight(const std::string& weight, FontWeight defaultFontWeight = FontWeight::NORMAL)
489 {
490 static const LinearMapNode<FontWeight> fontWeightTable[] = {
491 { "100", FontWeight::W100 },
492 { "200", FontWeight::W200 },
493 { "300", FontWeight::W300 },
494 { "400", FontWeight::W400 },
495 { "500", FontWeight::W500 },
496 { "600", FontWeight::W600 },
497 { "700", FontWeight::W700 },
498 { "800", FontWeight::W800 },
499 { "900", FontWeight::W900 },
500 { "bold", FontWeight::BOLD },
501 { "bolder", FontWeight::BOLDER },
502 { "lighter", FontWeight::LIGHTER },
503 { "medium", FontWeight::MEDIUM },
504 { "normal", FontWeight::NORMAL },
505 { "regular", FontWeight::REGULAR },
506 };
507 auto weightIter = BinarySearchFindIndex(fontWeightTable, ArraySize(fontWeightTable), weight.c_str());
508 return weightIter != -1 ? fontWeightTable[weightIter].value : defaultFontWeight;
509 }
510
StringToWordBreak(const std::string & wordBreak)511 inline WordBreak StringToWordBreak(const std::string& wordBreak)
512 {
513 static const LinearMapNode<WordBreak> wordBreakTable[] = {
514 { "break-all", WordBreak::BREAK_ALL },
515 { "break-word", WordBreak::BREAK_WORD },
516 { "normal", WordBreak::NORMAL },
517 };
518 auto wordBreakIter = BinarySearchFindIndex(wordBreakTable, ArraySize(wordBreakTable), wordBreak.c_str());
519 return wordBreakIter != -1 ? wordBreakTable[wordBreakIter].value : WordBreak::BREAK_WORD;
520 }
521
FontWeightToString(const FontWeight & fontWeight)522 inline std::string FontWeightToString(const FontWeight& fontWeight)
523 {
524 static const LinearEnumMapNode<FontWeight, std::string> fontWeightTable[] = {
525 { FontWeight::W100, "100" },
526 { FontWeight::W200, "200" },
527 { FontWeight::W300, "300" },
528 { FontWeight::W400, "400" },
529 { FontWeight::W500, "500" },
530 { FontWeight::W600, "600" },
531 { FontWeight::W700, "700" },
532 { FontWeight::W800, "800" },
533 { FontWeight::W900, "900" },
534 { FontWeight::BOLD, "bold" },
535 { FontWeight::BOLDER, "bolder" },
536 { FontWeight::LIGHTER, "lighter" },
537 { FontWeight::MEDIUM, "medium" },
538 { FontWeight::NORMAL, "normal" },
539 { FontWeight::REGULAR, "regular" },
540 };
541 auto weightIter = BinarySearchFindIndex(fontWeightTable, ArraySize(fontWeightTable), fontWeight);
542 return weightIter != -1 ? fontWeightTable[weightIter].value : "";
543 }
544 } // namespace StringUtils
545 } // namespace OHOS::Ace
546
547 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_TEXT_STYLE_H
548