1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/text_field/text_field_layout_algorithm.h"
17 
18 #include "base/geometry/axis.h"
19 #include "base/geometry/dimension.h"
20 #include "base/geometry/ng/rect_t.h"
21 #include "base/geometry/ng/size_t.h"
22 #include "base/i18n/localization.h"
23 #include "base/log/log_wrapper.h"
24 #include "base/memory/referenced.h"
25 #include "base/utils/utils.h"
26 #include "bridge/common/utils/utils.h"
27 #include "core/common/font_manager.h"
28 #include "core/components/common/layout/constants.h"
29 #include "core/components/common/properties/text_style.h"
30 #include "core/components/scroll/scroll_bar_theme.h"
31 #include "core/components_ng/base/frame_node.h"
32 #include "core/components_ng/pattern/text/text_layout_adapter.h"
33 #include "core/components_ng/pattern/text/text_layout_property.h"
34 #include "core/components_ng/pattern/text/text_styles.h"
35 #include "core/components_ng/pattern/text_field/text_field_content_modifier.h"
36 #include "core/components_ng/pattern/text_field/text_field_layout_property.h"
37 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
38 #include "core/components_ng/pattern/text_field/text_selector.h"
39 #include "core/components_ng/property/measure_utils.h"
40 #include "core/pipeline_ng/pipeline_context.h"
41 
42 namespace OHOS::Ace::NG {
43 namespace {
44 constexpr float PARAGRAPH_SAVE_BOUNDARY = 1.0f;
45 constexpr uint32_t INLINE_DEFAULT_VIEW_MAXLINE = 3;
46 constexpr uint32_t COUNTER_TEXT_MAXLINE = 1;
47 constexpr Dimension COUNTER_TEXT_MARGIN_OFFSET = 8._vp;
48 constexpr int32_t DEFAULT_MODE = -1;
49 constexpr int32_t SHOW_COUNTER_PERCENT = 100;
50 constexpr double TEXT_DECORATION_DISABLED_COLOR_ALPHA = 0.2;
51 constexpr Dimension INLINE_MIN_WITH = 16.0_vp;
52 } // namespace
ConstructTextStyles(const RefPtr<FrameNode> & frameNode,TextStyle & textStyle,std::string & textContent,bool & showPlaceHolder)53 void TextFieldLayoutAlgorithm::ConstructTextStyles(
54     const RefPtr<FrameNode>& frameNode, TextStyle& textStyle, std::string& textContent, bool& showPlaceHolder)
55 {
56     CHECK_NULL_VOID(frameNode);
57     auto pipeline = frameNode->GetContext();
58     CHECK_NULL_VOID(pipeline);
59     auto textFieldTheme = pipeline->GetTheme<TextFieldTheme>();
60     CHECK_NULL_VOID(textFieldTheme);
61     auto pattern = frameNode->GetPattern<TextFieldPattern>();
62     CHECK_NULL_VOID(pattern);
63     auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
64     CHECK_NULL_VOID(textFieldLayoutProperty);
65     auto isInlineStyle = pattern->IsNormalInlineState();
66     auto isTextArea = pattern->IsTextArea();
67 
68     if (!pattern->GetTextValue().empty()) {
69         UpdateTextStyle(frameNode, textFieldLayoutProperty, textFieldTheme, textStyle, pattern->IsDisabled());
70         textContent = pattern->GetTextValue();
71         UpdateTextStyleTextOverflowAndWordBreak(textStyle, isTextArea, isInlineStyle, textFieldLayoutProperty);
72     } else {
73         UpdatePlaceholderTextStyle(
74             frameNode, textFieldLayoutProperty, textFieldTheme, textStyle, pattern->IsDisabled());
75         textContent = textFieldLayoutProperty->GetPlaceholderValue("");
76         showPlaceHolder = true;
77     }
78 
79     if (pattern->GetMaxFontSizeScale().has_value()) {
80         textStyle.SetMaxFontScale(pattern->GetMaxFontSizeScale().value());
81     }
82     textIndent_ = textStyle.GetTextIndent();
83     auto fontManager = pipeline->GetFontManager();
84     if (fontManager && !(fontManager->GetAppCustomFont().empty()) &&
85         !(textFieldLayoutProperty->GetFontFamily().has_value())) {
86         textStyle.SetFontFamilies(Framework::ConvertStrToFontFamilies(fontManager->GetAppCustomFont()));
87     }
88     // use for modifier.
89     auto contentModifier = pattern->GetContentModifier();
90     if (contentModifier) {
91         SetPropertyToModifier(textStyle, contentModifier);
92         contentModifier->ModifyTextStyle(textStyle);
93         contentModifier->SetFontReady(false);
94     }
95 }
96 
UpdateTextStyleTextOverflowAndWordBreak(TextStyle & textStyle,bool isTextArea,bool isInlineStyle,const RefPtr<TextFieldLayoutProperty> & textFieldLayoutProperty)97 void TextFieldLayoutAlgorithm::UpdateTextStyleTextOverflowAndWordBreak(TextStyle& textStyle, bool isTextArea,
98     bool isInlineStyle, const RefPtr<TextFieldLayoutProperty>& textFieldLayoutProperty)
99 {
100     if (!isTextArea && isInlineStyle) {
101         //textinput inline
102         if (textFieldLayoutProperty->HasTextOverflow()) {
103             if (textFieldLayoutProperty->GetTextOverflow() == TextOverflow::DEFAULT) {
104                 textStyle.SetTextOverflow(TextOverflow::ELLIPSIS);
105             } else {
106                 textStyle.SetTextOverflow(textFieldLayoutProperty->GetTextOverflow().value());
107             }
108         } else {
109             textStyle.SetTextOverflow(TextOverflow::ELLIPSIS);
110         }
111     } else {
112         if (textFieldLayoutProperty->HasTextOverflow()) {
113             if (textFieldLayoutProperty->GetTextOverflow() == TextOverflow::DEFAULT) {
114                 textStyle.SetTextOverflow(TextOverflow::CLIP);
115             } else {
116                 textStyle.SetTextOverflow(textFieldLayoutProperty->GetTextOverflow().value());
117             }
118         } else {
119             textStyle.SetTextOverflow(TextOverflow::CLIP);
120         }
121     }
122 
123     if (isTextArea || isInlineStyle) {
124         textStyle.SetWordBreak(textFieldLayoutProperty->GetWordBreak().value_or(WordBreak::BREAK_WORD));
125     }
126     // Not Support TextOverflow::MARQUEE Now
127     if (textStyle.GetTextOverflow() == TextOverflow::MARQUEE) {
128         if (!isTextArea && isInlineStyle) {
129             textStyle.SetTextOverflow(TextOverflow::ELLIPSIS);
130         } else {
131             textStyle.SetTextOverflow(TextOverflow::CLIP);
132         }
133     }
134 }
135 
InlineFocusMeasure(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper,double & safeBoundary,float & contentWidth)136 void TextFieldLayoutAlgorithm::InlineFocusMeasure(const LayoutConstraintF& contentConstraint,
137     LayoutWrapper* layoutWrapper, double& safeBoundary, float& contentWidth)
138 {
139     ApplyIndent(layoutWrapper, contentConstraint.maxSize.Width());
140     paragraph_->Layout(
141         contentConstraint.maxSize.Width() - static_cast<float>(safeBoundary) - PARAGRAPH_SAVE_BOUNDARY);
142     auto longestLine = std::ceil(paragraph_->GetLongestLineWithIndent());
143     paragraph_->Layout(std::min(static_cast<float>(longestLine), paragraph_->GetMaxWidth()));
144     contentWidth = ConstraintWithMinWidth(
145         contentConstraint, layoutWrapper, paragraph_, static_cast<float>(safeBoundary) + PARAGRAPH_SAVE_BOUNDARY);
146 }
147 
InlineMeasureContent(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)148 std::optional<SizeF> TextFieldLayoutAlgorithm::InlineMeasureContent(const LayoutConstraintF& contentConstraint,
149     LayoutWrapper* layoutWrapper)
150 {
151     auto frameNode = layoutWrapper->GetHostNode();
152     CHECK_NULL_RETURN(frameNode, std::nullopt);
153     auto textFieldLayoutProperty = DynamicCast<TextFieldLayoutProperty>(layoutWrapper->GetLayoutProperty());
154     CHECK_NULL_RETURN(textFieldLayoutProperty, std::nullopt);
155     auto pattern = frameNode->GetPattern<TextFieldPattern>();
156     CHECK_NULL_RETURN(pattern, std::nullopt);
157     auto textFieldTheme = pattern->GetTheme();
158     CHECK_NULL_RETURN(textFieldTheme, std::nullopt);
159 
160     float contentWidth = 0.0f;
161     auto safeBoundary = textFieldTheme->GetInlineBorderWidth().ConvertToPx() * 2;
162     if (pattern->HasFocus()) {
163         InlineFocusMeasure(contentConstraint, layoutWrapper, safeBoundary, contentWidth);
164     } else {
165         ApplyIndent(layoutWrapper, contentConstraint.maxSize.Width());
166         paragraph_->Layout(contentConstraint.maxSize.Width());
167         if (autoWidth_) {
168             auto paragraphLongestLine = std::ceil(paragraph_->GetLongestLineWithIndent());
169             paragraph_->Layout(std::min(static_cast<float>(paragraphLongestLine), paragraph_->GetMaxWidth()));
170         }
171         contentWidth = ConstraintWithMinWidth(contentConstraint, layoutWrapper, paragraph_);
172         // calc inline status in advance
173         auto widthOffSet = contentConstraint.selfIdealSize.Width().has_value()?
174             pattern->GetPaddingLeft() + pattern->GetPaddingRight() - safeBoundary : 0.0f - safeBoundary;
175         inlineParagraph_->Layout(contentConstraint.maxSize.Width() + widthOffSet
176             - safeBoundary - PARAGRAPH_SAVE_BOUNDARY);
177         auto longestLine = std::ceil(inlineParagraph_->GetLongestLineWithIndent());
178         inlineParagraph_->Layout(std::min(static_cast<float>(longestLine), inlineParagraph_->GetMaxWidth()));
179         auto inlineContentWidth = ConstraintWithMinWidth(contentConstraint, layoutWrapper, inlineParagraph_,
180             static_cast<float>(safeBoundary) + PARAGRAPH_SAVE_BOUNDARY);
181         inlineMeasureItem_.inlineScrollRectOffsetX = contentWidth
182             + pattern->GetHorizontalPaddingAndBorderSum() - inlineContentWidth - safeBoundary - PARAGRAPH_SAVE_BOUNDARY;
183     }
184 
185     textRect_.SetSize(SizeF(GetVisualTextWidth(), paragraph_->GetHeight()));
186 
187     auto inlineIdealHeight = contentConstraint.maxSize.Height();
188     GetInlineMeasureItem(contentConstraint, layoutWrapper, inlineIdealHeight);
189     auto contentHeight = GreatNotEqual(paragraph_->GetLongestLine(), 0.0)
190         ? paragraph_->GetHeight() : std::max(preferredHeight_, paragraph_->GetHeight());
191     auto minWidth = INLINE_MIN_WITH.ConvertToPx();
192     contentWidth = GreatNotEqual(contentWidth, minWidth) ? contentWidth : minWidth;
193     return SizeF(contentWidth, std::min(inlineIdealHeight, contentHeight));
194 }
195 
GetInlineMeasureItem(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper,float & inlineIdealHeight)196 void TextFieldLayoutAlgorithm::GetInlineMeasureItem(
197     const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper, float& inlineIdealHeight)
198 {
199     auto frameNode = layoutWrapper->GetHostNode();
200     CHECK_NULL_VOID(frameNode);
201     auto textFieldLayoutProperty = DynamicCast<TextFieldLayoutProperty>(layoutWrapper->GetLayoutProperty());
202     CHECK_NULL_VOID(textFieldLayoutProperty);
203     auto pattern = frameNode->GetPattern<TextFieldPattern>();
204     CHECK_NULL_VOID(pattern);
205 
206     if (pattern->HasFocus() && paragraph_->GetLineCount() != 0) {
207         pattern->SetSingleLineHeight(paragraph_->GetHeight() / paragraph_->GetLineCount());
208         // The maximum height of the inline mode defaults to a maximum of three rows.
209         inlineIdealHeight =
210             pattern->GetSingleLineHeight() * textFieldLayoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE);
211         inlineMeasureItem_.inlineSizeHeight = pattern->GetSingleLineHeight() * std::min(
212             static_cast<uint32_t>(paragraph_->GetLineCount()),
213             textFieldLayoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE));
214     } else {
215         // calc inline status in advance
216         CalcInlineMeasureItem(layoutWrapper);
217     }
218 }
219 
ApplyIndent(LayoutWrapper * layoutWrapper,double width)220 void TextFieldLayoutAlgorithm::ApplyIndent(LayoutWrapper* layoutWrapper, double width)
221 {
222     if (LessOrEqual(textIndent_.Value(), 0.0)) {
223         return;
224     }
225     // first line indent
226     CHECK_NULL_VOID(paragraph_);
227     auto pipeline = PipelineContext::GetCurrentContextSafely();
228     CHECK_NULL_VOID(pipeline);
229     auto frameNode = layoutWrapper->GetHostNode();
230     CHECK_NULL_VOID(frameNode);
231     auto textFieldLayoutProperty = DynamicCast<TextFieldLayoutProperty>(layoutWrapper->GetLayoutProperty());
232     CHECK_NULL_VOID(textFieldLayoutProperty);
233     auto pattern = frameNode->GetPattern<TextFieldPattern>();
234     CHECK_NULL_VOID(pattern);
235 
236     double indentValue = 0.0;
237     if (textIndent_.Unit() != DimensionUnit::PERCENT) {
238         float maxFontScale = pattern->GetMaxFontSizeScale().has_value() ?
239             pattern->GetMaxFontSizeScale().value() : pipeline->GetMaxAppFontScale();
240         float fontScale = std::min(pipeline->GetFontScale(), maxFontScale);
241         if (!textIndent_.NormalizeToPx(pipeline->GetDipScale(),
242             fontScale, pipeline->GetLogicScale(), width, indentValue)) {
243             return;
244         }
245     } else {
246         indentValue = width * textIndent_.Value();
247     }
248     indent_ = static_cast<float>(indentValue);
249     std::vector<float> indents;
250     // only indent first line
251     indents.emplace_back(indent_);
252     indents.emplace_back(0.0);
253     paragraph_->SetIndents(indents);
254 }
255 
CalcInlineMeasureItem(LayoutWrapper * layoutWrapper)256 void TextFieldLayoutAlgorithm::CalcInlineMeasureItem(LayoutWrapper* layoutWrapper)
257 {
258     auto textFieldLayoutProperty = DynamicCast<TextFieldLayoutProperty>(layoutWrapper->GetLayoutProperty());
259     CHECK_NULL_VOID(textFieldLayoutProperty);
260     auto lineCount = inlineParagraph_->GetLineCount() != 0 ? inlineParagraph_->GetLineCount() : 1;
261     inlineMeasureItem_.inlineSizeHeight = inlineParagraph_->GetHeight() / lineCount
262         * std::min(static_cast<uint32_t>(lineCount),
263             textFieldLayoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE));
264     inlineMeasureItem_.inlineContentRectHeight = GreatNotEqual(inlineParagraph_->GetLongestLine(), 0.0)
265         ? inlineParagraph_->GetHeight() : std::max(preferredHeight_, inlineParagraph_->GetHeight());
266     inlineMeasureItem_.inlineLastOffsetY =
267         std::max(inlineMeasureItem_.inlineSizeHeight, inlineMeasureItem_.inlineContentRectHeight)
268         - std::min(inlineMeasureItem_.inlineSizeHeight, inlineMeasureItem_.inlineContentRectHeight);
269 }
270 
ConstraintWithMinWidth(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper,RefPtr<Paragraph> & paragraph,float removeValue)271 float TextFieldLayoutAlgorithm::ConstraintWithMinWidth(
272     const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper,
273     RefPtr<Paragraph>& paragraph, float removeValue)
274 {
275     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
276         !layoutWrapper->GetLayoutProperty()->GetLayoutRect()) {
277         const auto& calcLayoutConstraint = layoutWrapper->GetLayoutProperty()->GetCalcLayoutConstraint();
278         if (calcLayoutConstraint && calcLayoutConstraint->minSize.has_value() &&
279             calcLayoutConstraint->minSize->Width().has_value() &&
280             !contentConstraint.selfIdealSize.Width().has_value()) {
281             auto width = std::max(contentConstraint.minSize.Width() - removeValue, paragraph->GetLongestLine());
282             if (width != paragraph->GetLongestLine()) {
283                 paragraph->Layout(width);
284             } else {
285                 if (LessNotEqual(paragraph->GetLongestLine(), paragraph->GetMaxWidth())) {
286                     paragraph->Layout(std::ceil(paragraph->GetLongestLine()));
287                 }
288                 return contentConstraint.selfIdealSize.Width().has_value() ? paragraph->GetMaxWidth()
289                                                                            : GetVisualTextWidth();
290             }
291         }
292     }
293     return std::max(paragraph->GetMaxWidth(), 0.0f);
294 }
295 
PlaceHolderMeasureContent(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper,float imageWidth)296 SizeF TextFieldLayoutAlgorithm::PlaceHolderMeasureContent(const LayoutConstraintF& contentConstraint,
297     LayoutWrapper* layoutWrapper, float imageWidth)
298 {
299     paragraph_->Layout(contentConstraint.maxSize.Width() - imageWidth);
300 
301     // Adapts to auto width.
302     if (autoWidth_) {
303         auto minWidth = static_cast<float>(INLINE_MIN_WITH.ConvertToPx());
304         paragraph_->Layout(std::max(minWidth, std::ceil(paragraph_->GetLongestLine())));
305     }
306 
307     auto contentWidth = ConstraintWithMinWidth(contentConstraint, layoutWrapper, paragraph_, imageWidth);
308 
309     auto frameNode = layoutWrapper->GetHostNode();
310     CHECK_NULL_RETURN(frameNode, SizeF());
311     auto pattern = frameNode->GetPattern<TextFieldPattern>();
312     CHECK_NULL_RETURN(pattern, SizeF());
313     if (pattern->GetTextInputFlag()) {
314         // TextInput's counter is outside the input area
315         auto reviseContentWidth = contentWidth + imageWidth;
316         CounterNodeMeasure(reviseContentWidth, layoutWrapper);
317     } else {
318         // TextArea's counter is inside the input area
319         CounterNodeMeasure(contentWidth, layoutWrapper);
320     }
321 
322     auto height = GreatNotEqual(paragraph_->GetLongestLine(), 0.0)
323                       ? paragraph_->GetHeight()
324                       : std::max(preferredHeight_, paragraph_->GetHeight());
325 
326     auto contentHeight = std::min(contentConstraint.maxSize.Height(), height);
327 
328     textRect_.SetSize(SizeF(GetVisualTextWidth(), paragraph_->GetHeight()));
329 
330     return SizeF(contentWidth, contentHeight);
331 }
332 
TextAreaMeasureContent(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)333 SizeF TextFieldLayoutAlgorithm::TextAreaMeasureContent(const LayoutConstraintF& contentConstraint,
334     LayoutWrapper* layoutWrapper)
335 {
336     ACE_LAYOUT_SCOPED_TRACE("TextAreaMeasureContent");
337     ApplyIndent(layoutWrapper, contentConstraint.maxSize.Width());
338     paragraph_->Layout(contentConstraint.maxSize.Width());
339 
340     auto contentWidth = ConstraintWithMinWidth(contentConstraint, layoutWrapper, paragraph_);
341 
342     if (autoWidth_) {
343         contentWidth = std::min(contentWidth, paragraph_->GetLongestLineWithIndent());
344         auto minWidth = INLINE_MIN_WITH.ConvertToPx();
345         contentWidth = GreatNotEqual(contentWidth, minWidth) ? contentWidth : minWidth;
346         paragraph_->Layout(std::ceil(contentWidth));
347     }
348 
349     auto counterNodeHeight = CounterNodeMeasure(contentWidth, layoutWrapper);
350 
351     auto height = GreatNotEqual(paragraph_->GetLongestLine(), 0.0)
352                       ? paragraph_->GetHeight()
353                       : std::max(preferredHeight_, paragraph_->GetHeight());
354 
355     auto contentHeight = std::min(contentConstraint.maxSize.Height() - counterNodeHeight, height);
356 
357     textRect_.SetSize(SizeF(GetVisualTextWidth(), paragraph_->GetHeight()));
358     return SizeF(contentWidth, contentHeight);
359 }
360 
TextInputMeasureContent(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper,float imageWidth)361 SizeF TextFieldLayoutAlgorithm::TextInputMeasureContent(const LayoutConstraintF& contentConstraint,
362     LayoutWrapper* layoutWrapper, float imageWidth)
363 {
364     ACE_LAYOUT_SCOPED_TRACE("TextInputMeasureContent");
365     ApplyIndent(layoutWrapper, contentConstraint.maxSize.Width());
366     paragraph_->Layout(std::numeric_limits<double>::infinity());
367     float contentWidth = CalculateContentWidth(contentConstraint, layoutWrapper, imageWidth);
368     float contentHeight = CalculateContentHeight(contentConstraint);
369     textRect_.SetSize(SizeF(std::max(0.0f, paragraph_->GetLongestLine()) + indent_, paragraph_->GetHeight()));
370     return SizeF(contentWidth, contentHeight);
371 }
372 
CalculateContentWidth(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper,float imageWidth)373 float TextFieldLayoutAlgorithm::CalculateContentWidth(const LayoutConstraintF& contentConstraint,
374     LayoutWrapper* layoutWrapper, float imageWidth)
375 {
376     auto contentWidth = contentConstraint.maxSize.Width() - imageWidth;
377     auto textFieldWidth = contentWidth;
378 
379     std::optional<SizeF> minSize;
380     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
381         !layoutWrapper->GetLayoutProperty()->GetLayoutRect()) {
382         const auto &calcLayoutConstraint = layoutWrapper->GetLayoutProperty()->GetCalcLayoutConstraint();
383         if (calcLayoutConstraint && calcLayoutConstraint->minSize.has_value() &&
384             calcLayoutConstraint->minSize->Width().has_value() &&
385             !contentConstraint.selfIdealSize.Width().has_value()) {
386             minSize = contentConstraint.minSize;
387         }
388     }
389     if (minSize.has_value()) {
390         auto minWidth = minSize.value().Width();
391         paragraph_->Layout(std::max(std::ceil(paragraph_->GetLongestLineWithIndent()), minWidth));
392     } else if (autoWidth_) {
393         paragraph_->Layout(std::ceil(paragraph_->GetLongestLineWithIndent()));
394     } else {
395         paragraph_->Layout(std::max(std::ceil(paragraph_->GetLongestLineWithIndent()), textFieldWidth));
396     }
397 
398     CounterNodeMeasure(contentWidth, layoutWrapper);
399     if (autoWidth_) {
400         double minWidth = INLINE_MIN_WITH.ConvertToPx();
401         contentWidth = GreatNotEqual(contentWidth, minWidth) ? contentWidth : minWidth;
402         contentWidth = std::min(contentWidth, std::ceil(paragraph_->GetLongestLineWithIndent()));
403     }
404 
405     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
406         !layoutWrapper->GetLayoutProperty()->GetLayoutRect()) {
407         const auto &calcLayoutConstraint = layoutWrapper->GetLayoutProperty()->GetCalcLayoutConstraint();
408         if (calcLayoutConstraint && calcLayoutConstraint->minSize.has_value() &&
409             calcLayoutConstraint->minSize->Width().has_value() &&
410             !contentConstraint.selfIdealSize.Width().has_value()) {
411             contentWidth = std::min(contentConstraint.maxSize.Width() - imageWidth,
412                 std::max(std::ceil(paragraph_->GetLongestLineWithIndent()),
413                 contentConstraint.minSize.Width() - imageWidth));
414         }
415     }
416     return contentWidth;
417 }
418 
CalculateContentHeight(const LayoutConstraintF & contentConstraint)419 float TextFieldLayoutAlgorithm::CalculateContentHeight(const LayoutConstraintF& contentConstraint)
420 {
421     auto height = GreatNotEqual(paragraph_->GetLongestLine(), 0.0)
422                       ? paragraph_->GetHeight()
423                       : std::max(preferredHeight_, paragraph_->GetHeight());
424 
425     return std::min(contentConstraint.maxSize.Height(), height);
426 }
427 
GetCounterNodeAlignment(LayoutWrapper * layoutWrapper)428 TextAlign TextFieldLayoutAlgorithm::GetCounterNodeAlignment(LayoutWrapper* layoutWrapper)
429 {
430     bool isRTL = AceApplicationInfo::GetInstance().IsRightToLeft();
431     auto frameNode = layoutWrapper->GetHostNode();
432     CHECK_NULL_RETURN(frameNode, TextAlign::END);
433     RefPtr<LayoutProperty> property = frameNode->GetLayoutProperty();
434     CHECK_NULL_RETURN(property, TextAlign::END);
435     TextDirection layoutDirection = property->GetLayoutDirection();
436     if ((layoutDirection == TextDirection::RTL && !isRTL) ||
437         (layoutDirection == TextDirection::LTR && isRTL)) {
438         return TextAlign::START;
439     }
440     return TextAlign::END;
441 }
442 
UpdateCounterNode(uint32_t textLength,uint32_t maxLength,const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)443 void TextFieldLayoutAlgorithm::UpdateCounterNode(
444     uint32_t textLength, uint32_t maxLength, const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
445 {
446     auto frameNode = layoutWrapper->GetHostNode();
447     CHECK_NULL_VOID(frameNode);
448     auto pipeline = frameNode->GetContext();
449     CHECK_NULL_VOID(pipeline);
450     auto theme = pipeline->GetTheme<TextFieldTheme>();
451     CHECK_NULL_VOID(theme);
452     auto pattern = frameNode->GetPattern<TextFieldPattern>();
453     CHECK_NULL_VOID(pattern);
454     auto counterNode = pattern->GetCounterNode().Upgrade();
455     CHECK_NULL_VOID(counterNode);
456     auto textLayoutProperty = DynamicCast<TextLayoutProperty>(counterNode->GetLayoutProperty());
457     CHECK_NULL_VOID(textLayoutProperty);
458     auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
459     CHECK_NULL_VOID(textFieldLayoutProperty);
460 
461     std::string counterText;
462     TextStyle countTextStyle = (pattern->GetShowCounterStyleValue() && pattern->HasFocus()) ?
463                                 theme->GetOverCountTextStyle() :
464                                 theme->GetCountTextStyle();
465     auto counterType = textFieldLayoutProperty->GetSetCounterValue(DEFAULT_MODE);
466     auto limitSize = static_cast<uint32_t>(static_cast<int32_t>(maxLength) * counterType / SHOW_COUNTER_PERCENT);
467     if (counterType == DEFAULT_MODE || (textLength >= limitSize && counterType != DEFAULT_MODE)) {
468         counterText = std::to_string(textLength) + "/" + std::to_string(maxLength);
469     }
470     textLayoutProperty->UpdateContent(counterText);
471     textLayoutProperty->UpdateFontSize(countTextStyle.GetFontSize());
472     textLayoutProperty->UpdateTextColor(countTextStyle.GetTextColor());
473     textLayoutProperty->UpdateFontWeight(countTextStyle.GetFontWeight());
474     textLayoutProperty->UpdateTextAlign(GetCounterNodeAlignment(layoutWrapper));
475     textLayoutProperty->UpdateMaxLines(COUNTER_TEXT_MAXLINE);
476     auto host = counterNode->GetHostNode();
477     CHECK_NULL_VOID(host);
478     auto context = host->GetRenderContext();
479     CHECK_NULL_VOID(context);
480     context->UpdateForegroundColor(countTextStyle.GetTextColor());
481     host->Measure(contentConstraint);
482 }
483 
CounterLayout(LayoutWrapper * layoutWrapper)484 void TextFieldLayoutAlgorithm::CounterLayout(LayoutWrapper* layoutWrapper)
485 {
486     RefPtr<FrameNode> frameNode = layoutWrapper->GetHostNode();
487     CHECK_NULL_VOID(frameNode);
488     RefPtr<TextFieldPattern> pattern = frameNode->GetPattern<TextFieldPattern>();
489     RefPtr<LayoutWrapper> counterNode = pattern->GetCounterNode().Upgrade();
490     bool isInlineStyle = pattern->IsNormalInlineState();
491     bool isShowPassword = pattern->IsShowPasswordIcon();
492     if (counterNode && !isShowPassword && !isInlineStyle) {
493         HandleCounterLayout(layoutWrapper, counterNode, pattern);
494     }
495 }
496 
HandleCounterLayout(LayoutWrapper * layoutWrapper,const RefPtr<LayoutWrapper> & counterNode,const RefPtr<TextFieldPattern> & pattern)497 void TextFieldLayoutAlgorithm::HandleCounterLayout(LayoutWrapper* layoutWrapper,
498     const RefPtr<LayoutWrapper>& counterNode, const RefPtr<TextFieldPattern>& pattern)
499 {
500     auto frameNode = layoutWrapper->GetHostNode();
501     CHECK_NULL_VOID(frameNode);
502     RefPtr<GeometryNode> textGeometryNode = counterNode->GetGeometryNode();
503     CHECK_NULL_VOID(textGeometryNode);
504     const auto &content = layoutWrapper->GetGeometryNode()->GetContent();
505     CHECK_NULL_VOID(content);
506     RefPtr<LayoutProperty> property = frameNode->GetLayoutProperty();
507     CHECK_NULL_VOID(property);
508     bool isRTL = property->GetNonAutoLayoutDirection() == TextDirection::RTL;
509     float countX = 0;
510     if (!pattern->IsTextArea()) {
511         HandleNonTextArea(layoutWrapper, counterNode, pattern, isRTL, countX);
512     } else {
513         HandleTextArea(layoutWrapper, counterNode, pattern, isRTL, countX);
514     }
515 }
516 
HandleNonTextArea(LayoutWrapper * layoutWrapper,const RefPtr<LayoutWrapper> & counterNode,const RefPtr<TextFieldPattern> & pattern,bool isRTL,float & countX)517 void TextFieldLayoutAlgorithm::HandleNonTextArea(LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& counterNode,
518     const RefPtr<TextFieldPattern>& pattern, bool isRTL, float& countX)
519 {
520     RectF frameRect = layoutWrapper->GetGeometryNode()->GetFrameRect();
521     RectF contentRect = layoutWrapper->GetGeometryNode()->GetContentRect();
522     RefPtr<GeometryNode> textGeometryNode = counterNode->GetGeometryNode();
523     CHECK_NULL_VOID(textGeometryNode);
524     auto host = layoutWrapper->GetHostNode();
525     CHECK_NULL_VOID(host);
526     auto pipeline = host->GetContext();
527     CHECK_NULL_VOID(pipeline);
528 
529     countX = contentRect.GetX();
530     auto responseArea = pattern->GetResponseArea();
531     auto cleanNodeResponseArea = pattern->GetCleanNodeResponseArea();
532     if (responseArea) {
533         if (isRTL) {
534             countX -= responseArea->GetAreaRect().Width();
535         } else {
536             countX += responseArea->GetAreaRect().Width();
537         }
538     }
539     if (cleanNodeResponseArea) {
540         if (isRTL) {
541             countX -= cleanNodeResponseArea->GetAreaRect().Width();
542         } else {
543             countX += cleanNodeResponseArea->GetAreaRect().Width();
544         }
545     }
546     auto curFontScale = pipeline->GetFontScale();
547     auto countY = (NearEqual(curFontScale, 1.0f)) ? (frameRect.Height() + textGeometryNode->GetFrameRect().Height()) :
548         (frameRect.Bottom() - frameRect.Top() + COUNTER_TEXT_MARGIN_OFFSET.ConvertToPx());
549     textGeometryNode->SetFrameOffset(OffsetF(countX, countY));
550     counterNode->Layout();
551 }
552 
HandleTextArea(LayoutWrapper * layoutWrapper,const RefPtr<LayoutWrapper> & counterNode,const RefPtr<TextFieldPattern> & pattern,bool isRTL,float & countX)553 void TextFieldLayoutAlgorithm::HandleTextArea(LayoutWrapper* layoutWrapper, const RefPtr<LayoutWrapper>& counterNode,
554     const RefPtr<TextFieldPattern>& pattern, bool isRTL, float& countX)
555 {
556     const std::unique_ptr<GeometryProperty> &content = layoutWrapper->GetGeometryNode()->GetContent();
557     RefPtr<GeometryNode> counterGeometryNode = counterNode->GetGeometryNode();
558     CHECK_NULL_VOID(counterGeometryNode);
559     RectF frameRect = layoutWrapper->GetGeometryNode()->GetFrameRect();
560     countX = content->GetRect().GetX();
561     counterGeometryNode->SetFrameOffset(OffsetF(countX,
562         frameRect.Height() - pattern->GetPaddingBottom() - counterGeometryNode->GetFrameRect().Height()));
563     counterNode->Layout();
564 }
565 
CounterNodeMeasure(float contentWidth,LayoutWrapper * layoutWrapper)566 float TextFieldLayoutAlgorithm::CounterNodeMeasure(float contentWidth, LayoutWrapper* layoutWrapper)
567 {
568     auto frameNode = layoutWrapper->GetHostNode();
569     CHECK_NULL_RETURN(frameNode, 0.0f);
570     auto pattern = frameNode->GetPattern<TextFieldPattern>();
571     CHECK_NULL_RETURN(pattern, 0.0f);
572     auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
573     CHECK_NULL_RETURN(textFieldLayoutProperty, 0.0f);
574     auto isInlineStyle = pattern->IsNormalInlineState();
575     auto isShowPassword = pattern->IsShowPasswordIcon();
576     if (textFieldLayoutProperty->GetShowCounterValue(false) && textFieldLayoutProperty->HasMaxLength() &&
577         !isInlineStyle && !isShowPassword) {
578         auto counterNode = DynamicCast<UINode>(pattern->GetCounterNode().Upgrade());
579         CHECK_NULL_RETURN(counterNode, 0.0f);
580         auto counterNodeLayoutWrapper = layoutWrapper->GetOrCreateChildByIndex(frameNode->GetChildIndex(counterNode));
581         if (counterNodeLayoutWrapper) {
582             auto textLength =
583                 static_cast<uint32_t>(showPlaceHolder_ ? 0 : StringUtils::ToWstring(textContent_).length());
584             auto maxLength = static_cast<uint32_t>(textFieldLayoutProperty->GetMaxLength().value());
585             LayoutConstraintF textContentConstraint;
586             textContentConstraint.UpdateIllegalSelfIdealSizeWithCheck(OptionalSizeF(contentWidth, std::nullopt));
587             UpdateCounterNode(textLength, maxLength, textContentConstraint, layoutWrapper);
588             return counterNodeLayoutWrapper->GetGeometryNode()->GetFrameSize().Height();
589         }
590     }
591     return 0.0f;
592 }
593 
GetVisualTextWidth() const594 float TextFieldLayoutAlgorithm::GetVisualTextWidth() const
595 {
596     return std::min(paragraph_->GetMaxWidth(), std::max(0.0f, paragraph_->GetLongestLine()));
597 }
598 
UpdateTextStyle(const RefPtr<FrameNode> & frameNode,const RefPtr<TextFieldLayoutProperty> & layoutProperty,const RefPtr<TextFieldTheme> & theme,TextStyle & textStyle,bool isDisabled)599 void TextFieldLayoutAlgorithm::UpdateTextStyle(const RefPtr<FrameNode>& frameNode,
600     const RefPtr<TextFieldLayoutProperty>& layoutProperty, const RefPtr<TextFieldTheme>& theme,
601     TextStyle& textStyle, bool isDisabled)
602 {
603     CHECK_NULL_VOID(theme);
604     const std::vector<std::string> defaultFontFamily = { "sans-serif" };
605     textStyle.SetFontFamilies(layoutProperty->GetFontFamilyValue(defaultFontFamily));
606     FontRegisterCallback(frameNode, textStyle.GetFontFamilies());
607 
608     Dimension fontSize;
609     if (layoutProperty->HasFontSize() && layoutProperty->GetFontSize().value_or(Dimension()).IsNonNegative()) {
610         fontSize = layoutProperty->GetFontSizeValue(Dimension());
611     } else {
612         fontSize = theme->GetFontSize();
613     }
614     textStyle.SetFontSize(fontSize);
615     textStyle.SetTextAlign(layoutProperty->GetTextAlignValue(TextAlign::START));
616     textStyle.SetLineBreakStrategy(layoutProperty->GetLineBreakStrategyValue(LineBreakStrategy::GREEDY));
617     textStyle.SetFontWeight(layoutProperty->GetFontWeightValue(theme->GetFontWeight()));
618     auto renderContext = frameNode->GetRenderContext();
619     CHECK_NULL_VOID(renderContext);
620     if (renderContext->HasForegroundColor()) {
621         auto textColor = renderContext->GetForegroundColor().value();
622         if (isDisabled) {
623             textColor = textColor.BlendOpacity(theme->GetDisableOpacityRatio());
624         }
625         textStyle.SetTextColor(textColor);
626     } else if (renderContext->HasForegroundColorStrategy()) {
627         if (isDisabled) {
628             textStyle.SetTextColor(theme->GetDisableTextColor());
629         } else {
630             textStyle.SetTextColor(Color::BLACK);
631         }
632     } else {
633         if (isDisabled) {
634             textStyle.SetTextColor(theme->GetDisableTextColor());
635         } else {
636             textStyle.SetTextColor(layoutProperty->GetTextColorValue(theme->GetTextColor()));
637         }
638     }
639     if (layoutProperty->GetMaxLines()) {
640         textStyle.SetMaxLines(layoutProperty->GetMaxLines().value());
641     }
642     if (layoutProperty->HasItalicFontStyle()) {
643         textStyle.SetFontStyle(layoutProperty->GetItalicFontStyle().value());
644     }
645     if (layoutProperty->HasTextAlign()) {
646         textStyle.SetTextAlign(layoutProperty->GetTextAlign().value());
647     }
648     if (layoutProperty->HasTextIndent()) {
649         textStyle.SetTextIndent(layoutProperty->GetTextIndent().value());
650     }
651     UpdateTextStyleMore(frameNode, layoutProperty, textStyle, isDisabled);
652 }
653 
UpdatePlaceholderTextStyle(const RefPtr<FrameNode> & frameNode,const RefPtr<TextFieldLayoutProperty> & layoutProperty,const RefPtr<TextFieldTheme> & theme,TextStyle & textStyle,bool isDisabled)654 void TextFieldLayoutAlgorithm::UpdatePlaceholderTextStyle(const RefPtr<FrameNode>& frameNode,
655     const RefPtr<TextFieldLayoutProperty>& layoutProperty, const RefPtr<TextFieldTheme>& theme, TextStyle& textStyle,
656     bool isDisabled)
657 {
658     CHECK_NULL_VOID(theme);
659     const std::vector<std::string> defaultFontFamily = { "sans-serif" };
660     textStyle.SetFontFamilies(layoutProperty->GetPlaceholderFontFamilyValue(defaultFontFamily));
661     FontRegisterCallback(frameNode, textStyle.GetFontFamilies());
662 
663     Dimension fontSize;
664     if (layoutProperty->GetPlaceholderValue("").empty()) {
665         if (layoutProperty->HasFontSize() && layoutProperty->GetFontSize().value_or(Dimension()).IsNonNegative()) {
666             fontSize = layoutProperty->GetFontSizeValue(Dimension());
667         } else {
668             fontSize = theme->GetFontSize();
669         }
670     } else {
671         if (layoutProperty->HasPlaceholderFontSize() &&
672             layoutProperty->GetPlaceholderFontSize().value_or(Dimension()).IsNonNegative()) {
673             fontSize = layoutProperty->GetPlaceholderFontSizeValue(Dimension());
674         } else {
675             fontSize = theme->GetFontSize();
676         }
677     }
678 
679     textStyle.SetFontSize(fontSize);
680     textStyle.SetFontWeight(layoutProperty->GetPlaceholderFontWeightValue(theme->GetFontWeight()));
681     if (layoutProperty->HasPlaceholderTextColor()) {
682         auto textColor = layoutProperty->GetPlaceholderTextColorValue(theme->GetPlaceholderColor());
683         if (isDisabled) {
684             textColor = textColor.BlendOpacity(theme->GetDisableOpacityRatio());
685         }
686         textStyle.SetTextColor(textColor);
687     } else {
688         if (isDisabled) {
689             textStyle.SetTextColor(theme->GetDisableTextColor());
690         } else {
691             textStyle.SetTextColor(theme->GetPlaceholderColor());
692         }
693     }
694     if (layoutProperty->HasPlaceholderMaxLines()) {
695         textStyle.SetMaxLines(layoutProperty->GetPlaceholderMaxLines().value());
696     }
697     if (layoutProperty->HasPlaceholderItalicFontStyle()) {
698         textStyle.SetFontStyle(layoutProperty->GetPlaceholderItalicFontStyle().value());
699     }
700     if (layoutProperty->HasPlaceholderTextAlign()) {
701         textStyle.SetTextAlign(layoutProperty->GetPlaceholderTextAlign().value());
702     }
703     textStyle.SetTextOverflow(TextOverflow::ELLIPSIS);
704     textStyle.SetTextAlign(layoutProperty->GetTextAlignValue(TextAlign::START));
705     UpdatePlaceholderTextStyleMore(frameNode, layoutProperty, theme, textStyle, isDisabled);
706 }
707 
CalculateContentMaxSizeWithCalculateConstraint(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)708 LayoutConstraintF TextFieldLayoutAlgorithm::CalculateContentMaxSizeWithCalculateConstraint(
709     const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
710 {
711     auto textFieldContentConstraint = contentConstraint;
712     auto frameNode = layoutWrapper->GetHostNode();
713     CHECK_NULL_RETURN(frameNode, textFieldContentConstraint);
714     auto pattern = frameNode->GetPattern<TextFieldPattern>();
715     CHECK_NULL_RETURN(pattern, textFieldContentConstraint);
716     auto idealWidth = contentConstraint.selfIdealSize.Width().value_or(contentConstraint.maxSize.Width());
717     auto idealHeight = contentConstraint.selfIdealSize.Height().value_or(contentConstraint.maxSize.Height());
718     auto maxIdealSize = SizeF { idealWidth, idealHeight };
719     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN) &&
720         !layoutWrapper->GetLayoutProperty()->GetLayoutRect()) {
721         auto frameIdealSize = maxIdealSize + SizeF(pattern->GetHorizontalPaddingAndBorderSum(),
722                                                  pattern->GetVerticalPaddingAndBorderSum());
723         auto finalSize = UpdateOptionSizeByCalcLayoutConstraint(static_cast<OptionalSize<float>>(frameIdealSize),
724             layoutWrapper->GetLayoutProperty()->GetCalcLayoutConstraint(),
725             layoutWrapper->GetLayoutProperty()->GetLayoutConstraint()->percentReference);
726         finalSize.SetWidth(
727             finalSize.Width().value_or(frameIdealSize.Width()) - pattern->GetHorizontalPaddingAndBorderSum());
728         finalSize.SetHeight(
729             finalSize.Height().value_or(frameIdealSize.Height()) - pattern->GetVerticalPaddingAndBorderSum());
730         maxIdealSize.UpdateSizeWhenSmaller(finalSize.ConvertToSizeT());
731         maxIdealSize.UpdateSizeWhenLarger(textFieldContentConstraint.minSize);
732     }
733     textFieldContentConstraint.maxSize = maxIdealSize;
734     return textFieldContentConstraint;
735 }
736 
CalculateFrameSizeConstraint(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)737 LayoutConstraintF TextFieldLayoutAlgorithm::CalculateFrameSizeConstraint(
738     const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
739 {
740     LayoutConstraintF frameSizeConstraintF = contentConstraint;
741     auto frameNode = layoutWrapper->GetHostNode();
742     CHECK_NULL_RETURN(frameNode, frameSizeConstraintF);
743     auto pattern = frameNode->GetPattern<TextFieldPattern>();
744     CHECK_NULL_RETURN(pattern, frameSizeConstraintF);
745     auto border = pattern->GetBorderWidthProperty();
746     auto left = pattern->GetBorderLeft(border) + pattern->GetPaddingLeft();
747     auto right = pattern->GetBorderRight(border) + pattern->GetPaddingRight();
748     auto top = pattern->GetBorderTop(border) + pattern->GetPaddingTop();
749     auto bottom = pattern->GetBorderBottom(border) + pattern->GetPaddingBottom();
750     frameSizeConstraintF.maxSize.AddPadding(left, right, top, bottom);
751     frameSizeConstraintF.minSize.AddPadding(left, right, top, bottom);
752     return frameSizeConstraintF;
753 }
754 
FontRegisterCallback(const RefPtr<FrameNode> & frameNode,const std::vector<std::string> & fontFamilies)755 void TextFieldLayoutAlgorithm::FontRegisterCallback(
756     const RefPtr<FrameNode>& frameNode, const std::vector<std::string>& fontFamilies)
757 {
758     auto callback = [weakNode = WeakPtr<FrameNode>(frameNode)] {
759         auto frameNode = weakNode.Upgrade();
760         CHECK_NULL_VOID(frameNode);
761         frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
762         auto pattern = frameNode->GetPattern<TextFieldPattern>();
763         CHECK_NULL_VOID(pattern);
764         auto modifier = DynamicCast<TextFieldContentModifier>(pattern->GetContentModifier());
765         CHECK_NULL_VOID(modifier);
766         modifier->SetFontReady(true);
767     };
768     auto pipeline = frameNode->GetContext();
769     CHECK_NULL_VOID(pipeline);
770     auto fontManager = pipeline->GetFontManager();
771     if (fontManager) {
772         bool isCustomFont = false;
773         for (const auto& familyName : fontFamilies) {
774             bool customFont = fontManager->RegisterCallbackNG(frameNode, familyName, callback);
775             if (customFont) {
776                 isCustomFont = true;
777             }
778         }
779         if (isCustomFont || fontManager->IsDefaultFontChanged()) {
780             auto pattern = frameNode->GetPattern<TextFieldPattern>();
781             CHECK_NULL_VOID(pattern);
782             pattern->SetIsCustomFont(true);
783             auto modifier = DynamicCast<TextFieldContentModifier>(pattern->GetContentModifier());
784             CHECK_NULL_VOID(modifier);
785             modifier->SetIsCustomFont(true);
786         }
787     }
788 }
789 
GetParagraphStyle(const TextStyle & textStyle,const std::string & content,const float fontSize) const790 ParagraphStyle TextFieldLayoutAlgorithm::GetParagraphStyle(
791     const TextStyle& textStyle, const std::string& content, const float fontSize) const
792 {
793     return {
794         .direction = GetTextDirection(content, direction_),
795         .maxLines = textStyle.GetMaxLines(),
796         .fontLocale = Localization::GetInstance()->GetFontLocale(),
797         .wordBreak = textStyle.GetWordBreak(),
798         .lineBreakStrategy = textStyle.GetLineBreakStrategy(),
799         .textOverflow = textStyle.GetTextOverflow(),
800         .fontSize = fontSize
801     };
802 }
803 
CreateParagraph(const TextStyle & textStyle,std::string content,bool needObscureText,int32_t nakedCharPosition,CreateParagraphData paragraphData)804 void TextFieldLayoutAlgorithm::CreateParagraph(const TextStyle& textStyle, std::string content, bool needObscureText,
805     int32_t nakedCharPosition, CreateParagraphData paragraphData)
806 {
807     auto paraStyle = GetParagraphStyle(textStyle, content, paragraphData.fontSize);
808     if (!paragraphData.disableTextAlign) {
809         paraStyle.align = textStyle.GetTextAlign();
810     }
811     paragraph_ = Paragraph::Create(paraStyle, FontCollection::Current());
812     CHECK_NULL_VOID(paragraph_);
813     paragraph_->PushStyle(textStyle);
814     StringUtils::TransformStrCase(content, static_cast<int32_t>(textStyle.GetTextCase()));
815     auto pipeline = PipelineBase::GetCurrentContextSafely();
816     CHECK_NULL_VOID(pipeline);
817     auto theme = pipeline->GetTheme<TextFieldTheme>();
818     CHECK_NULL_VOID(theme);
819     auto displayText = TextFieldPattern::CreateDisplayText(content, nakedCharPosition,
820         needObscureText, theme->IsShowPasswordDirectly());
821     paragraph_->AddText(displayText);
822     paragraph_->Build();
823 }
824 
CreateParagraph(const TextStyle & textStyle,const std::vector<std::string> & contents,const std::string & content,bool needObscureText,CreateParagraphData paragraphData)825 void TextFieldLayoutAlgorithm::CreateParagraph(const TextStyle& textStyle, const std::vector<std::string>& contents,
826     const std::string& content, bool needObscureText, CreateParagraphData paragraphData)
827 {
828     TextStyle dragTextStyle = textStyle;
829     Color color = textStyle.GetTextColor().ChangeAlpha(DRAGGED_TEXT_TRANSPARENCY);
830     dragTextStyle.SetTextColor(color);
831     std::vector<TextStyle> textStyles { textStyle, dragTextStyle, textStyle };
832 
833     auto style = textStyles.begin();
834     ParagraphStyle paraStyle { .direction = GetTextDirection(content, direction_),
835         .maxLines = style->GetMaxLines(),
836         .fontLocale = Localization::GetInstance()->GetFontLocale(),
837         .wordBreak = style->GetWordBreak(),
838         .lineBreakStrategy = textStyle.GetLineBreakStrategy(),
839         .textOverflow = style->GetTextOverflow(),
840         .fontSize = paragraphData.fontSize };
841     if (!paragraphData.disableTextAlign) {
842         paraStyle.align = style->GetTextAlign();
843     }
844     paragraph_ = Paragraph::Create(paraStyle, FontCollection::Current());
845     CHECK_NULL_VOID(paragraph_);
846     for (size_t i = 0; i < contents.size(); i++) {
847         std::string splitStr = contents[i];
848         if (splitStr.empty()) {
849             continue;
850         }
851         if (style->GetMaxLines() == 1) {
852             std::replace(splitStr.begin(), splitStr.end(), '\n', ' ');
853         }
854         auto& style = textStyles[i];
855         paragraph_->PushStyle(style);
856         StringUtils::TransformStrCase(splitStr, static_cast<int32_t>(style.GetTextCase()));
857         if (needObscureText) {
858             paragraph_->AddText(
859                 TextFieldPattern::CreateObscuredText(static_cast<int32_t>(StringUtils::ToWstring(splitStr).length())));
860         } else {
861             paragraph_->AddText(StringUtils::Str8ToStr16(splitStr));
862         }
863         paragraph_->PopStyle();
864     }
865     paragraph_->Build();
866 }
867 
CreateInlineParagraph(const TextStyle & textStyle,std::string content,bool needObscureText,int32_t nakedCharPosition,CreateParagraphData paragraphData)868 void TextFieldLayoutAlgorithm::CreateInlineParagraph(const TextStyle& textStyle, std::string content,
869     bool needObscureText, int32_t nakedCharPosition, CreateParagraphData paragraphData)
870 {
871     auto paraStyle = GetParagraphStyle(textStyle, content, paragraphData.fontSize);
872     if (!paragraphData.disableTextAlign) {
873         paraStyle.align = textStyle.GetTextAlign();
874     }
875     paraStyle.maxLines = -1;
876     inlineParagraph_ = Paragraph::Create(paraStyle, FontCollection::Current());
877     CHECK_NULL_VOID(paragraph_);
878     inlineParagraph_->PushStyle(textStyle);
879     StringUtils::TransformStrCase(content, static_cast<int32_t>(textStyle.GetTextCase()));
880     auto pipeline = PipelineBase::GetCurrentContextSafely();
881     CHECK_NULL_VOID(pipeline);
882     auto theme = pipeline->GetTheme<TextFieldTheme>();
883     CHECK_NULL_VOID(theme);
884     auto displayText = TextFieldPattern::CreateDisplayText(content, nakedCharPosition,
885         needObscureText, theme->IsShowPasswordDirectly());
886     inlineParagraph_->AddText(displayText);
887     inlineParagraph_->Build();
888 }
889 
GetTextDirection(const std::string & content,TextDirection direction)890 TextDirection TextFieldLayoutAlgorithm::GetTextDirection(const std::string& content, TextDirection direction)
891 {
892     if (direction == TextDirection::LTR || direction == TextDirection::RTL) {
893         return direction;
894     }
895 
896     bool isRTL = AceApplicationInfo::GetInstance().IsRightToLeft();
897     auto textDirection = isRTL ? TextDirection::RTL : TextDirection::LTR;
898     auto showingTextForWString = StringUtils::ToWstring(content);
899     for (const auto& charOfShowingText : showingTextForWString) {
900         if (TextLayoutadapter::IsLeftToRight(charOfShowingText)) {
901             return TextDirection::LTR;
902         }
903         if (TextLayoutadapter::IsRightToLeft(charOfShowingText) ||
904             TextLayoutadapter::IsRightTOLeftArabic(charOfShowingText)) {
905             return TextDirection::RTL;
906         }
907     }
908     return textDirection;
909 }
910 
GetParagraph() const911 RefPtr<Paragraph> TextFieldLayoutAlgorithm::GetParagraph() const
912 {
913     return paragraph_;
914 }
915 
GetSuitableSize(SizeF & maxSize,LayoutWrapper * layoutWrapper)916 void TextFieldLayoutAlgorithm::GetSuitableSize(SizeF& maxSize, LayoutWrapper* layoutWrapper)
917 {
918     auto frameNode = layoutWrapper->GetHostNode();
919     CHECK_NULL_VOID(frameNode);
920     auto pattern = frameNode->GetPattern<TextFieldPattern>();
921     CHECK_NULL_VOID(pattern);
922     auto textFieldTheme = pattern->GetTheme();
923     CHECK_NULL_VOID(textFieldTheme);
924     auto safeBoundary = textFieldTheme->GetInlineBorderWidth().ConvertToPx() * 2;
925     if (pattern->HasFocus() && pattern->IsInlineMode()) {
926         maxSize.SetWidth(maxSize.Width() - static_cast<float>(safeBoundary) - PARAGRAPH_SAVE_BOUNDARY);
927     }
928 }
929 
GetTextFieldDefaultHeight()930 float TextFieldLayoutAlgorithm::GetTextFieldDefaultHeight()
931 {
932     auto pipeline = PipelineContext::GetCurrentContextSafely();
933     CHECK_NULL_RETURN(pipeline, 0.0f);
934     auto textFieldTheme = pipeline->GetTheme<TextFieldTheme>();
935     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
936     auto height = textFieldTheme->GetHeight();
937     return static_cast<float>(height.ConvertToPx());
938 }
939 
SetPropertyToModifier(const TextStyle & textStyle,RefPtr<TextFieldContentModifier> modifier)940 void TextFieldLayoutAlgorithm::SetPropertyToModifier(
941     const TextStyle& textStyle, RefPtr<TextFieldContentModifier> modifier)
942 {
943     CHECK_NULL_VOID(modifier);
944     modifier->SetFontFamilies(textStyle.GetFontFamilies());
945     modifier->SetFontSize(textStyle.GetFontSize());
946     if (textStyle.GetAdaptTextSize()) {
947         modifier->SetAdaptMinFontSize(textStyle.GetAdaptMinFontSize());
948         modifier->SetAdaptMaxFontSize(textStyle.GetAdaptMaxFontSize());
949     }
950     modifier->SetFontWeight(textStyle.GetFontWeight());
951     modifier->SetTextColor(textStyle.GetTextColor());
952     modifier->SetFontStyle(textStyle.GetFontStyle());
953     modifier->SetTextOverflow(textStyle.GetTextOverflow());
954     modifier->SetTextDecoration(textStyle.GetTextDecoration(), textStyle.GetTextDecorationColor(),
955         textStyle.GetTextDecorationStyle());
956 }
957 
UpdateUnitLayout(LayoutWrapper * layoutWrapper)958 void TextFieldLayoutAlgorithm::UpdateUnitLayout(LayoutWrapper* layoutWrapper)
959 {
960     auto frameNode = layoutWrapper->GetHostNode();
961     CHECK_NULL_VOID(frameNode);
962     auto pattern = frameNode->GetPattern<TextFieldPattern>();
963     CHECK_NULL_VOID(pattern);
964     auto children = frameNode->GetChildren();
965     const auto& content = layoutWrapper->GetGeometryNode()->GetContent();
966     CHECK_NULL_VOID(content);
967     auto contentSize = content->GetRect().GetSize();
968     auto size = layoutWrapper->GetGeometryNode()->GetFrameSize();
969     auto layoutProperty = AceType::DynamicCast<TextFieldLayoutProperty>(layoutWrapper->GetLayoutProperty());
970     CHECK_NULL_VOID(layoutProperty);
971     if (!children.empty() && layoutProperty->GetShowUnderlineValue(false) &&
972         layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::UNSPECIFIED) {
973         auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(0);
974         CHECK_NULL_VOID(childWrapper);
975         auto textGeometryNode = childWrapper->GetGeometryNode();
976         CHECK_NULL_VOID(textGeometryNode);
977         auto childFrameSize = textGeometryNode->GetFrameSize();
978         unitWidth_ = childFrameSize.Width();
979         textGeometryNode->SetFrameOffset(
980             OffsetF({ content->GetRect().GetX() + contentSize.Width() - childFrameSize.Width(), 0.0 }));
981         if (childFrameSize.Height() < size.Height()) {
982             childWrapper->GetGeometryNode()->SetFrameSize(SizeF({ unitWidth_, size.Height() }));
983         }
984         childWrapper->Layout();
985     }
986 }
987 
AddAdaptFontSizeAndAnimations(TextStyle & textStyle,const RefPtr<TextFieldLayoutProperty> & layoutProperty,const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)988 bool TextFieldLayoutAlgorithm::AddAdaptFontSizeAndAnimations(TextStyle& textStyle,
989     const RefPtr<TextFieldLayoutProperty>& layoutProperty, const LayoutConstraintF& contentConstraint,
990     LayoutWrapper* layoutWrapper)
991 {
992     auto frameNode = layoutWrapper->GetHostNode();
993     CHECK_NULL_RETURN(frameNode, false);
994     auto pattern = frameNode->GetPattern<TextFieldPattern>();
995     CHECK_NULL_RETURN(pattern, false);
996     bool hasHeightOverride = textStyle.HasHeightOverride();
997     auto lineHeight = textStyle.GetLineHeight();
998     SetAdaptFontSizeLineHeight(lineHeight, textStyle);
999     textStyle.SetLineHeight(Dimension(), false);
1000     bool result = false;
1001     const std::string& text = textContent_.empty() ? "a" : textContent_;
1002     switch (layoutProperty->GetHeightAdaptivePolicyValue(TextHeightAdaptivePolicy::MAX_LINES_FIRST)) {
1003         case TextHeightAdaptivePolicy::MAX_LINES_FIRST:
1004             if (pattern->IsInlineMode()) {
1005                 result = AdaptInlineFocusMinFontSize(textStyle, text, 1.0_fp, contentConstraint, layoutWrapper);
1006             } else {
1007                 result = AdaptMinFontSize(textStyle, text, 1.0_fp, contentConstraint, layoutWrapper);
1008             }
1009             break;
1010         case TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST:
1011             if (pattern->IsInlineMode()) {
1012                 result = AdaptInlineFocusFontSize(textStyle, text, 1.0_fp, contentConstraint, layoutWrapper);
1013             } else {
1014                 result = AdaptMinFontSize(textStyle, text, 1.0_fp, contentConstraint, layoutWrapper);
1015             }
1016             break;
1017         case TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST:
1018             if (pattern->IsInlineMode()) {
1019                 result = AdaptInlineFocusFontSize(textStyle, text, 1.0_fp, contentConstraint, layoutWrapper);
1020             } else {
1021                 result = AdaptMaxFontSize(textStyle, text, 1.0_fp, contentConstraint, layoutWrapper);
1022             }
1023             break;
1024         default:
1025             break;
1026     }
1027     textStyle.SetLineHeight(lineHeight, hasHeightOverride);
1028     if (result && (hasHeightOverride || textContent_.empty())) {
1029         return CreateParagraphAndLayout(textStyle, textContent_, contentConstraint, layoutWrapper, false);
1030     }
1031     return result;
1032 }
1033 
IsNeedAdaptFontSize(const TextStyle & textStyle,const RefPtr<TextFieldLayoutProperty> & layoutProperty,const LayoutConstraintF & contentConstraint)1034 bool TextFieldLayoutAlgorithm::IsNeedAdaptFontSize(const TextStyle& textStyle,
1035     const RefPtr<TextFieldLayoutProperty>& layoutProperty, const LayoutConstraintF& contentConstraint)
1036 {
1037     if (!textStyle.GetAdaptTextSize()) {
1038         return false;
1039     }
1040     auto adaptivePolicy = layoutProperty->GetHeightAdaptivePolicyValue(TextHeightAdaptivePolicy::MAX_LINES_FIRST);
1041     if ((adaptivePolicy != TextHeightAdaptivePolicy::MAX_LINES_FIRST) &&
1042         (adaptivePolicy != TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST) &&
1043         (adaptivePolicy != TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST)) {
1044         return false;
1045     }
1046     return TextAdaptFontSizer::IsNeedAdaptFontSize(textStyle, contentConstraint);
1047 }
1048 
AdaptInlineFocusFontSize(TextStyle & textStyle,const std::string & content,const Dimension & stepUnit,const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)1049 bool TextFieldLayoutAlgorithm::AdaptInlineFocusFontSize(TextStyle& textStyle, const std::string& content,
1050     const Dimension& stepUnit, const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
1051 {
1052     double maxFontSize = 0.0;
1053     double minFontSize = 0.0;
1054     GetAdaptMaxMinFontSize(textStyle, maxFontSize, minFontSize, contentConstraint);
1055     if (LessNotEqual(maxFontSize, minFontSize) || LessOrEqual(minFontSize, 0.0)) {
1056         return CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper, false);
1057     }
1058     double stepSize = 0.0;
1059     GetAdaptFontSizeStep(textStyle, stepSize, stepUnit, contentConstraint);
1060     auto tag = static_cast<int32_t>((maxFontSize - minFontSize) / stepSize);
1061     auto length = tag + 1 + (GreatNotEqual(maxFontSize, minFontSize + stepSize * tag) ? 1 : 0);
1062     int32_t left = 0;
1063     int32_t right = length - 1;
1064     float fontSize = 0.0f;
1065     auto newContentConstraint = BuildInfinityLayoutConstraint(contentConstraint);
1066     auto maxSize = GetMaxMeasureSize(contentConstraint);
1067     GetSuitableSize(maxSize, layoutWrapper);
1068     while (left <= right) {
1069         int32_t mid = left + (right - left) / 2;
1070         fontSize = static_cast<float>((mid == length - 1) ? (maxFontSize) : (minFontSize + stepSize * mid));
1071         textStyle.SetFontSize(Dimension(fontSize));
1072         if (!CreateParagraphAndLayout(textStyle, content, newContentConstraint, layoutWrapper)) {
1073             return false;
1074         }
1075         if (!IsInlineFocusAdaptExceedLimit(maxSize)) {
1076             left = mid + 1;
1077         } else {
1078             right = mid - 1;
1079         }
1080     }
1081     fontSize = static_cast<float>((left - 1 == length - 1) ? (maxFontSize) : (minFontSize + stepSize * (left - 1)));
1082     fontSize = LessNotEqual(fontSize, minFontSize) ? minFontSize : fontSize;
1083     fontSize = GreatNotEqual(fontSize, maxFontSize) ? maxFontSize : fontSize;
1084     textStyle.SetFontSize(Dimension(fontSize));
1085     return CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper);
1086 }
1087 
BuildInfinityLayoutConstraint(const LayoutConstraintF & contentConstraint)1088 LayoutConstraintF TextFieldLayoutAlgorithm::BuildInfinityLayoutConstraint(const LayoutConstraintF& contentConstraint)
1089 {
1090     auto newContentConstraint = contentConstraint;
1091     newContentConstraint.maxSize = { std::numeric_limits<double>::infinity(),
1092         std::numeric_limits<double>::infinity() };
1093     if (newContentConstraint.selfIdealSize.Width()) {
1094         newContentConstraint.selfIdealSize.SetWidth(std::numeric_limits<double>::infinity());
1095     }
1096     if (newContentConstraint.selfIdealSize.Height()) {
1097         newContentConstraint.selfIdealSize.SetHeight(std::numeric_limits<double>::infinity());
1098     }
1099     return newContentConstraint;
1100 }
1101 
IsInlineFocusAdaptExceedLimit(const SizeF & maxSize)1102 bool TextFieldLayoutAlgorithm::IsInlineFocusAdaptExceedLimit(const SizeF& maxSize)
1103 {
1104     auto paragraph = GetParagraph();
1105     CHECK_NULL_RETURN(paragraph, false);
1106     bool didExceedMaxLines = false;
1107     didExceedMaxLines = didExceedMaxLines || GreatNotEqual(paragraph->GetHeight() / paragraph->GetLineCount(),
1108         maxSize.Height());
1109     didExceedMaxLines = didExceedMaxLines || GreatNotEqual(paragraph->GetLongestLine(), maxSize.Width());
1110     didExceedMaxLines = didExceedMaxLines || IsAdaptFontSizeExceedLineHeight(paragraph);
1111     return didExceedMaxLines;
1112 }
1113 
AdaptInlineFocusMinFontSize(TextStyle & textStyle,const std::string & content,const Dimension & stepUnit,const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)1114 bool TextFieldLayoutAlgorithm::AdaptInlineFocusMinFontSize(TextStyle& textStyle, const std::string& content,
1115     const Dimension& stepUnit, const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
1116 {
1117     double maxFontSize = 0.0;
1118     double minFontSize = 0.0;
1119     GetAdaptMaxMinFontSize(textStyle, maxFontSize, minFontSize, contentConstraint);
1120     if (LessNotEqual(maxFontSize, minFontSize) || LessOrEqual(minFontSize, 0.0)) {
1121         return CreateParagraphAndLayout(textStyle, content, contentConstraint, layoutWrapper, false);
1122     }
1123     double stepSize = 0.0;
1124     GetAdaptFontSizeStep(textStyle, stepSize, stepUnit, contentConstraint);
1125     auto textFieldLayoutProperty = DynamicCast<TextFieldLayoutProperty>(layoutWrapper->GetLayoutProperty());
1126     CHECK_NULL_RETURN(textFieldLayoutProperty, false);
1127     auto maxViewLines = textFieldLayoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE);
1128     auto newContentConstraint = BuildInlineFocusLayoutConstraint(contentConstraint, layoutWrapper);
1129     auto maxSize = GetMaxMeasureSize(contentConstraint);
1130     GetSuitableSize(maxSize, layoutWrapper);
1131     while (GreatOrEqual(maxFontSize, minFontSize)) {
1132         textStyle.SetFontSize(Dimension(maxFontSize));
1133         if (!CreateParagraphAndLayout(textStyle, content, newContentConstraint, layoutWrapper)) {
1134             return false;
1135         }
1136         if (!IsInlineFocusAdaptMinExceedLimit(maxSize, maxViewLines)) {
1137             break;
1138         }
1139         maxFontSize -= stepSize;
1140     }
1141     return true;
1142 }
1143 
BuildInlineFocusLayoutConstraint(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper)1144 LayoutConstraintF TextFieldLayoutAlgorithm::BuildInlineFocusLayoutConstraint(
1145     const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
1146 {
1147     auto frameNode = layoutWrapper->GetHostNode();
1148     CHECK_NULL_RETURN(frameNode, contentConstraint);
1149     auto pattern = frameNode->GetPattern<TextFieldPattern>();
1150     CHECK_NULL_RETURN(pattern, contentConstraint);
1151     auto textFieldTheme = pattern->GetTheme();
1152     CHECK_NULL_RETURN(textFieldTheme, contentConstraint);
1153     auto safeBoundary = textFieldTheme->GetInlineBorderWidth().ConvertToPx() * 2;
1154     auto inlineBoundary = static_cast<float>(safeBoundary) + PARAGRAPH_SAVE_BOUNDARY;
1155     auto newContentConstraint = contentConstraint;
1156     newContentConstraint.maxSize.SetWidth(newContentConstraint.maxSize.Width() - inlineBoundary);
1157     if (newContentConstraint.selfIdealSize.Width()) {
1158         newContentConstraint.selfIdealSize.SetWidth(newContentConstraint.selfIdealSize.Width().value() -
1159             inlineBoundary);
1160     }
1161     return newContentConstraint;
1162 }
1163 
IsInlineFocusAdaptMinExceedLimit(const SizeF & maxSize,uint32_t maxViewLines)1164 bool TextFieldLayoutAlgorithm::IsInlineFocusAdaptMinExceedLimit(const SizeF& maxSize, uint32_t maxViewLines)
1165 {
1166     auto paragraph = GetParagraph();
1167     CHECK_NULL_RETURN(paragraph, false);
1168     bool didExceedMaxLines = paragraph->DidExceedMaxLines();
1169     didExceedMaxLines = didExceedMaxLines || ((maxViewLines > 0) && (paragraph->GetLineCount() > maxViewLines));
1170     didExceedMaxLines = didExceedMaxLines || GreatNotEqual(paragraph->GetHeight() / paragraph->GetLineCount(),
1171         maxSize.Height());
1172     didExceedMaxLines = didExceedMaxLines || GreatNotEqual(paragraph->GetLongestLine(), maxSize.Width());
1173     didExceedMaxLines = didExceedMaxLines || IsAdaptFontSizeExceedLineHeight(paragraph);
1174     return didExceedMaxLines;
1175 }
1176 
CreateParagraphAndLayout(const TextStyle & textStyle,const std::string & content,const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper,bool needLayout)1177 bool TextFieldLayoutAlgorithm::CreateParagraphAndLayout(const TextStyle& textStyle, const std::string& content,
1178     const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper, bool needLayout)
1179 {
1180     if (!CreateParagraphEx(textStyle, content, contentConstraint, layoutWrapper)) {
1181         return false;
1182     }
1183     ACE_LAYOUT_SCOPED_TRACE("CreateParagraphAndLayout[needLayout:%d]", needLayout);
1184     if (needLayout) {
1185         CHECK_NULL_RETURN(paragraph_, false);
1186         auto maxSize = GetMaxMeasureSize(contentConstraint);
1187         ApplyIndent(layoutWrapper, maxSize.Width());
1188         paragraph_->Layout(std::max(0.0f, maxSize.Width()));
1189     }
1190     return true;
1191 }
1192 
UpdateTextStyleMore(const RefPtr<FrameNode> & frameNode,const RefPtr<TextFieldLayoutProperty> & layoutProperty,TextStyle & textStyle,bool isDisabled)1193 void TextFieldLayoutAlgorithm::UpdateTextStyleMore(const RefPtr<FrameNode>& frameNode,
1194     const RefPtr<TextFieldLayoutProperty>& layoutProperty, TextStyle& textStyle, bool isDisabled)
1195 {
1196     if (layoutProperty->HasAdaptMinFontSize()) {
1197         textStyle.SetAdaptMinFontSize(layoutProperty->GetAdaptMinFontSize().value());
1198     }
1199     if (layoutProperty->HasAdaptMaxFontSize()) {
1200         textStyle.SetAdaptMaxFontSize(layoutProperty->GetAdaptMaxFontSize().value());
1201     }
1202     auto pattern = frameNode->GetPattern<TextFieldPattern>();
1203     CHECK_NULL_VOID(pattern);
1204     auto pipeline = frameNode->GetContext();
1205     CHECK_NULL_VOID(pipeline);
1206     if (pattern->IsInPasswordMode()) {
1207         return;
1208     }
1209     if (layoutProperty->HasTextDecoration()) {
1210         textStyle.SetTextDecoration(layoutProperty->GetTextDecoration().value());
1211     }
1212     if (layoutProperty->HasTextDecorationColor()) {
1213         if (isDisabled) {
1214             textStyle.SetTextDecorationColor(layoutProperty->GetTextDecorationColor().value()
1215                 .BlendOpacity(TEXT_DECORATION_DISABLED_COLOR_ALPHA));
1216         } else {
1217             textStyle.SetTextDecorationColor(layoutProperty->GetTextDecorationColor().value());
1218         }
1219     }
1220     if (layoutProperty->HasTextDecorationStyle()) {
1221         textStyle.SetTextDecorationStyle(layoutProperty->GetTextDecorationStyle().value());
1222     }
1223     if (layoutProperty->HasLetterSpacing()) {
1224         textStyle.SetLetterSpacing(layoutProperty->GetLetterSpacing().value());
1225     }
1226     if (layoutProperty->HasLineHeight()) {
1227         textStyle.SetLineHeight(layoutProperty->GetLineHeight().value());
1228         textStyle.SetHalfLeading(pipeline->GetHalfLeading());
1229     }
1230     if (layoutProperty->HasFontFeature()) {
1231         textStyle.SetFontFeatures(layoutProperty->GetFontFeature().value());
1232     }
1233     if (layoutProperty->HasLineSpacing()) {
1234         textStyle.SetLineSpacing(layoutProperty->GetLineSpacing().value());
1235     }
1236 }
1237 
UpdatePlaceholderTextStyleMore(const RefPtr<FrameNode> & frameNode,const RefPtr<TextFieldLayoutProperty> & layoutProperty,const RefPtr<TextFieldTheme> & theme,TextStyle & placeholderTextStyle,bool isDisabled)1238 void TextFieldLayoutAlgorithm::UpdatePlaceholderTextStyleMore(const RefPtr<FrameNode>& frameNode,
1239     const RefPtr<TextFieldLayoutProperty>& layoutProperty, const RefPtr<TextFieldTheme>& theme,
1240     TextStyle& placeholderTextStyle, bool isDisabled)
1241 {
1242     if (layoutProperty->GetPlaceholderValue("").empty()) {
1243         if (layoutProperty->HasAdaptMinFontSize()) {
1244             placeholderTextStyle.SetAdaptMinFontSize(layoutProperty->GetAdaptMinFontSize().value());
1245         }
1246         if (layoutProperty->HasAdaptMaxFontSize()) {
1247             placeholderTextStyle.SetAdaptMaxFontSize(layoutProperty->GetAdaptMaxFontSize().value());
1248         }
1249     }
1250     auto pattern = frameNode->GetPattern<TextFieldPattern>();
1251     CHECK_NULL_VOID(pattern);
1252     auto pipeline = frameNode->GetContext();
1253     CHECK_NULL_VOID(pipeline);
1254     if (pattern->IsInPasswordMode()) {
1255         return;
1256     }
1257     if (layoutProperty->HasLineHeight()) {
1258         placeholderTextStyle.SetLineHeight(layoutProperty->GetLineHeight().value());
1259         placeholderTextStyle.SetHalfLeading(pipeline->GetHalfLeading());
1260     }
1261     placeholderTextStyle.SetLineSpacing(theme->GetPlaceholderLineSpacing());
1262 }
1263 
DidExceedMaxLines(const SizeF & maxSize)1264 bool TextFieldLayoutAlgorithm::DidExceedMaxLines(const SizeF& maxSize)
1265 {
1266     auto paragraph = GetParagraph();
1267     CHECK_NULL_RETURN(paragraph, false);
1268     return paragraph->DidExceedMaxLines() ||
1269         GreatNotEqual(paragraph->GetHeight(), maxSize.Height()) ||
1270         GreatNotEqual(paragraph->GetLongestLine(), maxSize.Width()) ||
1271         IsAdaptFontSizeExceedLineHeight(paragraph);
1272 }
1273 
IsAdaptExceedLimit(const SizeF & maxSize)1274 bool TextFieldLayoutAlgorithm::IsAdaptExceedLimit(const SizeF& maxSize)
1275 {
1276     auto paragraph = GetParagraph();
1277     CHECK_NULL_RETURN(paragraph, false);
1278     return (paragraph->GetLineCount() > 1) || paragraph->DidExceedMaxLines() ||
1279         GreatNotEqual(paragraph->GetLongestLine(), maxSize.Width()) ||
1280         IsAdaptFontSizeExceedLineHeight(paragraph) ||
1281            GreatNotEqual(paragraph->GetHeight(), maxSize.Height());
1282 }
1283 } // namespace OHOS::Ace::NG
1284