1 /*
2  * Copyright (c) 2022 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_FIELD_TEXT_FIELD_LAYOUT_ALGORITHM_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_FIELD_TEXT_FIELD_LAYOUT_ALGORITHM_H
18 
19 #include <string>
20 #include <utility>
21 
22 #include "base/geometry/ng/offset_t.h"
23 #include "base/memory/referenced.h"
24 #include "core/components/text_field/textfield_theme.h"
25 #include "core/components_ng/layout/layout_wrapper.h"
26 #include "core/components_ng/pattern/text/text_adapt_font_sizer.h"
27 #include "core/components_ng/pattern/text_field/text_field_layout_property.h"
28 
29 namespace OHOS::Ace::NG {
30 
31 struct InlineMeasureItem {
32     float inlineScrollRectOffsetX = 0.0f;
33     float inlineLastOffsetY = 0.0f;
34     float inlineContentRectHeight = 0.0f;
35     float inlineSizeHeight = 0.0f;
36 };
37 struct CreateParagraphData {
38     bool disableTextAlign = false;
39     float fontSize = 0.0f;
40 };
41 class TextFieldPattern;
42 class TextFieldContentModifier;
43 class ACE_EXPORT TextFieldLayoutAlgorithm : public LayoutAlgorithm, public TextAdaptFontSizer {
44     DECLARE_ACE_TYPE(TextFieldLayoutAlgorithm, LayoutAlgorithm, TextAdaptFontSizer);
45 
46 public:
47     TextFieldLayoutAlgorithm() = default;
48 
49     ~TextFieldLayoutAlgorithm() override = default;
50 
OnReset()51     void OnReset() override
52     {
53         paragraph_->Reset();
54     }
55 
56     RefPtr<Paragraph> GetParagraph() const override;
57     void GetSuitableSize(SizeF& maxSize, LayoutWrapper* layoutWrapper) override;
58     bool CreateParagraphAndLayout(const TextStyle& textStyle, const std::string& content,
59         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper, bool needLayout = true) override;
60 
GetTextRect()61     const RectF& GetTextRect() const
62     {
63         return textRect_;
64     }
65 
GetParentGlobalOffset()66     const OffsetF& GetParentGlobalOffset() const
67     {
68         return parentGlobalOffset_;
69     }
70 
GetUnitWidth()71     float GetUnitWidth() const
72     {
73         return unitWidth_;
74     }
75 
GetInlineMeasureItem()76     InlineMeasureItem GetInlineMeasureItem() const
77     {
78         return inlineMeasureItem_;
79     }
80 
81     static TextDirection GetTextDirection(const std::string& content, TextDirection direction = TextDirection::AUTO);
82 
83     static void UpdateTextStyle(const RefPtr<FrameNode>& frameNode,
84         const RefPtr<TextFieldLayoutProperty>& layoutProperty, const RefPtr<TextFieldTheme>& theme,
85         TextStyle& textStyle, bool isDisabled);
86     static void UpdatePlaceholderTextStyle(const RefPtr<FrameNode>& frameNode,
87         const RefPtr<TextFieldLayoutProperty>& layoutProperty, const RefPtr<TextFieldTheme>& theme,
88         TextStyle& textStyle, bool isDisabled);
89     void CounterLayout(LayoutWrapper* layoutWrapper);
90     float CounterNodeMeasure(float contentWidth, LayoutWrapper* layoutWrapper);
91     void UpdateCounterTextMargin(LayoutWrapper* layoutWrapper);
92     void UpdateCounterBorderStyle(uint32_t& textLength, uint32_t& maxLength, LayoutWrapper* layoutWrapper);
93     void UpdateCounterNode(uint32_t textLength, uint32_t maxLength, const LayoutConstraintF& contentConstraint,
94         LayoutWrapper* layoutWrapper);
95     bool DidExceedMaxLines(const SizeF& maxSize) override;
96     bool IsAdaptExceedLimit(const SizeF& maxSize) override;
97 
98 protected:
99     static void FontRegisterCallback(const RefPtr<FrameNode>& frameNode, const std::vector<std::string>& fontFamilies);
100     void CreateParagraph(const TextStyle& textStyle, std::string content, bool needObscureText,
101         int32_t nakedCharPosition, CreateParagraphData paragraphData);
102     void CreateParagraph(const TextStyle& textStyle, const std::vector<std::string>& contents,
103         const std::string& content, bool needObscureText, CreateParagraphData paragraphData);
104     void CreateInlineParagraph(const TextStyle& textStyle, std::string content, bool needObscureText,
105         int32_t nakedCharPosition, CreateParagraphData paragraphData);
106     void SetPropertyToModifier(const TextStyle& textStyle, RefPtr<TextFieldContentModifier> modifier);
107 
108     float GetTextFieldDefaultHeight();
109 
110     void ConstructTextStyles(
111         const RefPtr<FrameNode>& frameNode, TextStyle& textStyle, std::string& textContent, bool& showPlaceHolder);
112     LayoutConstraintF CalculateContentMaxSizeWithCalculateConstraint(
113         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper);
114 
115     int32_t ConvertTouchOffsetToCaretPosition(const Offset& localOffset);
116     void UpdateUnitLayout(LayoutWrapper* layoutWrapper);
117     ParagraphStyle GetParagraphStyle(
118         const TextStyle& textStyle, const std::string& content, const float fontSize) const;
119     void GetInlineMeasureItem(
120         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper, float& inlineIdealHeight);
121     float ConstraintWithMinWidth(
122         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper,
123         RefPtr<Paragraph>& paragraph, float removeValue = 0.0f);
124     SizeF GetConstraintSize(const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper);
125     std::optional<SizeF> InlineMeasureContent(const LayoutConstraintF& contentConstraint,
126         LayoutWrapper* layoutWrapper);
127     SizeF PlaceHolderMeasureContent(
128         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper, float imageWidth = 0.0f);
129     SizeF TextInputMeasureContent(const LayoutConstraintF& contentConstraint,
130         LayoutWrapper* layoutWrapper, float imageWidth);
131     SizeF TextAreaMeasureContent(const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper);
132 
133     bool AddAdaptFontSizeAndAnimations(TextStyle& textStyle, const RefPtr<TextFieldLayoutProperty>& layoutProperty,
134         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper);
135     bool IsNeedAdaptFontSize(const TextStyle& textStyle, const RefPtr<TextFieldLayoutProperty>& layoutProperty,
136         const LayoutConstraintF& contentConstraint);
137     bool AdaptInlineFocusFontSize(TextStyle& textStyle, const std::string& content, const Dimension& stepUnit,
138         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) override;
139     bool AdaptInlineFocusMinFontSize(TextStyle& textStyle, const std::string& content, const Dimension& stepUnit,
140         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper);
141     virtual bool CreateParagraphEx(const TextStyle& textStyle, const std::string& content,
142         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper) = 0;
143 
144     LayoutConstraintF CalculateFrameSizeConstraint(
145         const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper);
146 
147     RefPtr<Paragraph> paragraph_;
148     RefPtr<Paragraph> inlineParagraph_;
149     InlineMeasureItem inlineMeasureItem_;
150     LayoutConstraintF textFieldContentConstraint_;
151 
152     RectF textRect_;
153     OffsetF parentGlobalOffset_;
154     std::string textContent_;
155     bool showPlaceHolder_ = false;
156     float preferredHeight_ = 0.0f;
157     TextDirection direction_ = TextDirection::AUTO;
158 
159     float unitWidth_ = 0.0f;
160     bool autoWidth_ = false;
161     Dimension textIndent_ = 0.0_px;
162     float indent_ = 0.0f;
163 private:
164     TextAlign GetCounterNodeAlignment(LayoutWrapper* layoutWrapper);
165     void InlineFocusMeasure(const LayoutConstraintF& contentConstraint,
166         LayoutWrapper* layoutWrapper, double& safeBoundary, float& contentWidth);
167     static void UpdateTextStyleMore(const RefPtr<FrameNode>& frameNode,
168         const RefPtr<TextFieldLayoutProperty>& layoutProperty, TextStyle& textStyle, bool isDisabled);
169     static void UpdatePlaceholderTextStyleMore(const RefPtr<FrameNode>& frameNode,
170         const RefPtr<TextFieldLayoutProperty>& layoutProperty, const RefPtr<TextFieldTheme>& theme,
171         TextStyle& placeholderTextStyle, bool isDisabled);
172     void UpdateTextStyleTextOverflowAndWordBreak(TextStyle& textStyle, bool isTextArea,
173         bool isInlineStyle, const RefPtr<TextFieldLayoutProperty>& textFieldLayoutProperty);
174     float GetVisualTextWidth() const;
175     void CalcInlineMeasureItem(LayoutWrapper* layoutWrapper);
176     bool IsInlineFocusAdaptExceedLimit(const SizeF& maxSize);
177     bool IsInlineFocusAdaptMinExceedLimit(const SizeF& maxSize, uint32_t maxViewLines);
178     void HandleCounterLayout(LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& counterNode,
179         const RefPtr<TextFieldPattern>& pattern);
180     void HandleNonTextArea(LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& counterNode,
181         const RefPtr<TextFieldPattern>& pattern, bool isRTL, float& countX);
182     void HandleTextArea(LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& counterNode,
183         const RefPtr<TextFieldPattern>& pattern, bool isRTL, float& countX);
184     float CalculateContentWidth(const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper,
185         float imageWidth);
186     float CalculateContentHeight(const LayoutConstraintF& contentConstraint);
187     LayoutConstraintF BuildInfinityLayoutConstraint(const LayoutConstraintF& contentConstraint);
188     void ApplyIndent(LayoutWrapper* layoutWrapper, double width);
189     LayoutConstraintF BuildInlineFocusLayoutConstraint(const LayoutConstraintF& contentConstraint,
190         LayoutWrapper* layoutWrapper);
191     ACE_DISALLOW_COPY_AND_MOVE(TextFieldLayoutAlgorithm);
192 };
193 } // namespace OHOS::Ace::NG
194 
195 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_FIELD_TEXT_FIELD_LAYOUT_ALGORITHM_H
196