• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 <bitset>
20 #include <cstdint>
21 #include <optional>
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25 
26 #include "advanced_text_style.h"
27 #include "ui/base/referenced.h"
28 #include "ui/base/utils/utils.h"
29 
30 #include "base/geometry/dimension.h"
31 #include "base/utils/linear_map.h"
32 #include "core/components/common/layout/constants.h"
33 #include "core/components/common/properties/color.h"
34 #include "core/components/common/properties/shadow.h"
35 #include "core/components_ng/base/inspector_filter.h"
36 #include "core/components_ng/property/border_property.h"
37 #include "core/pipeline/base/render_component.h"
38 #include "frameworks/core/components/common/properties/decoration.h"
39 #include "frameworks/core/components_ng/pattern/symbol/symbol_effect_options.h"
40 
41 namespace OHOS::Ace {
42 // The normal weight is W400, the larger the number after W, the thicker the font will be.
43 // BOLD is equal to W700 and NORMAL is equal to W400, lighter is W100, BOLDER is W900.
44 enum class FontWeight {
45     W100 = 0,
46     W200,
47     W300,
48     W400,
49     W500,
50     W600,
51     W700,
52     W800,
53     W900,
54     BOLD,
55     NORMAL,
56     BOLDER,
57     LIGHTER,
58     MEDIUM,
59     REGULAR,
60 };
61 namespace {
62 const FontWeight FONT_WEIGHT_CONVERT_MAP[] = {
63     FontWeight::W100,
64     FontWeight::W200,
65     FontWeight::W300,
66     FontWeight::W400,
67     FontWeight::W500,
68     FontWeight::W600,
69     FontWeight::W700,
70     FontWeight::W800,
71     FontWeight::W900,
72     FontWeight::W700,       // FontWeight::BOLD
73     FontWeight::W400,       // FontWeight::NORMAL
74     FontWeight::W900,       // FontWeight::BOLDER,
75     FontWeight::W100,       // FontWeight::LIGHTER
76     FontWeight::W500,       // FontWeight::MEDIUM
77     FontWeight::W400,       // FontWeight::REGULAR
78 };
ConvertFontWeight(FontWeight fontWeight)79 inline FontWeight ConvertFontWeight(FontWeight fontWeight)
80 {
81     int index = static_cast<int>(fontWeight);
82     if (index >= 0 && index < static_cast<int>(sizeof(FONT_WEIGHT_CONVERT_MAP) / sizeof(FontWeight))) {
83         return FONT_WEIGHT_CONVERT_MAP[index];
84     }
85     // 返回默认值,例如 FontWeight::W400
86     return FontWeight::W400;
87 }
88 } // namespace
89 
90 struct DimensionWithActual {
91     constexpr DimensionWithActual() = default;
DimensionWithActualDimensionWithActual92     explicit DimensionWithActual(const Dimension& variable, float actual) : value(variable), actualValue(actual) {}
93     bool operator==(const DimensionWithActual& rhs) const
94     {
95         return NearEqual(value, rhs.value) && NearEqual(actualValue, rhs.actualValue, 0.00001f);
96     }
97 
ToStringDimensionWithActual98     std::string ToString()
99     {
100         std::stringstream ss;
101         ss << "value: " << value.ToString();
102         ss << " actualValue: " << std::to_string(actualValue);
103         return ss.str();
104     }
105 
ResetDimensionWithActual106     void Reset()
107     {
108         value.Reset();
109         actualValue = 0.0f;
110     }
111 
112     Dimension value;
113     float actualValue = 0.0f;
114 };
115 
116 constexpr uint32_t DEFAULT_MAX_FONT_FAMILY_LENGTH = Infinity<uint32_t>();
117 
118 enum class FontStyle {
119     NORMAL,
120     ITALIC,
121     NONE
122 };
123 
124 enum class SuperscriptStyle {
125     NORMAL,
126     SUPERSCRIPT,
127     SUBSCRIPT,
128     NONE
129 };
130 
131 namespace StringUtils {
ToString(const FontStyle & fontStyle)132 inline std::string ToString(const FontStyle& fontStyle)
133 {
134     static const LinearEnumMapNode<FontStyle, std::string> table[] = {
135         { FontStyle::NORMAL, "NORMAL" },
136         { FontStyle::ITALIC, "ITALIC" },
137     };
138     auto iter = BinarySearchFindIndex(table, ArraySize(table), fontStyle);
139     return iter != -1 ? table[iter].value : "";
140 }
141 
ToStringNDK(const FontStyle & fontStyle)142 inline std::string ToStringNDK(const FontStyle& fontStyle)
143 {
144     static const LinearEnumMapNode<FontStyle, std::string> table[] = {
145         { FontStyle::NORMAL, "normal" },
146         { FontStyle::ITALIC, "italic" },
147     };
148     auto iter = BinarySearchFindIndex(table, ArraySize(table), fontStyle);
149     return iter != -1 ? table[iter].value : "";
150 }
151 } // namespace StringUtils
152 
153 enum class TextBaseline {
154     ALPHABETIC,
155     IDEOGRAPHIC,
156     TOP,
157     BOTTOM,
158     MIDDLE,
159     HANGING,
160 };
161 
162 namespace StringUtils {
ToString(const TextBaseline & textBaseline)163 inline std::string ToString(const TextBaseline& textBaseline)
164 {
165     static const LinearEnumMapNode<TextBaseline, std::string> table[] = {
166         { TextBaseline::ALPHABETIC, "ALPHABETIC" },
167         { TextBaseline::IDEOGRAPHIC, "IDEOGRAPHIC" },
168         { TextBaseline::TOP, "TOP" },
169         { TextBaseline::BOTTOM, "BOTTOM" },
170         { TextBaseline::MIDDLE, "MIDDLE" },
171         { TextBaseline::HANGING, "HANGING" },
172     };
173     auto iter = BinarySearchFindIndex(table, ArraySize(table), textBaseline);
174     return iter != -1 ? table[iter].value : "";
175 }
176 } // namespace StringUtils
177 
178 enum class TextCase {
179     NORMAL = 0,
180     LOWERCASE,
181     UPPERCASE,
182 };
183 
184 namespace StringUtils {
ToString(const TextCase & textCase)185 inline std::string ToString(const TextCase& textCase)
186 {
187     static const LinearEnumMapNode<TextCase, std::string> table[] = {
188         { TextCase::NORMAL, "NORMAL" },
189         { TextCase::LOWERCASE, "LOWERCASE" },
190         { TextCase::UPPERCASE, "UPPERCASE" },
191     };
192     auto iter = BinarySearchFindIndex(table, ArraySize(table), textCase);
193     return iter != -1 ? table[iter].value : "";
194 }
195 } // namespace StringUtils
196 
197 enum class EllipsisMode {
198     HEAD,
199     MIDDLE,
200     TAIL,
201 };
202 
203 enum class TextFlipDirection {
204     DOWN = 0,
205     UP,
206 };
207 namespace StringUtils {
ToString(const TextFlipDirection & textFlipDirection)208 inline std::string ToString(const TextFlipDirection& textFlipDirection)
209 {
210     static const LinearEnumMapNode<TextFlipDirection, std::string> table[] = {
211         { TextFlipDirection::DOWN, "down" },
212         { TextFlipDirection::UP, "up" },
213     };
214     auto iter = BinarySearchFindIndex(table, ArraySize(table), textFlipDirection);
215     return iter != -1 ? table[iter].value : "";
216 }
217 } // namespace StringUtils
218 
219 namespace StringUtils {
ToString(const EllipsisMode & ellipsisMode)220 inline std::string ToString(const EllipsisMode& ellipsisMode)
221 {
222     static const LinearEnumMapNode<EllipsisMode, std::string> table[] = {
223         { EllipsisMode::HEAD, "HEAD" },
224         { EllipsisMode::MIDDLE, "MIDDLE" },
225         { EllipsisMode::TAIL, "TAIL" },
226     };
227     auto iter = BinarySearchFindIndex(table, ArraySize(table), ellipsisMode);
228     return iter != -1 ? table[iter].value : "";
229 }
230 } // namespace StringUtils
231 
232 enum class WordBreak { NORMAL = 0, BREAK_ALL, BREAK_WORD, HYPHENATION };
233 extern const std::vector<WordBreak> WORD_BREAK_TYPES;
234 extern const std::vector<LineBreakStrategy> LINE_BREAK_STRATEGY_TYPES;
235 namespace StringUtils {
ToString(const WordBreak & wordBreak)236 inline std::string ToString(const WordBreak& wordBreak)
237 {
238     static const LinearEnumMapNode<WordBreak, std::string> table[] = {
239         { WordBreak::NORMAL, "NORMAL" },
240         { WordBreak::BREAK_ALL, "BREAK_ALL" },
241         { WordBreak::BREAK_WORD, "BREAK_WORD" },
242         { WordBreak::HYPHENATION, "HYPHENATION" },
243     };
244     auto iter = BinarySearchFindIndex(table, ArraySize(table), wordBreak);
245     return iter != -1 ? table[iter].value : "";
246 }
247 } // namespace StringUtils
248 
249 /// Where to vertically align the placeholder relative to the surrounding text.
250 enum class PlaceholderAlignment {
251     /// Match the baseline of the placeholder with the baseline.
252     BASELINE,
253 
254     /// Align the bottom edge of the placeholder with the baseline such that the
255     /// placeholder sits on top of the baseline.
256     ABOVEBASELINE,
257 
258     /// Align the top edge of the placeholder with the baseline specified in
259     /// such that the placeholder hangs below the baseline.
260     BELOWBASELINE,
261 
262     /// Align the top edge of the placeholder with the top edge of the font.
263     /// When the placeholder is very tall, the extra space will hang from
264     /// the top and extend through the bottom of the line.
265     TOP,
266 
267     /// Align the bottom edge of the placeholder with the top edge of the font.
268     /// When the placeholder is very tall, the extra space will rise from
269     /// the bottom and extend through the top of the line.
270     BOTTOM,
271 
272     /// Align the middle of the placeholder with the middle of the text. When the
273     /// placeholder is very tall, the extra space will grow equally from
274     /// the top and bottom of the line.
275     MIDDLE,
276 
277     /// Same alignment as Text.
278     FOLLOW_PARAGRAPH,
279 };
280 
281 namespace StringUtils {
ToString(const PlaceholderAlignment & placeholderAlignment)282 inline std::string ToString(const PlaceholderAlignment& placeholderAlignment)
283 {
284     static const LinearEnumMapNode<PlaceholderAlignment, std::string> table[] = {
285         { PlaceholderAlignment::BASELINE, "BASELINE" },
286         { PlaceholderAlignment::ABOVEBASELINE, "ABOVEBASELINE" },
287         { PlaceholderAlignment::BELOWBASELINE, "BELOWBASELINE" },
288         { PlaceholderAlignment::TOP, "TOP" },
289         { PlaceholderAlignment::BOTTOM, "BOTTOM" },
290         { PlaceholderAlignment::MIDDLE, "MIDDLE" },
291         { PlaceholderAlignment::FOLLOW_PARAGRAPH, "FOLLOW_PARAGRAPH" },
292     };
293     auto iter = BinarySearchFindIndex(table, ArraySize(table), placeholderAlignment);
294     return iter != -1 ? table[iter].value : "";
295 }
296 } // namespace StringUtils
297 
298 enum class SpanItemType { NORMAL = 0, IMAGE = 1, CustomSpan = 2, SYMBOL = 3, PLACEHOLDER = 4 };
299 
300 namespace StringUtils {
ToString(const SpanItemType & spanItemType)301 inline std::string ToString(const SpanItemType& spanItemType)
302 {
303     static const LinearEnumMapNode<SpanItemType, std::string> table[] = {
304         { SpanItemType::NORMAL, "NORMAL" },
305         { SpanItemType::IMAGE, "IMAGE" },
306         { SpanItemType::CustomSpan, "CustomSpan" },
307         { SpanItemType::SYMBOL, "SYMBOL" },
308         { SpanItemType::PLACEHOLDER, "PLACEHOLDER" },
309     };
310     auto iter = BinarySearchFindIndex(table, ArraySize(table), spanItemType);
311     return iter != -1 ? table[iter].value : "";
312 }
313 }
314 
315 struct TextSizeGroup {
316     Dimension fontSize = 14.0_px;
317     uint32_t maxLines = INT32_MAX;
318     TextOverflow textOverflow = TextOverflow::CLIP;
319 };
320 
321 /// Placeholder properties
322 struct PlaceholderRun {
323     /// Placeholder's width
324     float width = 0.0f;
325 
326     /// Placeholder's height
327     float height = 0.0f;
328 
329     /// Vertically alignment the placeholder relative to the surrounding text.
330     PlaceholderAlignment alignment = PlaceholderAlignment::BOTTOM;
331 
332     /// The placeholder with the baseline styles
333     TextBaseline baseline = TextBaseline::ALPHABETIC;
334 
335     /// The baseline offset
336     float baseline_offset = 0.0f;
337 
338     bool operator==(const PlaceholderRun& value) const
339     {
340         return width == value.width && height == value.height && alignment == value.alignment &&
341                baseline == value.baseline && baseline_offset == value.baseline_offset;
342     }
343 
344     bool operator!=(const PlaceholderRun& value) const
345     {
346         return !(value == *this);
347     }
348 };
349 
350 enum class BorderRadiusIndex {
351     TOPLEFT = 0,
352     TOPRIGHT = 1,
353     BOTTOMLEFT = 2,
354     BOTTOMRIGHT = 3
355 };
356 
357 struct TextBackgroundStyle {
358     std::optional<Color> backgroundColor;
359     std::optional<NG::BorderRadiusProperty> backgroundRadius;
360     int32_t groupId = 0;
361     bool needCompareGroupId = true;
362 
UpdateColorByResourceIdTextBackgroundStyle363     void UpdateColorByResourceId()
364     {
365         CHECK_NULL_VOID(backgroundColor);
366         backgroundColor->UpdateColorByResourceId();
367     }
368 
369     static void ToJsonValue(std::unique_ptr<JsonValue>& json, const std::optional<TextBackgroundStyle>& style,
370         const NG::InspectorFilter& filter);
371 
372     bool operator==(const TextBackgroundStyle& value) const
373     {
374         // Only compare groupId if both styles require it.
375         bool bothNeedCompareGroupId = needCompareGroupId && value.needCompareGroupId;
376         return backgroundColor == value.backgroundColor && backgroundRadius == value.backgroundRadius &&
377                (!bothNeedCompareGroupId || groupId == value.groupId);
378     }
379 
AddResourceTextBackgroundStyle380     void AddResource(const std::string& key, const RefPtr<ResourceObject>& resObj,
381         std::function<void(const RefPtr<ResourceObject>&, TextBackgroundStyle&)>&& updateFunc)
382     {
383         if (resObj == nullptr || !updateFunc) {
384             return;
385         }
386         textBackgroundStyleResMap_[key] = { resObj, std::move(updateFunc) };
387     }
388 
ReloadResourcesTextBackgroundStyle389     void ReloadResources()
390     {
391         for (const auto& [key, resourceUpdater] : textBackgroundStyleResMap_) {
392             resourceUpdater.updateFunc(resourceUpdater.obj, *this);
393         }
394     }
395 
396     struct ResourceUpdater {
397         RefPtr<ResourceObject> obj;
398         std::function<void(const RefPtr<ResourceObject>&, TextBackgroundStyle&)> updateFunc;
399     };
400 
401     std::unordered_map<std::string, ResourceUpdater> textBackgroundStyleResMap_;
402 };
403 
404 enum class TextStyleAttribute {
405     RE_CREATE = -1,
406     FONT_SIZE = 0,
407     FONT_WEIGHT = 1,
408     FONT_STYLE = 3,
409     FONT_FAMILIES = 4,
410     LETTER_SPACING = 5,
411     WORD_SPACING = 6,
412     HEIGHT_ONLY = 7,
413     HEIGHT_SCALE = 8,
414     FONT_FEATURES = 9,
415     FONT_VARIATIONS = 10,
416     BASELINE_SHIFT = 11,
417 
418     DECRATION = 12,
419     DECORATION_COLOR = 13,
420     DECORATION_STYLE = 14,
421     DECORATION_THICKNESS_SCALE = 15,
422     BACKGROUND_RECT = 16,
423     STYLE_ID = 17,
424     FONT_COLOR = 18,
425     SHADOWS = 19,
426     HALF_LEADING = 20,
427     FOREGROUND_BRUSH = 21,
428     MAX_TEXT_STYLE
429 };
430 
431 enum class ParagraphStyleAttribute {
432     RE_CREATE = -1,
433     FONT_SIZE = 0,
434     DIRECTION = 1,
435     MAXLINES = 2,
436 
437     HALF_LEADING = 8,
438     BREAKSTRAGY = 19,
439 
440     WORD_BREAKTYPE = 20,
441     ELLIPSIS = 21,
442     ELLIPSE_MODAL = 22,
443     TEXT_ALIGN = 23,
444     SPACING = 24,
445     SPACING_IS_END = 25,
446     TEXT_HEIGHT_BEHAVIOR = 26,
447 
448     MAX_TEXT_STYLE
449 };
450 
451 enum class SymbolStyleAttribute {
452     RE_CREATE = -1,
453     // EffectStrategy
454     EFFECT_STRATEGY = 0,
455     // SymbolEffectOptions
456     ANIMATION_MODE = 1,
457     ANIMATION_START = 2,
458     COMMONSUB_TYPE = 3,
459     // RenderColors(SymbolColorList)
460     COLOR_LIST = 4,
461     // RenderStrategy
462     RENDER_MODE = 5,
463     GRADIENT_COLOR = 6,
464     SYMBOL_SHADOW = 7,
465     MAX_SYMBOL_STYLE,
466 };
467 
468 // For textStyle
469 #define ACE_DEFINE_TEXT_STYLE_FUNC(name, type, changeflag)           \
470 public:                                                              \
471     const type& Get##name() const                                    \
472     {                                                                \
473         return prop##name##_;                                        \
474     }                                                                \
475     void Set##name(const type& newValue)                             \
476     {                                                                \
477         if (NearEqual(prop##name##_, newValue)) {                    \
478             return;                                                  \
479         }                                                            \
480         auto flag = static_cast<int32_t>(changeflag);                \
481         if (GreatOrEqual(flag, 0)) {                                 \
482             reLayoutTextStyleBitmap_.set(static_cast<size_t>(flag)); \
483         } else {                                                     \
484             needReCreateParagraph_ = true;                           \
485         }                                                            \
486         prop##name##_ = newValue;                                    \
487     }                                                                \
488     void Set##name(const std::optional<type>& value)                 \
489     {                                                                \
490         if (value.has_value()) {                                     \
491             Set##name(value.value());                                \
492         }                                                            \
493     }
494 
495 #define ACE_DEFINE_TEXT_STYLE(name, type, changeflag)  \
496     ACE_DEFINE_TEXT_STYLE_FUNC(name, type, changeflag) \
497 private:                                               \
498     type prop##name##_;
499 
500 #define ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(name, type, value, changeflag) \
501     ACE_DEFINE_TEXT_STYLE_FUNC(name, type, changeflag)                          \
502                                                                                 \
503 private:                                                                        \
504     type prop##name##_ = value;
505 // For textStyle
506 #define ACE_DEFINE_TEXT_DIMENSION_STYLE_FUNC(name, changeflag)                                                \
507 public:                                                                                                       \
508     const Dimension& Get##name() const                                                                        \
509     {                                                                                                         \
510         return prop##name##_.value;                                                                           \
511     }                                                                                                         \
512     void Set##name(const Dimension& value)                                                                    \
513     {                                                                                                         \
514         auto actualValue = value.ConvertToPxDistribute(GetMinFontScale(), GetMaxFontScale(), IsAllowScale()); \
515         auto newValue = DimensionWithActual(value, static_cast<float>(actualValue));                          \
516         if (NearEqual(prop##name##_, newValue)) {                                                             \
517             return;                                                                                           \
518         }                                                                                                     \
519         auto flag = static_cast<int32_t>(changeflag);                                                         \
520         if (GreatOrEqual(flag, 0)) {                                                                          \
521             reLayoutTextStyleBitmap_.set(flag);                                                               \
522         } else {                                                                                              \
523             needReCreateParagraph_ = true;                                                                    \
524         }                                                                                                     \
525         prop##name##_ = newValue;                                                                             \
526     }
527 
528 // For textStyle
529 #define ACE_DEFINE_TEXT_DIMENSION_STYLE(name, changeflag)  \
530     ACE_DEFINE_TEXT_DIMENSION_STYLE_FUNC(name, changeflag) \
531                                                            \
532 private:                                                   \
533     DimensionWithActual prop##name##_;
534 // For textStyle
535 #define ACE_DEFINE_TEXT_DIMENSION_STYLE_WITH_DEFAULT_VALUE(name, defaultValue, actualDefaultValue, changeflag) \
536     ACE_DEFINE_TEXT_DIMENSION_STYLE_FUNC(name, changeflag)                                                     \
537                                                                                                                \
538 private:                                                                                                       \
539     DimensionWithActual prop##name##_ { defaultValue, actualDefaultValue };
540 
541 #define ACE_DEFINE_TEXT_STYLE_OPTIONAL_TYPE(name, type, changeflag)   \
542 public:                                                               \
543     const std::optional<type>& Get##name() const                      \
544     {                                                                 \
545         return prop##name##_;                                         \
546     }                                                                 \
547     void Set##name(const type& newValue)                              \
548     {                                                                 \
549         if (prop##name##_.has_value()) {                              \
550             if (NearEqual(prop##name##_.value(), newValue)) {         \
551                 return;                                               \
552             }                                                         \
553         }                                                             \
554         auto flag = static_cast<int32_t>(changeflag);                 \
555         if (GreatOrEqual(flag, 0)) {                                  \
556             reLayoutTextStyleBitmap_.set(flag);                       \
557         } else {                                                      \
558             needReCreateParagraph_ = true;                            \
559         }                                                             \
560         prop##name##_ = newValue;                                     \
561     }                                                                 \
562     void Set##name(const std::optional<type> newValue)                \
563     {                                                                 \
564         if (!prop##name##_.has_value() && !newValue.has_value()) {    \
565             return;                                                   \
566         }                                                             \
567         if (prop##name##_.has_value() && newValue.has_value()) {      \
568             if (NearEqual(prop##name##_.value(), newValue.value())) { \
569                 return;                                               \
570             }                                                         \
571         }                                                             \
572         auto flag = static_cast<int32_t>(changeflag);                 \
573         if (GreatOrEqual(flag, 0)) {                                  \
574             reLayoutTextStyleBitmap_.set(flag);                       \
575         } else {                                                      \
576             needReCreateParagraph_ = true;                            \
577         }                                                             \
578         prop##name##_ = newValue;                                     \
579     }                                                                 \
580                                                                       \
581 private:                                                              \
582     std::optional<type> prop##name##_;
583 
584 // For paragraphStyle
585 #define ACE_DEFINE_PARAGRAPH_STYLE(name, type, changeflag)                \
586 public:                                                                   \
587     const type& Get##name() const                                         \
588     {                                                                     \
589         return prop##name##_;                                             \
590     }                                                                     \
591     void Set##name(const type& newValue)                                  \
592     {                                                                     \
593         if (NearEqual(prop##name##_, newValue)) {                         \
594             return;                                                       \
595         }                                                                 \
596         auto flag = static_cast<int32_t>(changeflag);                     \
597         if (GreatOrEqual(flag, 0)) {                                      \
598             reLayoutParagraphStyleBitmap_.set(static_cast<size_t>(flag)); \
599         } else {                                                          \
600             needReCreateParagraph_ = true;                                \
601         }                                                                 \
602         prop##name##_ = newValue;                                         \
603     }                                                                     \
604                                                                           \
605 private:                                                                  \
606     type prop##name##_;
607 
608 #define ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(name, type, initValue, changeflag) \
609 public:                                                                                  \
610     const type& Get##name() const                                                        \
611     {                                                                                    \
612         return prop##name##_;                                                            \
613     }                                                                                    \
614     void Set##name(const type& newValue)                                                 \
615     {                                                                                    \
616         if (NearEqual(prop##name##_, newValue)) {                                        \
617             return;                                                                      \
618         }                                                                                \
619         auto flag = static_cast<int32_t>(changeflag);                                    \
620         if (GreatOrEqual(flag, 0)) {                                                     \
621             reLayoutParagraphStyleBitmap_.set(static_cast<size_t>(flag));                \
622         } else {                                                                         \
623             needReCreateParagraph_ = true;                                               \
624         }                                                                                \
625         prop##name##_ = newValue;                                                        \
626     }                                                                                    \
627     void Set##name(const std::optional<type>& newValue)                                  \
628     {                                                                                    \
629         if (newValue.has_value()) {                                                      \
630             Set##name(newValue.value());                                                 \
631         }                                                                                \
632     }                                                                                    \
633                                                                                          \
634 private:                                                                                 \
635     type prop##name##_ = initValue;
636 
637 // For symbol
638 #define ACE_DEFINE_SYMBOL_STYLE(name, type, changeflag) \
639 public:                                                 \
640     const type& Get##name() const                       \
641     {                                                   \
642         return prop##name##_;                           \
643     }                                                   \
644     void Set##name(const type& newValue)                \
645     {                                                   \
646         if (NearEqual(prop##name##_, newValue)) {       \
647             return;                                     \
648         }                                               \
649         auto flag = static_cast<int32_t>(changeflag);   \
650         if (GreatOrEqual(flag, 0)) {                    \
651             reLayoutSymbolStyleBitmap_.set(flag);       \
652         } else {                                        \
653             needReCreateParagraph_ = true;              \
654         }                                               \
655         prop##name##_ = newValue;                       \
656     }                                                   \
657                                                         \
658 private:                                                \
659     type prop##name##_;
660 
661 #define ACE_DEFINE_SYMBOL_STYLE_WITH_DEFAULT_VALUE(name, type, value, changeflag) \
662 public:                                                                           \
663     const type& Get##name() const                                                 \
664     {                                                                             \
665         return prop##name##_;                                                     \
666     }                                                                             \
667     void Set##name(const type& newValue)                                          \
668     {                                                                             \
669         if (NearEqual(prop##name##_, newValue)) {                                 \
670             return;                                                               \
671         }                                                                         \
672         auto flag = static_cast<int32_t>(changeflag);                             \
673         if (GreatOrEqual(flag, 0)) {                                              \
674             reLayoutSymbolStyleBitmap_.set(flag);                                 \
675         } else {                                                                  \
676             needReCreateParagraph_ = true;                                        \
677         }                                                                         \
678         prop##name##_ = newValue;                                                 \
679     }                                                                             \
680                                                                                   \
681 private:                                                                          \
682     type prop##name##_ = value;
683 
684 #define ACE_DEFINE_ADVANCED_TEXT_STYLE_OPTIONAL_TYPE(name, type)                     \
685 public:                                                                              \
686     std::optional<type> Get##name() const                                            \
687     {                                                                                \
688         CHECK_NULL_RETURN(advancedTextStyle_, std::nullopt);                         \
689         return advancedTextStyle_->Get##name();                                      \
690     }                                                                                \
691     void Set##name(const type& newValue)                                             \
692     {                                                                                \
693         if (!advancedTextStyle_) {                                                   \
694             advancedTextStyle_ = AceType::MakeRefPtr<AdvancedTextStyle>();           \
695         }                                                                            \
696         CHECK_NULL_VOID(advancedTextStyle_);                                         \
697         advancedTextStyle_->Set##name(newValue);                                     \
698     }                                                                                \
699     void Set##name(const std::optional<type> newValue)                               \
700     {                                                                                \
701         if (!advancedTextStyle_ && !newValue.has_value()) {                          \
702             return;                                                                  \
703         }                                                                            \
704         if (!advancedTextStyle_) {                                                   \
705             advancedTextStyle_ = AceType::MakeRefPtr<AdvancedTextStyle>();           \
706         }                                                                            \
707         CHECK_NULL_VOID(advancedTextStyle_);                                         \
708         if (!advancedTextStyle_->Get##name().has_value() && !newValue.has_value()) { \
709             return;                                                                  \
710         }                                                                            \
711         advancedTextStyle_->Set##name(newValue);                                     \
712     }
713 
714 #define ACE_DEFINE_ADVANCED_TEXT_STYLE_OPTIONAL_TYPE_WITH_FLAG(name, type, changeflag)  \
715     std::optional<type> Get##name() const                                               \
716     {                                                                                   \
717         CHECK_NULL_RETURN(advancedTextStyle_, std::nullopt);                            \
718         return advancedTextStyle_->Get##name();                                         \
719     }                                                                                   \
720     void Set##name(const type& newValue)                                                \
721     {                                                                                   \
722         if (!advancedTextStyle_) {                                                      \
723             advancedTextStyle_ = AceType::MakeRefPtr<AdvancedTextStyle>();              \
724         }                                                                               \
725         CHECK_NULL_VOID(advancedTextStyle_);                                            \
726         if (Has##name()) {                                                              \
727             if (NearEqual(advancedTextStyle_->Get##name().value(), newValue)) {         \
728                 return;                                                                 \
729             }                                                                           \
730         }                                                                               \
731         advancedTextStyle_->Set##name(newValue);                                        \
732         auto flag = static_cast<int32_t>(changeflag);                                   \
733         if (GreatOrEqual(flag, 0)) {                                                    \
734             reLayoutParagraphStyleBitmap_.set(flag);                                    \
735         } else {                                                                        \
736             needReCreateParagraph_ = true;                                              \
737         }                                                                               \
738     }                                                                                   \
739     void Set##name(const std::optional<type> newValue)                                  \
740     {                                                                                   \
741         if (!advancedTextStyle_ && !newValue.has_value()) {                             \
742             return;                                                                     \
743         }                                                                               \
744         if (!advancedTextStyle_) {                                                      \
745             advancedTextStyle_ = AceType::MakeRefPtr<AdvancedTextStyle>();              \
746         }                                                                               \
747         CHECK_NULL_VOID(advancedTextStyle_);                                            \
748         if (!advancedTextStyle_->Get##name().has_value() && !newValue.has_value()) {    \
749             return;                                                                     \
750         }                                                                               \
751         if (Has##name() && newValue.has_value()) {                                      \
752             if (NearEqual(advancedTextStyle_->Get##name().value(), newValue.value())) { \
753                 return;                                                                 \
754             }                                                                           \
755         }                                                                               \
756         advancedTextStyle_->Set##name(newValue);                                        \
757         auto flag = static_cast<int32_t>(changeflag);                                   \
758         if (GreatOrEqual(flag, 0)) {                                                    \
759             reLayoutParagraphStyleBitmap_.set(flag);                                    \
760         } else {                                                                        \
761             needReCreateParagraph_ = true;                                              \
762         }                                                                               \
763     }                                                                                   \
764     bool Has##name() const                                                              \
765     {                                                                                   \
766         CHECK_NULL_RETURN(advancedTextStyle_, false);                                   \
767         return advancedTextStyle_->Get##name().has_value();                             \
768     }                                                                                   \
769     const type& Get##name##Value(const type& defaultValue) const                        \
770     {                                                                                   \
771         if (!Has##name()) {                                                             \
772             return defaultValue;                                                        \
773         }                                                                               \
774         return advancedTextStyle_->Get##name().value();                                 \
775     }
776 
777 #define ACE_DEFINE_SYMBOL_TEXT_STYLE_OPTIONAL_TYPE(name, type)                        \
778     std::optional<type> Get##name() const                                             \
779     {                                                                                 \
780         CHECK_NULL_RETURN(symbolTextStyle_, std::nullopt);                            \
781         return symbolTextStyle_->Get##name();                                         \
782     }                                                                                 \
783     void Set##name(const type& newValue)                                              \
784     {                                                                                 \
785         if (!symbolTextStyle_) {                                                      \
786             symbolTextStyle_ = AceType::MakeRefPtr<SymbolTextStyle>();                \
787         }                                                                             \
788         CHECK_NULL_VOID(symbolTextStyle_);                                            \
789         if (Has##name()) {                                                            \
790             if (NearEqual(symbolTextStyle_->Get##name().value(), newValue)) {         \
791                 return;                                                               \
792             }                                                                         \
793         }                                                                             \
794         symbolTextStyle_->Set##name(newValue);                                        \
795     }                                                                                 \
796     void Set##name(const std::optional<type> newValue)                                \
797     {                                                                                 \
798         if (!symbolTextStyle_ && !newValue.has_value()) {                             \
799             return;                                                                   \
800         }                                                                             \
801         if (!symbolTextStyle_) {                                                      \
802             symbolTextStyle_ = AceType::MakeRefPtr<SymbolTextStyle>();                \
803         }                                                                             \
804         CHECK_NULL_VOID(symbolTextStyle_);                                            \
805         if (!symbolTextStyle_->Get##name().has_value() && !newValue.has_value()) {    \
806             return;                                                                   \
807         }                                                                             \
808         if (Has##name() && newValue.has_value()) {                                    \
809             if (NearEqual(symbolTextStyle_->Get##name().value(), newValue.value())) { \
810                 return;                                                               \
811             }                                                                         \
812         }                                                                             \
813         symbolTextStyle_->Set##name(newValue);                                        \
814     }                                                                                 \
815     bool Has##name() const                                                            \
816     {                                                                                 \
817         CHECK_NULL_RETURN(symbolTextStyle_, false);                                   \
818         return symbolTextStyle_->Get##name().has_value();                             \
819     }                                                                                 \
820     const type& Get##name##Value(const type& defaultValue) const                      \
821     {                                                                                 \
822         if (!Has##name()) {                                                           \
823             return defaultValue;                                                      \
824         }                                                                             \
825         return symbolTextStyle_->Get##name().value();                                 \
826     }                                                                                 \
827     void Set##name##WithoutMark(const std::optional<type> newValue)                   \
828     {                                                                                 \
829         if (!symbolTextStyle_ && !newValue.has_value()) {                             \
830             return;                                                                   \
831         }                                                                             \
832         if (!symbolTextStyle_) {                                                      \
833             symbolTextStyle_ = AceType::MakeRefPtr<SymbolTextStyle>();                \
834         }                                                                             \
835         CHECK_NULL_VOID(symbolTextStyle_);                                            \
836         if (!symbolTextStyle_->Get##name().has_value() && !newValue.has_value()) {    \
837             return;                                                                   \
838         }                                                                             \
839         if (Has##name() && newValue.has_value()) {                                    \
840             if (NearEqual(symbolTextStyle_->Get##name().value(), newValue.value())) { \
841                 return;                                                               \
842             }                                                                         \
843         }                                                                             \
844         symbolTextStyle_->Set##name(newValue);                                        \
845     }
846 
847 class ACE_EXPORT TextStyle final {
848 public:
849     TextStyle() = default;
850     TextStyle(const std::vector<std::string>& fontFamilies, double fontSize, FontWeight fontWeight, FontStyle fontStyle,
851         const Color& textColor);
TextStyle(double fontSize)852     TextStyle(double fontSize)
853     {
854         SetFontSize(Dimension(fontSize));
855     }
TextStyle(const Color & textColor)856     TextStyle(const Color& textColor) : propTextColor_(textColor) {}
857     ~TextStyle() = default;
858 
859     bool operator==(const TextStyle& rhs) const;
860     bool operator!=(const TextStyle& rhs) const;
861 
862     static void ToJsonValue(std::unique_ptr<JsonValue>& json, const std::optional<TextStyle>& style,
863         const NG::InspectorFilter& filter);
864 
865     static std::string GetDeclarationString(
866         const std::optional<Color>& color, const std::vector<TextDecoration>& textDecorations,
867         const std::optional<TextDecorationStyle>& textDecorationStyle, const std::optional<float>& lineThicknessScale);
868 
869     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(
870         TextBaseline, TextBaseline, TextBaseline::ALPHABETIC, TextStyleAttribute::RE_CREATE);
871     ACE_DEFINE_TEXT_DIMENSION_STYLE(BaselineOffset, TextStyleAttribute::BASELINE_SHIFT);
872     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(
873         TextDecoration, std::vector<TextDecoration>, { TextDecoration::NONE }, TextStyleAttribute::DECRATION);
874     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(
875         TextDecorationStyle, TextDecorationStyle, TextDecorationStyle::SOLID, TextStyleAttribute::DECORATION_STYLE);
876     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(
877         TextDecorationColor, Color, Color::BLACK, TextStyleAttribute::DECORATION_COLOR);
878     ACE_DEFINE_TEXT_STYLE(FontFamilies, std::vector<std::string>, TextStyleAttribute::FONT_FAMILIES);
879     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(FontStyle, FontStyle, FontStyle::NORMAL, TextStyleAttribute::FONT_STYLE);
880     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(WhiteSpace, WhiteSpace, WhiteSpace::PRE, TextStyleAttribute::RE_CREATE);
881     ACE_DEFINE_TEXT_STYLE_OPTIONAL_TYPE(MaxFontScale, float, TextStyleAttribute::RE_CREATE);
882     ACE_DEFINE_TEXT_STYLE_OPTIONAL_TYPE(MinFontScale, float, TextStyleAttribute::RE_CREATE);
883     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(VariableFontWeight, int32_t, 0, TextStyleAttribute::FONT_VARIATIONS);
884     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(
885         EnableVariableFontWeight, bool, false, TextStyleAttribute::FONT_VARIATIONS);
886     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(TextColor, Color, Color::BLACK, TextStyleAttribute::FONT_COLOR);
887     ACE_DEFINE_TEXT_DIMENSION_STYLE(WordSpacing, TextStyleAttribute::WORD_SPACING);
888     ACE_DEFINE_TEXT_DIMENSION_STYLE_WITH_DEFAULT_VALUE(
889         TextIndent, Dimension(0.0f, DimensionUnit::PX), 0.0f, TextStyleAttribute::RE_CREATE);
890     ACE_DEFINE_TEXT_DIMENSION_STYLE(LetterSpacing, TextStyleAttribute::LETTER_SPACING);
891     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(MaxLines, uint32_t, UINT32_MAX, ParagraphStyleAttribute::MAXLINES);
892     // Must use with SetAdaptMinFontSize and SetAdaptMaxFontSize.
893     ACE_DEFINE_TEXT_DIMENSION_STYLE(AdaptFontSizeStep, TextStyleAttribute::FONT_SIZE);
894     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(AllowScale, bool, true, TextStyleAttribute::RE_CREATE);
895     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(
896         TextOverflow, TextOverflow, TextOverflow::CLIP, ParagraphStyleAttribute::ELLIPSIS);
897     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(
898         TextAlign, TextAlign, TextAlign::START, ParagraphStyleAttribute::TEXT_ALIGN);
899     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(
900         TextVerticalAlign, VerticalAlign, VerticalAlign::NONE, TextStyleAttribute::RE_CREATE);
901     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(
902         ParagraphVerticalAlign, TextVerticalAlign, TextVerticalAlign::BASELINE, ParagraphStyleAttribute::RE_CREATE);
903     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(
904         WordBreak, WordBreak, WordBreak::BREAK_WORD, ParagraphStyleAttribute::WORD_BREAKTYPE);
905     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(TextCase, TextCase, TextCase::NORMAL, TextStyleAttribute::RE_CREATE);
906     ACE_DEFINE_TEXT_STYLE(TextShadows, std::vector<Shadow>, TextStyleAttribute::SHADOWS);
907     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(HalfLeading, bool, false, TextStyleAttribute::HALF_LEADING);
908     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(
909         IsOnlyBetweenLines, bool, false, ParagraphStyleAttribute::TEXT_HEIGHT_BEHAVIOR);
910     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(
911         EllipsisMode, EllipsisMode, EllipsisMode::TAIL, ParagraphStyleAttribute::RE_CREATE);
912     ACE_DEFINE_TEXT_STYLE(Locale, std::string, TextStyleAttribute::RE_CREATE);
913     ACE_DEFINE_TEXT_STYLE_OPTIONAL_TYPE(TextBackgroundStyle, TextBackgroundStyle, TextStyleAttribute::BACKGROUND_RECT);
914     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(
915         LineBreakStrategy, LineBreakStrategy, LineBreakStrategy::GREEDY, ParagraphStyleAttribute::BREAKSTRAGY);
916     ACE_DEFINE_PARAGRAPH_STYLE(Ellipsis, std::u16string, ParagraphStyleAttribute::ELLIPSIS);
917     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(HeightScale, double, 1.0, TextStyleAttribute::HEIGHT_SCALE);
918     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(
919         TextDirection, TextDirection, TextDirection::AUTO, ParagraphStyleAttribute::DIRECTION);
920     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(HeightOnly, bool, false, TextStyleAttribute::RE_CREATE);
921     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(
922         OptimizeTrailingSpace, bool, false, ParagraphStyleAttribute::RE_CREATE);
923     ACE_DEFINE_PARAGRAPH_STYLE_WITH_DEFAULT_VALUE(EnableAutoSpacing, bool, false, ParagraphStyleAttribute::RE_CREATE);
924     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(
925         LineThicknessScale, float, 1.0f, TextStyleAttribute::DECORATION_THICKNESS_SCALE);
926 
927     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(
928         StrokeWidth, Dimension, Dimension(0.0f, DimensionUnit::PX), TextStyleAttribute::RE_CREATE);
929     ACE_DEFINE_TEXT_STYLE(StrokeColor, Color, TextStyleAttribute::RE_CREATE);
930     ACE_DEFINE_TEXT_STYLE_OPTIONAL_TYPE(ColorShaderStyle, Color, TextStyleAttribute::FOREGROUND_BRUSH);
931     ACE_DEFINE_TEXT_STYLE_WITH_DEFAULT_VALUE(
932         Superscript, SuperscriptStyle, SuperscriptStyle::NORMAL, TextStyleAttribute::RE_CREATE);
933 
934     // for Symbol
935     ACE_DEFINE_SYMBOL_STYLE(RenderColors, std::vector<Color>, SymbolStyleAttribute::COLOR_LIST);
936     ACE_DEFINE_SYMBOL_STYLE(GradientColorProp, std::vector<SymbolGradient>, SymbolStyleAttribute::GRADIENT_COLOR);
937     ACE_DEFINE_SYMBOL_STYLE_WITH_DEFAULT_VALUE(RenderStrategy, int32_t, 0, SymbolStyleAttribute::RENDER_MODE);
938     ACE_DEFINE_SYMBOL_STYLE_WITH_DEFAULT_VALUE(EffectStrategy, int32_t, 0, SymbolStyleAttribute::EFFECT_STRATEGY);
939     ACE_DEFINE_SYMBOL_STYLE_WITH_DEFAULT_VALUE(
940         SymbolType, SymbolType, SymbolType::SYSTEM, SymbolStyleAttribute::RE_CREATE);
941     ACE_DEFINE_ADVANCED_TEXT_STYLE_OPTIONAL_TYPE(Gradient, Gradient);
942 
943 public:
944     ACE_DEFINE_ADVANCED_TEXT_STYLE_OPTIONAL_TYPE_WITH_FLAG(
945         FontForegroudGradiantColor, FontForegroudGradiantColor, TextStyleAttribute::RE_CREATE);
946 
SetFontSize(const Dimension & fontSize)947     void SetFontSize(const Dimension& fontSize)
948     {
949         auto actualValue = fontSize.ConvertToPxDistribute(GetMinFontScale(), GetMaxFontScale(), IsAllowScale());
950         auto newValue = DimensionWithActual(fontSize, static_cast<float>(actualValue));
951         if (NearEqual(newValue, fontSize_)) {
952             return;
953         }
954         fontSize_ = newValue;
955         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::FONT_SIZE));
956         reLayoutParagraphStyleBitmap_.set(static_cast<int32_t>(ParagraphStyleAttribute::FONT_SIZE));
957         if (lineSpacing_.value.IsValid() || hasHeightOverride_) {
958             reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::HEIGHT_SCALE));
959             reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::HEIGHT_ONLY));
960         }
961     }
962 
GetFontSize()963     const Dimension& GetFontSize() const
964     {
965         return fontSize_.value;
966     }
967 
GetFontSizeActual()968     float GetFontSizeActual()
969     {
970         return fontSize_.actualValue;
971     }
972 
ResetTextBaselineOffset()973     void ResetTextBaselineOffset()
974     {
975         propBaselineOffset_.Reset();
976         reLayoutTextStyleBitmap_.reset(static_cast<int32_t>(TextStyleAttribute::BASELINE_SHIFT));
977     }
978 
GetFontWeight()979     FontWeight GetFontWeight() const
980     {
981         return fontWeight_;
982     }
983 
SetFontWeight(FontWeight fontWeight)984     void SetFontWeight(FontWeight fontWeight)
985     {
986         auto before = ConvertFontWeight(fontWeight_);
987         auto after = ConvertFontWeight(fontWeight);
988         fontWeight_ = fontWeight;
989         if (NearEqual(before, after)) {
990             return;
991         }
992         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::FONT_WEIGHT));
993         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::FONT_VARIATIONS));
994     }
995 
SetFontWeight(const std::optional<FontWeight> & fontWeight)996     void SetFontWeight(const std::optional<FontWeight>& fontWeight) const
997     {
998         if (fontWeight.has_value()) {
999             SetFontWeight(fontWeight.value());
1000         }
1001     }
1002 
GetFontFeatures()1003     const std::list<std::pair<std::string, int32_t>>& GetFontFeatures() const
1004     {
1005         return fontFeatures_;
1006     }
1007 
SetFontFeatures(const std::list<std::pair<std::string,int32_t>> & fontFeatures)1008     void SetFontFeatures(const std::list<std::pair<std::string, int32_t>>& fontFeatures)
1009     {
1010         if (NearEqual(fontFeatures, fontFeatures_)) {
1011             return;
1012         }
1013         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::FONT_FEATURES));
1014         fontFeatures_ = fontFeatures;
1015     }
1016 
SetFontFeatures(const std::optional<std::list<std::pair<std::string,int32_t>>> & fontFeatures)1017     void SetFontFeatures(const std::optional<std::list<std::pair<std::string, int32_t>>>& fontFeatures)
1018     {
1019         if (fontFeatures.has_value()) {
1020             SetFontFeatures(fontFeatures.value());
1021         }
1022     }
1023 
GetLineHeight()1024     const Dimension& GetLineHeight() const
1025     {
1026         return lineHeight_.value;
1027     }
1028 
1029     void SetLineHeight(const Dimension& lineHeight, bool hasHeightOverride = true)
1030     {
1031         auto actualValue = lineHeight.ConvertToPxDistribute(GetMinFontScale(), GetMaxFontScale(), IsAllowScale());
1032         auto newValue = DimensionWithActual(lineHeight, static_cast<float>(actualValue));
1033         if (NearEqual(newValue, lineHeight_)) {
1034             return;
1035         }
1036         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::HEIGHT_SCALE));
1037         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::HEIGHT_ONLY));
1038         lineHeight_ = newValue;
1039         hasHeightOverride_ = hasHeightOverride;
1040     }
1041 
SetTextDecoration(TextDecoration value)1042     void SetTextDecoration(TextDecoration value)
1043     {
1044         std::vector<TextDecoration> array { value };
1045         SetTextDecoration(array);
1046     }
1047 
GetTextDecorationFirst()1048     TextDecoration GetTextDecorationFirst() const
1049     {
1050         return GetTextDecoration().size() > 0 ?
1051             GetTextDecoration()[0] : TextDecoration::NONE;
1052     }
1053 
GetParagraphSpacing()1054     const Dimension& GetParagraphSpacing() const
1055     {
1056         return paragraphSpacing_;
1057     }
1058 
SetParagraphSpacing(const Dimension & paragraphSpacing)1059     void SetParagraphSpacing(const Dimension& paragraphSpacing)
1060     {
1061         if (NearEqual(paragraphSpacing_, paragraphSpacing)) {
1062             return;
1063         }
1064         paragraphSpacing_ = paragraphSpacing;
1065         needReCreateParagraph_ = true;
1066     }
1067 
GetLineSpacing()1068     const Dimension& GetLineSpacing() const
1069     {
1070         return lineSpacing_.value;
1071     }
1072 
SetLineSpacing(const Dimension & lineSpacing)1073     void SetLineSpacing(const Dimension& lineSpacing)
1074     {
1075         auto actualValue = lineSpacing.ConvertToPxDistribute(GetMinFontScale(), GetMaxFontScale(), IsAllowScale());
1076         auto newValue = DimensionWithActual(lineSpacing, static_cast<float>(actualValue));
1077         if (NearEqual(newValue, lineSpacing_)) {
1078             return;
1079         }
1080         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::HEIGHT_SCALE));
1081         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::HEIGHT_ONLY));
1082         lineSpacing_ = newValue;
1083     }
1084 
HasHeightOverride()1085     bool HasHeightOverride() const
1086     {
1087         return hasHeightOverride_;
1088     }
1089 
GetAdaptTextSize()1090     bool GetAdaptTextSize() const
1091     {
1092         return adaptTextSize_;
1093     }
1094 
DisableAdaptTextSize()1095     void DisableAdaptTextSize()
1096     {
1097         adaptTextSize_ = false;
1098     }
1099 
SetAdaptTextSize(bool value)1100     void SetAdaptTextSize(bool value)
1101     {
1102         adaptTextSize_ = value;
1103     }
1104 
1105     // Only used in old frames.
1106     // start
1107     void SetAdaptTextSize(
1108         const Dimension& maxFontSize, const Dimension& minFontSize, const Dimension& fontSizeStep = 1.0_px);
1109 
GetAdaptHeight()1110     bool GetAdaptHeight() const
1111     {
1112         return adaptHeight_;
1113     }
1114 
SetAdaptHeight(bool adaptHeight)1115     void SetAdaptHeight(bool adaptHeight)
1116     {
1117         adaptHeight_ = adaptHeight;
1118     }
1119 
SetPreferFontSizes(const std::vector<Dimension> & preferFontSizes)1120     void SetPreferFontSizes(const std::vector<Dimension>& preferFontSizes)
1121     {
1122         preferFontSizes_ = preferFontSizes;
1123         adaptTextSize_ = true;
1124     }
1125 
GetPreferFontSizes()1126     const std::vector<Dimension>& GetPreferFontSizes() const
1127     {
1128         return preferFontSizes_;
1129     }
1130 
GetPreferTextSizeGroups()1131     const std::vector<TextSizeGroup>& GetPreferTextSizeGroups() const
1132     {
1133         return preferTextSizeGroups_;
1134     }
1135 
SetPreferTextSizeGroups(const std::vector<TextSizeGroup> & preferTextSizeGroups)1136     void SetPreferTextSizeGroups(const std::vector<TextSizeGroup>& preferTextSizeGroups)
1137     {
1138         preferTextSizeGroups_ = preferTextSizeGroups;
1139         adaptTextSize_ = true;
1140     } // end
1141 
1142     // Must use with SetAdaptMaxFontSize.
SetAdaptMinFontSize(const Dimension & adaptMinFontSize)1143     void SetAdaptMinFontSize(const Dimension& adaptMinFontSize)
1144     {
1145         auto actualValue = adaptMinFontSize.ConvertToPxDistribute(GetMinFontScale(), GetMaxFontScale(), IsAllowScale());
1146         auto newValue = DimensionWithActual(adaptMinFontSize, static_cast<float>(actualValue));
1147         if (NearEqual(newValue, adaptMinFontSize_)) {
1148             return;
1149         }
1150         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::FONT_SIZE));
1151         adaptMinFontSize_ = newValue;
1152         adaptTextSize_ = true;
1153     }
1154     // Must use with SetAdaptMinFontSize.
SetAdaptMaxFontSize(const Dimension & adaptMaxFontSize)1155     void SetAdaptMaxFontSize(const Dimension& adaptMaxFontSize)
1156     {
1157         auto actualValue = adaptMaxFontSize.ConvertToPxDistribute(GetMinFontScale(), GetMaxFontScale(), IsAllowScale());
1158         auto newValue = DimensionWithActual(adaptMaxFontSize, static_cast<float>(actualValue));
1159         if (NearEqual(newValue, adaptMaxFontSize_)) {
1160             return;
1161         }
1162         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::FONT_SIZE));
1163         adaptMaxFontSize_ = newValue;
1164         adaptTextSize_ = true;
1165     }
1166 
GetAdaptMinFontSize()1167     const Dimension& GetAdaptMinFontSize() const
1168     {
1169         return adaptMinFontSize_.value;
1170     }
1171 
GetAdaptMaxFontSize()1172     const Dimension& GetAdaptMaxFontSize() const
1173     {
1174         return adaptMaxFontSize_.value;
1175     }
1176 
IsAllowScale()1177     bool IsAllowScale() const
1178     {
1179         return propAllowScale_;
1180     }
1181 
SetShadow(const Shadow & shadow)1182     void SetShadow(const Shadow& shadow)
1183     {
1184         propTextShadows_.emplace_back(shadow);
1185     }
1186 
1187     bool isSymbolGlyph_ = false;
1188 
SetSymbolColorList(const std::vector<Color> & renderColors)1189     void SetSymbolColorList(const std::vector<Color>& renderColors)
1190     {
1191         if (NearEqual(propRenderColors_, renderColors)) {
1192             return;
1193         }
1194         reLayoutSymbolStyleBitmap_.set(static_cast<int32_t>(SymbolStyleAttribute::COLOR_LIST));
1195         propRenderColors_ = renderColors;
1196     }
1197 
GetSymbolColorList()1198     const std::vector<Color>& GetSymbolColorList() const
1199     {
1200         return propRenderColors_;
1201     }
1202 
1203     void CompareCommonSubType(const std::optional<NG::SymbolEffectOptions>& options,
1204         const std::optional<NG::SymbolEffectOptions>& oldOptions);
1205     void CompareAnimationMode(const std::optional<NG::SymbolEffectOptions>& options,
1206         const std::optional<NG::SymbolEffectOptions>& oldOptions);
1207     void SetWhenOnlyOneOptionIsValid(const std::optional<NG::SymbolEffectOptions>& options);
1208     void SetSymbolEffectOptions(const std::optional<NG::SymbolEffectOptions>& symbolEffectOptions);
1209 
GetSymbolEffectOptions()1210     const std::optional<NG::SymbolEffectOptions> GetSymbolEffectOptions() const
1211     {
1212         return GetInnerSymbolEffectOptions();
1213     }
1214 
1215     std::string ToString() const;
1216     void UpdateColorByResourceId();
1217 
GetReLayoutTextStyleBitmap()1218     const std::bitset<static_cast<size_t>(TextStyleAttribute::MAX_TEXT_STYLE)>& GetReLayoutTextStyleBitmap() const
1219     {
1220         return reLayoutTextStyleBitmap_;
1221     }
1222 
1223     const std::bitset<static_cast<size_t>(ParagraphStyleAttribute::MAX_TEXT_STYLE)>&
GetReLayoutParagraphStyleBitmap()1224     GetReLayoutParagraphStyleBitmap() const
1225     {
1226         return reLayoutParagraphStyleBitmap_;
1227     }
1228 
GetReLayoutSymbolStyleBitmap()1229     const std::bitset<static_cast<size_t>(SymbolStyleAttribute::MAX_SYMBOL_STYLE)>& GetReLayoutSymbolStyleBitmap() const
1230     {
1231         return reLayoutSymbolStyleBitmap_;
1232     }
1233 
NeedReLayout()1234     bool NeedReLayout() const
1235     {
1236         return reLayoutTextStyleBitmap_.any() || reLayoutParagraphStyleBitmap_.any() ||
1237                reLayoutSymbolStyleBitmap_.any();
1238     }
1239 
NeedReCreateParagraph()1240     bool NeedReCreateParagraph() const
1241     {
1242         return needReCreateParagraph_;
1243     }
1244 
ResetReCreateAndReLayoutBitmap()1245     void ResetReCreateAndReLayoutBitmap()
1246     {
1247         reLayoutTextStyleBitmap_.reset();
1248         reLayoutParagraphStyleBitmap_.reset();
1249         reLayoutSymbolStyleBitmap_.reset();
1250         needReCreateParagraph_ = false;
1251     }
1252 
GetTextStyleUid()1253     int32_t GetTextStyleUid() const
1254     {
1255         return textStyleUid_;
1256     }
1257 
SetTextStyleUid(int32_t textStyleUid)1258     void SetTextStyleUid(int32_t textStyleUid)
1259     {
1260         textStyleUid_ = textStyleUid;
1261     }
1262 
GetSymbolUid()1263     int32_t GetSymbolUid() const
1264     {
1265         return symbolUid_;
1266     }
1267 
SetSymbolUid(int32_t symbolUid)1268     void SetSymbolUid(int32_t symbolUid)
1269     {
1270         symbolUid_ = symbolUid;
1271     }
1272 
SetSymbolShadow(const SymbolShadow & symbolShadow)1273     void SetSymbolShadow(const SymbolShadow& symbolShadow)
1274     {
1275         if (GetInnerSymbolShadowProp().has_value() && GetInnerSymbolShadowProp().value() == symbolShadow) {
1276             return;
1277         }
1278         SetInnerSymbolShadowProp(symbolShadow);
1279         reLayoutSymbolStyleBitmap_.set(static_cast<int32_t>(SymbolStyleAttribute::SYMBOL_SHADOW));
1280     }
1281 
GetSymbolShadow()1282     SymbolShadow GetSymbolShadow() const
1283     {
1284         return GetInnerSymbolShadowProp().value_or(SymbolShadow());
1285     }
1286 
SetShaderStyle(const std::vector<SymbolGradient> & shaderStyle)1287     void SetShaderStyle(const std::vector<SymbolGradient>& shaderStyle)
1288     {
1289         if (propGradientColorProp_ != shaderStyle) {
1290             propGradientColorProp_ = shaderStyle;
1291             reLayoutSymbolStyleBitmap_.set(static_cast<int32_t>(SymbolStyleAttribute::GRADIENT_COLOR));
1292         }
1293     }
1294 
GetShaderStyle()1295     std::vector<SymbolGradient> GetShaderStyle() const
1296     {
1297         return propGradientColorProp_;
1298     }
1299 
SetForeGroundBrushBitMap()1300     void SetForeGroundBrushBitMap()
1301     {
1302         reLayoutTextStyleBitmap_.set(static_cast<int32_t>(TextStyleAttribute::FOREGROUND_BRUSH));
1303     }
1304 
1305 private:
1306     ACE_DEFINE_SYMBOL_TEXT_STYLE_OPTIONAL_TYPE(InnerSymbolEffectOptions, NG::SymbolEffectOptions);
1307     ACE_DEFINE_SYMBOL_TEXT_STYLE_OPTIONAL_TYPE(InnerSymbolShadowProp, SymbolShadow);
1308     std::bitset<static_cast<size_t>(TextStyleAttribute::MAX_TEXT_STYLE)> reLayoutTextStyleBitmap_;
1309     std::bitset<static_cast<size_t>(ParagraphStyleAttribute::MAX_TEXT_STYLE)> reLayoutParagraphStyleBitmap_;
1310     std::bitset<static_cast<size_t>(SymbolStyleAttribute::MAX_SYMBOL_STYLE)> reLayoutSymbolStyleBitmap_;
1311     bool needReCreateParagraph_ = false;
1312     int32_t textStyleUid_ = 0;
1313     int32_t symbolUid_ = 0;
1314     std::list<std::pair<std::string, int32_t>> fontFeatures_;
1315     std::vector<Dimension> preferFontSizes_;
1316     std::vector<TextSizeGroup> preferTextSizeGroups_;
1317     // use 14px for normal font size.
1318     DimensionWithActual fontSize_ { Dimension(14, DimensionUnit::PX), 14.0f };
1319     FontWeight fontWeight_ { FontWeight::NORMAL };
1320 
1321     DimensionWithActual adaptMinFontSize_;
1322     DimensionWithActual adaptMaxFontSize_;
1323     DimensionWithActual lineHeight_;
1324     DimensionWithActual lineSpacing_;
1325     Dimension paragraphSpacing_ { 0.0f, DimensionUnit::PX };
1326     bool hasHeightOverride_ = false;
1327     bool adaptTextSize_ = false;
1328     bool adaptHeight_ = false; // whether adjust text size with height.
1329 
1330     RefPtr<AdvancedTextStyle> advancedTextStyle_;
1331     RefPtr<SymbolTextStyle> symbolTextStyle_;
1332 };
1333 
1334 namespace StringUtils {
1335 
1336 inline std::pair<bool, FontWeight> ParseFontWeight(const std::string& weight,
1337     FontWeight defaultFontWeight = FontWeight::NORMAL)
1338 {
1339     static const LinearMapNode<FontWeight> fontWeightTable[] = {
1340         { "100", FontWeight::W100 },
1341         { "200", FontWeight::W200 },
1342         { "300", FontWeight::W300 },
1343         { "400", FontWeight::W400 },
1344         { "500", FontWeight::W500 },
1345         { "600", FontWeight::W600 },
1346         { "700", FontWeight::W700 },
1347         { "800", FontWeight::W800 },
1348         { "900", FontWeight::W900 },
1349         { "bold", FontWeight::BOLD },
1350         { "bolder", FontWeight::BOLDER },
1351         { "lighter", FontWeight::LIGHTER },
1352         { "medium", FontWeight::MEDIUM },
1353         { "normal", FontWeight::NORMAL },
1354         { "regular", FontWeight::REGULAR },
1355     };
1356     auto weightIter = BinarySearchFindIndex(fontWeightTable, ArraySize(fontWeightTable), weight.c_str());
1357     return weightIter != -1 ? std::make_pair(true, fontWeightTable[weightIter].value)
1358                             : std::make_pair(false, defaultFontWeight);
1359 }
1360 
1361 inline FontWeight StringToFontWeight(const std::string& weight, FontWeight defaultFontWeight = FontWeight::NORMAL)
1362 {
1363     return ParseFontWeight(weight, defaultFontWeight).second;
1364 }
1365 
StringToWordBreak(const std::string & wordBreak)1366 inline WordBreak StringToWordBreak(const std::string& wordBreak)
1367 {
1368     static const LinearMapNode<WordBreak> wordBreakTable[] = {
1369         { "hyphenation", WordBreak::HYPHENATION },
1370         { "break-all", WordBreak::BREAK_ALL },
1371         { "break-word", WordBreak::BREAK_WORD },
1372         { "normal", WordBreak::NORMAL },
1373     };
1374     auto wordBreakIter = BinarySearchFindIndex(wordBreakTable, ArraySize(wordBreakTable), wordBreak.c_str());
1375     return wordBreakIter != -1 ? wordBreakTable[wordBreakIter].value : WordBreak::BREAK_WORD;
1376 }
1377 
FontWeightToString(const FontWeight & fontWeight)1378 inline std::string FontWeightToString(const FontWeight& fontWeight)
1379 {
1380     static const std::unordered_map<FontWeight, std::string> fontWeightTable = {
1381         { FontWeight::W100, "100" }, { FontWeight::W200, "200" }, { FontWeight::W300, "300" },
1382         { FontWeight::W400, "400" }, { FontWeight::W500, "500" }, { FontWeight::W600, "600" },
1383         { FontWeight::W700, "700" }, { FontWeight::W800, "800" }, { FontWeight::W900, "900" },
1384         { FontWeight::BOLD, "bold" }, { FontWeight::BOLDER, "bolder" }, { FontWeight::LIGHTER, "lighter" },
1385         { FontWeight::MEDIUM, "medium" }, { FontWeight::NORMAL, "normal" }, { FontWeight::REGULAR, "regular" },
1386     };
1387     auto weightIter = fontWeightTable.find(fontWeight);
1388     return weightIter != fontWeightTable.end() ? weightIter->second : "";
1389 }
1390 
ToString(const FontWeight & fontWeight)1391 inline std::string ToString(const FontWeight& fontWeight)
1392 {
1393     return FontWeightToString(fontWeight);
1394 }
1395 
SymbolColorListToString(const std::vector<Color> & colorList)1396 inline std::string SymbolColorListToString(const std::vector<Color>& colorList)
1397 {
1398     std::string symbolColorList = "";
1399     if (!colorList.empty()) {
1400         symbolColorList = colorList[0].ColorToString();
1401         for (uint32_t i = 1; i < colorList.size(); ++i) {
1402             symbolColorList += ", " + colorList[i].ColorToString();
1403         }
1404     }
1405     return symbolColorList;
1406 }
1407 } // namespace StringUtils
1408 } // namespace OHOS::Ace
1409 
1410 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_TEXT_STYLE_H
1411