1 /*
2  * Copyright (c) 2024 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_NG_PATTERN_TEXT_MULTIPLE_PARAGRAPH_LAYOUT_ALGORITHM_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_MULTIPLE_PARAGRAPH_LAYOUT_ALGORITHM_H
18 
19 #include <list>
20 #include <optional>
21 #include <string>
22 #include <unordered_map>
23 #include <utility>
24 
25 #include "base/memory/referenced.h"
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/layout/box_layout_algorithm.h"
28 #include "core/components_ng/layout/layout_wrapper.h"
29 #include "core/components_ng/pattern/rich_editor/paragraph_manager.h"
30 #include "core/components_ng/pattern/text/span_node.h"
31 #include "core/components_ng/pattern/text/text_content_modifier.h"
32 #include "core/components_ng/pattern/text/text_layout_property.h"
33 #include "core/components_ng/pattern/text/text_styles.h"
34 
35 namespace OHOS::Ace::NG {
36 // TextLayoutAlgorithm acts as the underlying text layout.
37 class ACE_EXPORT MultipleParagraphLayoutAlgorithm : public BoxLayoutAlgorithm {
38     DECLARE_ACE_TYPE(MultipleParagraphLayoutAlgorithm, BoxLayoutAlgorithm);
39 
40 public:
41     MultipleParagraphLayoutAlgorithm() = default;
42     ~MultipleParagraphLayoutAlgorithm() override = default;
43 
44     void Measure(LayoutWrapper* layoutWrapper) override;
45     void Layout(LayoutWrapper* layoutWrapper) override;
GetBaselineOffset()46     virtual float GetBaselineOffset() const
47     {
48         return 0.0f;
49     }
50 
51     static SizeF GetMaxMeasureSize(const LayoutConstraintF& contentConstraint);
52     RefPtr<Paragraph> GetSingleParagraph() const;
53 
54 protected:
55     void GetSpanParagraphStyle(LayoutWrapper* layoutWrapper, const RefPtr<SpanItem>& spanItem, ParagraphStyle& pStyle);
56     virtual ParagraphStyle GetParagraphStyle(
57         const TextStyle& textStyle, const std::string& content, LayoutWrapper* layoutWrapper) const;
58     virtual bool CreateParagraph(
59         const TextStyle& textStyle, std::string content, LayoutWrapper* layoutWrapper, double maxWidth = 0.0) = 0;
HandleEmptyParagraph(RefPtr<Paragraph> paragraph,const std::list<RefPtr<SpanItem>> & spanGroup)60     virtual void HandleEmptyParagraph(RefPtr<Paragraph> paragraph, const std::list<RefPtr<SpanItem>>& spanGroup) {}
GetParagraphStyleSpanItem(const std::list<RefPtr<SpanItem>> & spanGroup)61     virtual RefPtr<SpanItem> GetParagraphStyleSpanItem(const std::list<RefPtr<SpanItem>>& spanGroup)
62     {
63         CHECK_NULL_RETURN(!spanGroup.empty(), nullptr);
64         return spanGroup.front();
65     }
66 
67     void ApplyIndent(ParagraphStyle& paragraphStyle, const RefPtr<Paragraph>& paragraph, double width,
68         const TextStyle& textStyle);
69     void ConstructTextStyles(
70         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper, TextStyle& textStyle);
71     bool ParagraphReLayout(const LayoutConstraintF& contentConstraint);
72     bool UpdateParagraphBySpan(LayoutWrapper* layoutWrapper, ParagraphStyle paraStyle, double maxWidth,
73         const TextStyle& textStyle);
74     OffsetF SetContentOffset(LayoutWrapper* layoutWrapper);
SpansToString()75     std::string SpansToString()
76     {
77         std::stringstream ss;
78         for (auto& list : spans_) {
79             ss << "[";
80             for_each(list.begin(), list.end(), [&ss](RefPtr<SpanItem>& item) {
81                 ss << "[" << item->interval.first << "," << item->interval.second << ":"
82                    << StringUtils::RestoreEscape(item->content) << "], ";
83             });
84             ss << "], ";
85         }
86         return ss.str();
87     }
88 
GetParagraphs()89     std::list<ParagraphManager::ParagraphInfo> GetParagraphs()
90     {
91         std::list<ParagraphManager::ParagraphInfo> paragraphInfo;
92         if (paragraphManager_) {
93             paragraphInfo = paragraphManager_->GetParagraphs();
94         }
95         return paragraphInfo;
96     }
97 
98     std::vector<std::list<RefPtr<SpanItem>>> spans_;
99     RefPtr<ParagraphManager> paragraphManager_;
100     std::optional<TextStyle> textStyle_;
101     float baselineOffset_ = 0.0f;
102     float shadowOffset_ = 0.0f;
103     bool spanStringHasMaxLines_ = false;
104     bool isSpanStringMode_ = false;
105     bool isMarquee_ = false;
106 
107 private:
108     virtual OffsetF GetContentOffset(LayoutWrapper* layoutWrapper) = 0;
GetShadowOffset(const std::list<RefPtr<SpanItem>> & group)109     virtual float GetShadowOffset(const std::list<RefPtr<SpanItem>>& group)
110     {
111         return 0.0f;
112     }
113     static TextDirection GetTextDirection(const std::string& content, LayoutWrapper* layoutWrapper);
114     static TextDirection GetTextDirectionByContent(const std::string& content);
115 
116     void UpdateSymbolSpanEffect(
117         RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph, const std::list<RefPtr<SpanItem>>& spans);
118     void FontRegisterCallback(const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle);
119     void UpdateTextColorIfForeground(const RefPtr<FrameNode>& frameNode, TextStyle& textStyle);
120     void SetPropertyToModifier(const RefPtr<TextLayoutProperty>& layoutProperty,
121         const RefPtr<TextContentModifier>& modifier, const TextStyle& textStyle);
122     void SetDecorationPropertyToModifier(const RefPtr<TextLayoutProperty>& layoutProperty,
123         const RefPtr<TextContentModifier>& modifier, const TextStyle& textStyle);
124     void SetFontSizePropertyToModifier(const RefPtr<TextLayoutProperty>& layoutProperty,
125         const RefPtr<TextContentModifier>&, const TextStyle& textStyle);
126 
127     void AddImageToParagraph(RefPtr<ImageSpanItem>& imageSpanItem, const RefPtr<LayoutWrapper>& iterItem,
128         const LayoutConstraintF& layoutConstrain, const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength,
129         const TextStyle& textStyle);
130     void AddPlaceHolderToParagraph(RefPtr<PlaceholderSpanItem>& placeholderSpanItem,
131         const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& layoutConstrain,
132         const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength);
133     void UpdateParagraphByCustomSpan(RefPtr<CustomSpanItem>& customSpanItem, LayoutWrapper* layoutWrapper,
134         const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength, CustomSpanPlaceholderInfo& customSpanPlaceholder);
135 
136     void AddSymbolSpanToParagraph(const RefPtr<SpanItem>& child, int32_t& spanTextLength,
137         const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph);
138     void AddTextSpanToParagraph(const RefPtr<SpanItem>& child, int32_t& spanTextLength,
139         const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph);
140 
141     void GetChildrenPlaceholderIndex(std::vector<int32_t>& placeholderIndex);
142 
143     int32_t preParagraphsPlaceholderCount_ = 0;
144     int32_t currentParagraphPlaceholderCount_ = 0;
145 
146     float paragraphFontSize_ = 0.0f;
147 
148     ACE_DISALLOW_COPY_AND_MOVE(MultipleParagraphLayoutAlgorithm);
149 };
150 } // namespace OHOS::Ace::NG
151 
152 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_MULTIPLE_PARAGRAPH_LAYOUT_ALGORITHM_H
153