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