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