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