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