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