• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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/multiple_paragraph_layout_algorithm.h"
17 
18 #include "text_layout_adapter.h"
19 
20 #include "base/geometry/dimension.h"
21 #include "base/i18n/localization.h"
22 #include "base/log/ace_performance_monitor.h"
23 #include "base/utils/utf_helper.h"
24 #include "core/common/font_manager.h"
25 #include "core/components/common/properties/text_style.h"
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/pattern/rich_editor/paragraph_manager.h"
28 #include "core/components_ng/pattern/text/paragraph_util.h"
29 #include "core/components_ng/pattern/text/text_pattern.h"
30 #include "core/components_ng/property/measure_utils.h"
31 #include "core/components_ng/render/font_collection.h"
32 #include "core/pipeline_ng/pipeline_context.h"
33 #include "frameworks/bridge/common/utils/utils.h"
34 
35 namespace OHOS::Ace::NG {
36 namespace {
37 constexpr int32_t SYMBOL_SPAN_LENGTH = 2;
38 const std::string CUSTOM_SYMBOL_SUFFIX = "_CustomSymbol";
39 const std::string DEFAULT_SYMBOL_FONTFAMILY = "HM Symbol";
GetContentOffsetY(LayoutWrapper * layoutWrapper)40 float GetContentOffsetY(LayoutWrapper* layoutWrapper)
41 {
42     CHECK_NULL_RETURN(layoutWrapper, 0.0f);
43     auto geometryNode = layoutWrapper->GetGeometryNode();
44     CHECK_NULL_RETURN(geometryNode, 0.0f);
45     auto layoutProperty = layoutWrapper->GetLayoutProperty();
46     CHECK_NULL_RETURN(layoutProperty, 0.0f);
47     auto size = geometryNode->GetFrameSize();
48     const auto& padding = layoutProperty->CreatePaddingAndBorder();
49     auto offsetY = padding.top.value_or(0);
50     auto align = Alignment::CENTER;
51     if (layoutProperty->GetPositionProperty()) {
52         align = layoutProperty->GetPositionProperty()->GetAlignment().value_or(align);
53     }
54     const auto& content = geometryNode->GetContent();
55     if (content) {
56         offsetY += Alignment::GetAlignPosition(size, content->GetRect().GetSize(), align).GetY();
57     }
58     return offsetY;
59 }
60 } // namespace
61 
ConstructTextStyles(const LayoutConstraintF & contentConstraint,LayoutWrapper * layoutWrapper,TextStyle & textStyle)62 void MultipleParagraphLayoutAlgorithm::ConstructTextStyles(
63     const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper, TextStyle& textStyle)
64 {
65     auto frameNode = layoutWrapper->GetHostNode();
66     CHECK_NULL_VOID(frameNode);
67     textStyle.SetTextStyleUid(frameNode->GetId() + 1);
68     if (frameNode->GetTag() == V2::SYMBOL_ETS_TAG) {
69         textStyle.SetSymbolUid(frameNode->GetId() + 1);
70         textStyle.isSymbolGlyph_ = true;
71     }
72     if (Negative(contentConstraint.maxSize.Width()) || Negative(contentConstraint.maxSize.Height())) {
73         return;
74     }
75     auto pipeline = frameNode->GetContext();
76     CHECK_NULL_VOID(pipeline);
77     auto textLayoutProperty = DynamicCast<TextLayoutProperty>(layoutWrapper->GetLayoutProperty());
78     CHECK_NULL_VOID(textLayoutProperty);
79     auto pattern = frameNode->GetPattern<TextPattern>();
80     CHECK_NULL_VOID(pattern);
81     auto contentModifier = pattern->GetContentModifier();
82     auto themeScopeId = frameNode->GetThemeScopeId();
83     auto content = textLayoutProperty->GetContent().value_or(u"");
84     auto textTheme = pipeline->GetTheme<TextTheme>(themeScopeId);
85     CHECK_NULL_VOID(textTheme);
86     CreateTextStyleUsingTheme(textLayoutProperty, textTheme, textStyle, frameNode->GetTag() == V2::SYMBOL_ETS_TAG);
87     textStyle.SetSymbolType(textLayoutProperty->GetSymbolTypeValue(SymbolType::SYSTEM));
88     if (textLayoutProperty->HasFontForegroudGradiantColor()) {
89         textStyle.SetFontForegroudGradiantColor(textLayoutProperty->GetFontForegroudGradiantColor());
90     } else {
91         textStyle.SetFontForegroudGradiantColor(textTheme->GetTextStyle().GetFontForegroudGradiantColor());
92     }
93     std::vector<std::string> fontFamilies;
94     auto fontManager = pipeline->GetFontManager();
95     if (fontManager && !(fontManager->GetAppCustomFont().empty()) &&
96         !(textLayoutProperty->GetFontFamily().has_value())) {
97         fontFamilies = Framework::ConvertStrToFontFamilies(fontManager->GetAppCustomFont());
98     } else {
99 #ifndef OHOS_STANDARD_SYSTEM
100         const std::vector<std::string> defaultFontFamily = {"sans-serif"};
101 #else
102         const std::vector<std::string> defaultFontFamily = textTheme->GetTextStyle().GetFontFamilies();
103 #endif
104         fontFamilies = textLayoutProperty->GetFontFamilyValue(defaultFontFamily);
105     }
106     UpdateFontFamilyWithSymbol(textStyle, fontFamilies, frameNode->GetTag() == V2::SYMBOL_ETS_TAG);
107     UpdateSymbolStyle(textStyle, frameNode->GetTag() == V2::SYMBOL_ETS_TAG);
108     auto textColor = textLayoutProperty->GetTextColorValue(textTheme->GetTextStyle().GetTextColor());
109     auto lineThicknessScale = textLayoutProperty->GetLineThicknessScale().value_or(1.0f);
110     textStyle.SetLineThicknessScale(lineThicknessScale);
111     if (contentModifier) {
112         if (textLayoutProperty->GetIsAnimationNeededValue(true)) {
113             SetPropertyToModifier(textLayoutProperty, contentModifier, textStyle, frameNode, textColor);
114             contentModifier->ModifyTextStyle(textStyle, textColor);
115         }
116         contentModifier->SetFontReady(false);
117     }
118     UpdateShaderStyle(textLayoutProperty, textStyle);
119     textStyle.SetHalfLeading(textLayoutProperty->GetHalfLeadingValue(pipeline->GetHalfLeading()));
120     textStyle.SetEnableAutoSpacing(textLayoutProperty->GetEnableAutoSpacingValue(false));
121     textStyle.SetParagraphVerticalAlign(
122         textLayoutProperty->GetTextVerticalAlignValue(TextVerticalAlign::BASELINE));
123     SetAdaptFontSizeStepToTextStyle(textStyle, textLayoutProperty->GetAdaptFontSizeStep());
124     // Register callback for fonts.
125     FontRegisterCallback(frameNode, textStyle);
126     textStyle.SetTextDirection(ParagraphUtil::GetTextDirection(content, layoutWrapper));
127     textStyle.SetLocale(Localization::GetInstance()->GetFontLocale());
128     // Determines whether a foreground color is set or inherited.
129     UpdateTextColorIfForeground(frameNode, textStyle, textColor);
130     inheritTextStyle_ = textStyle;
131 }
132 
UpdateShaderStyle(const RefPtr<TextLayoutProperty> & layoutProperty,TextStyle & textStyle)133 void MultipleParagraphLayoutAlgorithm::UpdateShaderStyle(
134     const RefPtr<TextLayoutProperty>& layoutProperty, TextStyle& textStyle)
135 {
136     if (layoutProperty->HasGradientShaderStyle()) {
137         auto gradients = layoutProperty->GetGradientShaderStyle().value_or(Gradient());
138         auto gradient = ToGradient(gradients);
139         textStyle.SetColorShaderStyle(std::optional<Color>(std::nullopt));
140         textStyle.SetGradient(gradient);
141     } else if (layoutProperty->HasColorShaderStyle()) {
142         std::optional<Color> colors = layoutProperty->GetColorShaderStyle().value_or(Color::TRANSPARENT);
143         textStyle.SetGradient(std::nullopt);
144         textStyle.SetColorShaderStyle(colors);
145     } else {
146         textStyle.SetGradient(std::nullopt);
147         textStyle.SetColorShaderStyle(std::optional<Color>(std::nullopt));
148     }
149 }
150 
ToGradient(const NG::Gradient & gradient)151 std::optional<OHOS::Ace::Gradient> MultipleParagraphLayoutAlgorithm::ToGradient(const NG::Gradient& gradient)
152 {
153     OHOS::Ace::Gradient retGradient;
154     retGradient.SetType(static_cast<OHOS::Ace::GradientType>(gradient.GetType()));
155     if (retGradient.GetType() == OHOS::Ace::GradientType::LINEAR) {
156         CHECK_NULL_RETURN(gradient.GetLinearGradient(), std::nullopt);
157         auto angle = gradient.GetLinearGradient()->angle;
158         if (angle.has_value()) {
159             retGradient.GetLinearGradient().angle = ToAnimatableDimension(angle.value());
160         }
161         auto linearX = gradient.GetLinearGradient()->linearX;
162         if (linearX.has_value()) {
163             retGradient.GetLinearGradient().linearX = static_cast<OHOS::Ace::GradientDirection>(linearX.value());
164         }
165         auto linearY = gradient.GetLinearGradient()->linearY;
166         if (linearY.has_value()) {
167             retGradient.GetLinearGradient().linearY = static_cast<OHOS::Ace::GradientDirection>(linearY.value());
168         }
169     }
170     if (retGradient.GetType() == OHOS::Ace::GradientType::RADIAL) {
171         CHECK_NULL_RETURN(gradient.GetRadialGradient(), std::nullopt);
172         auto radialCenterX = gradient.GetRadialGradient()->radialCenterX;
173         if (radialCenterX.has_value()) {
174             retGradient.GetRadialGradient().radialCenterX = ToAnimatableDimension(radialCenterX.value());
175         }
176         auto radialCenterY = gradient.GetRadialGradient()->radialCenterY;
177         if (radialCenterY.has_value()) {
178             retGradient.GetRadialGradient().radialCenterY = ToAnimatableDimension(radialCenterY.value());
179         }
180         auto radialVerticalSize = gradient.GetRadialGradient()->radialVerticalSize;
181         if (radialVerticalSize.has_value()) {
182             retGradient.GetRadialGradient().radialVerticalSize = ToAnimatableDimension(radialVerticalSize.value());
183         }
184         auto radialHorizontalSize = gradient.GetRadialGradient()->radialHorizontalSize;
185         if (radialHorizontalSize.has_value()) {
186             retGradient.GetRadialGradient().radialHorizontalSize = ToAnimatableDimension(radialHorizontalSize.value());
187         }
188     }
189     retGradient.SetRepeat(gradient.GetRepeat());
190     const auto& colorStops = gradient.GetColors();
191     for (const auto& item : colorStops) {
192         OHOS::Ace::GradientColor gradientColor;
193         gradientColor.SetColor(item.GetColor());
194         gradientColor.SetHasValue(item.GetHasValue());
195         gradientColor.SetDimension(item.GetDimension());
196         retGradient.AddColor(gradientColor);
197     }
198     return retGradient;
199 }
200 
ToAnimatableDimension(const Dimension & dimension)201 AnimatableDimension MultipleParagraphLayoutAlgorithm::ToAnimatableDimension(const Dimension& dimension)
202 {
203     AnimatableDimension result(dimension);
204     return result;
205 }
206 
UpdateFontFamilyWithSymbol(TextStyle & textStyle,std::vector<std::string> & fontFamilies,bool isSymbol)207 void MultipleParagraphLayoutAlgorithm::UpdateFontFamilyWithSymbol(TextStyle& textStyle,
208     std::vector<std::string>& fontFamilies, bool isSymbol)
209 {
210     if (!isSymbol) {
211         textStyle.SetFontFamilies(fontFamilies);
212         return;
213     }
214     auto symbolType = textStyle.GetSymbolType();
215     std::vector<std::string> symbolFontFamilies;
216     if (symbolType == SymbolType::CUSTOM) {
217         for (auto& name : fontFamilies) {
218             if (name.find(CUSTOM_SYMBOL_SUFFIX) != std::string::npos) {
219                 symbolFontFamilies.push_back(name);
220                 break;
221             }
222         }
223         textStyle.SetFontFamilies(symbolFontFamilies);
224     } else {
225         symbolFontFamilies.push_back(DEFAULT_SYMBOL_FONTFAMILY);
226         textStyle.SetFontFamilies(symbolFontFamilies);
227     }
228 }
229 
UpdateSymbolStyle(TextStyle & textStyle,bool isSymbol)230 void MultipleParagraphLayoutAlgorithm::UpdateSymbolStyle(TextStyle& textStyle, bool isSymbol)
231 {
232     if (!isSymbol) {
233         return;
234     }
235     textStyle.SetRenderStrategy(textStyle.GetRenderStrategy() < 0 ? 0 : textStyle.GetRenderStrategy());
236     textStyle.SetEffectStrategy(textStyle.GetEffectStrategy() < 0 ? 0 : textStyle.GetEffectStrategy());
237 }
238 
Measure(LayoutWrapper * layoutWrapper)239 void MultipleParagraphLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
240 {
241     // child constraint has already been calculated by the UpdateParagraphBySpan method when triggering MeasureContent
242     BoxLayoutAlgorithm::PerformMeasureSelf(layoutWrapper);
243     MeasureWidthLayoutCalPolicy(layoutWrapper);
244     auto baselineDistance = 0.0f;
245     auto paragraph = GetSingleParagraph();
246     if (paragraph) {
247         baselineDistance = paragraph->GetAlphabeticBaseline() + std::max(GetBaselineOffset(), 0.0f);
248     }
249     if (!NearZero(baselineDistance, 0.0f)) {
250         baselineDistance += GetContentOffsetY(layoutWrapper);
251     }
252     layoutWrapper->GetGeometryNode()->SetBaselineDistance(baselineDistance);
253 }
254 
Layout(LayoutWrapper * layoutWrapper)255 void MultipleParagraphLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
256 {
257     CHECK_NULL_VOID(layoutWrapper);
258     auto contentOffset = GetContentOffset(layoutWrapper);
259     CHECK_NULL_VOID(paragraphManager_);
260     auto frameNode = layoutWrapper->GetHostNode();
261     CHECK_NULL_VOID(frameNode);
262     CHECK_NULL_VOID(frameNode->GetTag() != V2::SYMBOL_ETS_TAG);
263     auto pattern = frameNode->GetPattern<TextPattern>();
264     CHECK_NULL_VOID(pattern);
265     std::vector<int32_t> placeholderIndex;
266     GetChildrenPlaceholderIndex(placeholderIndex);
267     auto rectsForPlaceholders = paragraphManager_->GetPlaceholderRects();
268     if (spans_.empty() || placeholderIndex.empty()) {
269         pattern->InitSpanImageLayout(placeholderIndex, rectsForPlaceholders, contentOffset);
270         return;
271     }
272     size_t index = 0;
273     const auto& children = GetAllChildrenWithBuild(layoutWrapper);
274     // children only contains the image span.
275     for (const auto& child : children) {
276         if (!child) {
277             ++index;
278             continue;
279         }
280         if (index >= placeholderIndex.size() || index < 0) {
281             child->SetActive(false);
282             continue;
283         }
284         auto indexTemp = placeholderIndex.at(index);
285         if (indexTemp >= static_cast<int32_t>(rectsForPlaceholders.size()) || indexTemp < 0) {
286             child->SetActive(false);
287             continue;
288         }
289         child->SetActive(true);
290         auto rect = rectsForPlaceholders.at(indexTemp) - OffsetF(0.0f, std::min(baselineOffset_, 0.0f));
291         auto geometryNode = child->GetGeometryNode();
292         if (!geometryNode) {
293             ++index;
294             continue;
295         }
296         geometryNode->SetMarginFrameOffset(contentOffset + OffsetF(rect.Left(), rect.Top()));
297         child->Layout();
298         ++index;
299     }
300     pattern->InitSpanImageLayout(placeholderIndex, rectsForPlaceholders, contentOffset);
301 }
302 
GetChildrenPlaceholderIndex(std::vector<int32_t> & placeholderIndex)303 void MultipleParagraphLayoutAlgorithm::GetChildrenPlaceholderIndex(std::vector<int32_t>& placeholderIndex)
304 {
305     for (auto&& group : spans_) {
306         for (const auto& child : group) {
307             if (!child) {
308                 continue;
309             }
310             auto customSpanItem = AceType::DynamicCast<CustomSpanItem>(child);
311             if (customSpanItem && !customSpanItem->isFrameNode) {
312                 continue;
313             }
314             if (AceType::InstanceOf<ImageSpanItem>(child) || AceType::InstanceOf<PlaceholderSpanItem>(child)) {
315                 placeholderIndex.emplace_back(child->placeholderIndex);
316             }
317         }
318     }
319 }
320 
FontRegisterCallback(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle)321 void MultipleParagraphLayoutAlgorithm::FontRegisterCallback(
322     const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle)
323 {
324     auto callback = [weakNode = WeakPtr<FrameNode>(frameNode)] {
325         auto frameNode = weakNode.Upgrade();
326         CHECK_NULL_VOID(frameNode);
327         frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
328         auto pattern = frameNode->GetPattern<TextPattern>();
329         CHECK_NULL_VOID(pattern);
330         auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
331         CHECK_NULL_VOID(modifier);
332         modifier->SetFontReady(true);
333         TAG_LOGI(AceLogTag::ACE_TEXT, "FontRegisterCallback callback id:%{public}d", frameNode->GetId());
334         auto layoutProperty = frameNode->GetLayoutProperty();
335         CHECK_NULL_VOID(layoutProperty);
336         layoutProperty->OnPropertyChangeMeasure();
337     };
338     auto pipeline = frameNode->GetContext();
339     CHECK_NULL_VOID(pipeline);
340     auto fontManager = pipeline->GetFontManager();
341     if (fontManager) {
342         bool isCustomFont = false;
343         for (const auto& familyName : textStyle.GetFontFamilies()) {
344             bool customFont = fontManager->RegisterCallbackNG(frameNode, familyName, callback);
345             if (customFont) {
346                 isCustomFont = true;
347             }
348         }
349         if (isCustomFont || fontManager->IsDefaultFontChanged()) {
350             auto pattern = frameNode->GetPattern<TextPattern>();
351             CHECK_NULL_VOID(pattern);
352             pattern->SetIsCustomFont(true);
353             auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
354             CHECK_NULL_VOID(modifier);
355             modifier->SetIsCustomFont(true);
356         }
357     }
358 }
359 
UpdateTextColorIfForeground(const RefPtr<FrameNode> & frameNode,TextStyle & textStyle,const Color & textColor)360 void MultipleParagraphLayoutAlgorithm::UpdateTextColorIfForeground(
361     const RefPtr<FrameNode>& frameNode, TextStyle& textStyle, const Color& textColor)
362 {
363     auto renderContext = frameNode->GetRenderContext();
364     if (renderContext->HasForegroundColor()) {
365         if (renderContext->GetForegroundColorValue().GetValue() != textColor.GetValue()) {
366             textStyle.SetTextColor(Color::FOREGROUND);
367         } else {
368             textStyle.SetTextColor(textColor);
369         }
370     } else if (renderContext->HasForegroundColorStrategy()) {
371         textStyle.SetTextColor(Color::FOREGROUND);
372     } else {
373         textStyle.SetTextColor(textColor);
374     }
375 }
376 
SetFontSizePropertyToModifier(const RefPtr<TextLayoutProperty> & layoutProperty,const RefPtr<TextContentModifier> & modifier,const TextStyle & textStyle)377 void MultipleParagraphLayoutAlgorithm::SetFontSizePropertyToModifier(const RefPtr<TextLayoutProperty>& layoutProperty,
378     const RefPtr<TextContentModifier>& modifier, const TextStyle& textStyle)
379 {
380     auto fontSize = layoutProperty->GetFontSize();
381     if (fontSize.has_value()) {
382         modifier->SetFontSize(fontSize.value(), textStyle);
383     } else {
384         // Reset modifier FontSize.
385         modifier->SetFontSize(textStyle.GetFontSize(), textStyle, true);
386     }
387     auto adaptMinFontSize = layoutProperty->GetAdaptMinFontSize();
388     if (adaptMinFontSize.has_value()) {
389         modifier->SetAdaptMinFontSize(adaptMinFontSize.value(), textStyle);
390     } else {
391         // Reset modifier MinFontSize.
392         modifier->SetAdaptMinFontSize(textStyle.GetAdaptMinFontSize(), textStyle, true);
393     }
394     auto adaptMaxFontSize = layoutProperty->GetAdaptMaxFontSize();
395     if (adaptMaxFontSize.has_value()) {
396         modifier->SetAdaptMaxFontSize(adaptMaxFontSize.value(), textStyle);
397     } else {
398         // Reset modifier MaxFontSize.
399         modifier->SetAdaptMaxFontSize(textStyle.GetAdaptMaxFontSize(), textStyle, true);
400     }
401 }
402 
SetDecorationPropertyToModifier(const RefPtr<TextLayoutProperty> & layoutProperty,const RefPtr<TextContentModifier> & modifier,const TextStyle & textStyle)403 void MultipleParagraphLayoutAlgorithm::SetDecorationPropertyToModifier(const RefPtr<TextLayoutProperty>& layoutProperty,
404     const RefPtr<TextContentModifier>& modifier, const TextStyle& textStyle)
405 {
406     auto textDecorationColor = layoutProperty->GetTextDecorationColor();
407     if (textDecorationColor.has_value()) {
408         modifier->SetTextDecorationColor(textDecorationColor.value());
409     } else {
410         modifier->SetTextDecorationColor(textStyle.GetTextDecorationColor(), true);
411     }
412     auto textDecoration = layoutProperty->GetTextDecoration();
413     if (textDecoration.has_value()) {
414         auto value = textDecoration.value().size() > 0 ? textDecoration.value()[0] : TextDecoration::NONE;
415         modifier->SetTextDecoration(value, false);
416     } else {
417         modifier->SetTextDecoration(textStyle.GetTextDecorationFirst(), true);
418     }
419 }
420 
SetPropertyToModifier(const RefPtr<TextLayoutProperty> & layoutProperty,const RefPtr<TextContentModifier> & modifier,const TextStyle & textStyle,const RefPtr<FrameNode> & frameNode,const Color & textColor)421 void MultipleParagraphLayoutAlgorithm::SetPropertyToModifier(const RefPtr<TextLayoutProperty>& layoutProperty,
422     const RefPtr<TextContentModifier>& modifier, const TextStyle& textStyle, const RefPtr<FrameNode>& frameNode,
423     const Color& textColor)
424 {
425     SetFontSizePropertyToModifier(layoutProperty, modifier, textStyle);
426     auto fontWeight = layoutProperty->GetFontWeight();
427     if (fontWeight.has_value()) {
428         modifier->SetFontWeight(fontWeight.value());
429     } else {
430         modifier->SetFontWeight(textStyle.GetFontWeight(), true);
431     }
432     auto propTextColor = layoutProperty->GetTextColor();
433     if (propTextColor.has_value()) {
434         modifier->SetTextColor(propTextColor.value());
435     } else {
436         modifier->SetTextColor(textColor, true);
437     }
438     if (frameNode->GetTag() == V2::SYMBOL_ETS_TAG) {
439         auto symbolColors = layoutProperty->GetSymbolColorList();
440         if (symbolColors && symbolColors.has_value()) {
441             modifier->SetSymbolColor(symbolColors.value());
442         } else {
443             modifier->SetSymbolColor(textStyle.GetSymbolColorList(), true);
444         }
445     }
446     auto textShadow = layoutProperty->GetTextShadow();
447     if (textShadow.has_value()) {
448         modifier->SetTextShadow(textShadow.value());
449     } else {
450         modifier->SetTextShadow(textStyle.GetTextShadows());
451     }
452     SetDecorationPropertyToModifier(layoutProperty, modifier, textStyle);
453     auto baselineOffset = layoutProperty->GetBaselineOffset();
454     if (baselineOffset.has_value()) {
455         modifier->SetBaselineOffset(baselineOffset.value(), textStyle);
456     } else {
457         modifier->SetBaselineOffset(textStyle.GetBaselineOffset(), textStyle, true);
458     }
459     auto lineHeight = layoutProperty->GetLineHeight();
460     if (lineHeight.has_value()) {
461         if (lineHeight->Unit() == DimensionUnit::PERCENT) {
462             modifier->SetLineHeight(lineHeight.value(), textStyle, true);
463         } else {
464             modifier->SetLineHeight(lineHeight.value(), textStyle);
465         }
466     } else {
467         modifier->SetLineHeight(textStyle.GetLineHeight(), textStyle, true);
468     }
469 }
470 
GetSingleParagraph() const471 RefPtr<Paragraph> MultipleParagraphLayoutAlgorithm::GetSingleParagraph() const
472 {
473     CHECK_NULL_RETURN(paragraphManager_, nullptr);
474     CHECK_NULL_RETURN(!paragraphManager_->GetParagraphs().empty(), nullptr);
475     auto paragraphInfo = paragraphManager_->GetParagraphs().front();
476     auto paragraph = paragraphInfo.paragraph;
477     CHECK_NULL_RETURN(paragraph, nullptr);
478     return paragraph;
479 }
480 
SetContentOffset(LayoutWrapper * layoutWrapper)481 OffsetF MultipleParagraphLayoutAlgorithm::SetContentOffset(LayoutWrapper* layoutWrapper)
482 {
483     OffsetF contentOffset(0.0f, 0.0f);
484     CHECK_NULL_RETURN(layoutWrapper, contentOffset);
485 
486     auto size = layoutWrapper->GetGeometryNode()->GetFrameSize();
487     const auto& padding = layoutWrapper->GetLayoutProperty()->CreatePaddingAndBorder();
488     MinusPaddingToSize(padding, size);
489     auto left = padding.left.value_or(0);
490     auto top = padding.top.value_or(0);
491     auto paddingOffset = OffsetF(left, top);
492     auto align = Alignment::CENTER;
493     if (layoutWrapper->GetLayoutProperty()->GetPositionProperty()) {
494         align = layoutWrapper->GetLayoutProperty()->GetPositionProperty()->GetAlignment().value_or(align);
495     }
496 
497     const auto& content = layoutWrapper->GetGeometryNode()->GetContent();
498     if (content) {
499         contentOffset = Alignment::GetAlignPosition(size, content->GetRect().GetSize(), align) + paddingOffset;
500         content->SetOffset(contentOffset);
501     }
502     return contentOffset;
503 }
504 
SetAdaptFontSizeStepToTextStyle(TextStyle & textStyle,const std::optional<Dimension> & adaptFontSizeStep)505 void MultipleParagraphLayoutAlgorithm::SetAdaptFontSizeStepToTextStyle(
506     TextStyle& textStyle, const std::optional<Dimension>& adaptFontSizeStep)
507 {
508     textStyle.SetAdaptFontSizeStep(adaptFontSizeStep.value_or(Dimension(1.0, DimensionUnit::PX)));
509 }
510 
ParagraphReLayout(const LayoutConstraintF & contentConstraint)511 bool MultipleParagraphLayoutAlgorithm::ParagraphReLayout(const LayoutConstraintF& contentConstraint)
512 {
513     // Confirmed specification: The width of the text paragraph covers the width of the component, so this code is
514     // generally not allowed to be modified
515     CHECK_NULL_RETURN(paragraphManager_, false);
516     auto paragraphs = paragraphManager_->GetParagraphs();
517     float paragraphNewWidth =
518         std::min(std::min(paragraphManager_->GetTextWidthIncludeIndent(), paragraphManager_->GetMaxWidth()),
519             GetMaxMeasureSize(contentConstraint).Width());
520     paragraphNewWidth =
521         std::clamp(paragraphNewWidth, contentConstraint.minSize.Width(), contentConstraint.maxSize.Width());
522     if (!contentConstraint.selfIdealSize.Width() || IsNeedParagraphReLayout()) {
523         for (auto pIter = paragraphs.begin(); pIter != paragraphs.end(); pIter++) {
524             auto paragraph = pIter->paragraph;
525             CHECK_NULL_RETURN(paragraph, false);
526             if (SystemProperties::GetTextTraceEnabled()) {
527                 ACE_TEXT_SCOPED_TRACE("ParagraphReLayout[NewWidth:%f][MaxWidth:%f][IndentWidth:%f][Constraint:%s]",
528                     paragraphNewWidth, paragraph->GetMaxWidth(), paragraphManager_->GetTextWidthIncludeIndent(),
529                     contentConstraint.ToString().c_str());
530             }
531             if (!NearEqual(paragraphNewWidth, paragraph->GetMaxWidth())) {
532                 int32_t id = -1;
533                 if (SystemProperties::GetAcePerformanceMonitorEnabled()) {
534                     id = Container::CurrentId();
535                 }
536                 OTHER_DURATION(id);
537                 paragraph->Layout(std::ceil(paragraphNewWidth));
538             }
539         }
540     }
541     return true;
542 }
543 
ReLayoutParagraphBySpan(LayoutWrapper * layoutWrapper,ParagraphStyle & paraStyle,const TextStyle & textStyle,std::vector<TextStyle> & textStyles)544 bool MultipleParagraphLayoutAlgorithm::ReLayoutParagraphBySpan(LayoutWrapper* layoutWrapper, ParagraphStyle& paraStyle,
545     const TextStyle& textStyle, std::vector<TextStyle>& textStyles)
546 {
547     CHECK_NULL_RETURN(!spans_.empty(), false);
548     auto spans = spans_.front();
549     ParagraphStyle spanParagraphStyle = paraStyle;
550     auto frameNode = layoutWrapper->GetHostNode();
551     CHECK_NULL_RETURN(frameNode, false);
552     bool reLayout = false;
553     int32_t index = 0;
554     InheritParentTextStyle(textStyle);
555     for (const auto& child : spans) {
556         if (!child) {
557             continue;
558         }
559         TextStyle spanTextStyle;
560         needReCreateParagraph_ |= child->UpdateSpanTextStyle(inheritTextStyle_, frameNode);
561         auto style = child->GetTextStyle();
562         if (SystemProperties::GetTextTraceEnabled()) {
563             ACE_TEXT_SCOPED_TRACE(
564                 "ReLayoutParagraphBySpan[id:%d][needReCreateParagraph_:%d][textStyleBitmap:%s][textColor:%s]",
565                 child->nodeId_, needReCreateParagraph_,
566                 style.has_value() ? style->GetReLayoutTextStyleBitmap().to_string().c_str() : "Na",
567                 style.has_value() ? style->GetTextColor().ColorToString().c_str() : "Na");
568         }
569         CHECK_NULL_RETURN(!needReCreateParagraph_, false);
570         if (child->GetTextStyle().has_value()) {
571             spanTextStyle = child->GetTextStyle().value();
572         }
573         if (index == 0) {
574             auto direction = ParagraphUtil::GetTextDirection(child->content, layoutWrapper);
575             spanTextStyle.SetTextDirection(direction);
576             spanTextStyle.SetLocale(Localization::GetInstance()->GetFontLocale());
577             paraStyle = ParagraphUtil::GetParagraphStyle(spanTextStyle);
578         }
579         reLayout |= spanTextStyle.NeedReLayout();
580         textStyles.emplace_back(spanTextStyle);
581         child->ResetReCreateAndReLayout();
582         index++;
583     }
584     return reLayout;
585 }
586 
ImageSpanMeasure(const RefPtr<ImageSpanItem> & imageSpanItem,const RefPtr<LayoutWrapper> & layoutWrapper,const LayoutConstraintF & layoutConstrain,const TextStyle & textStyle)587 bool MultipleParagraphLayoutAlgorithm::ImageSpanMeasure(const RefPtr<ImageSpanItem>& imageSpanItem,
588     const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& layoutConstrain, const TextStyle& textStyle)
589 {
590     auto frameNode = layoutWrapper->GetHostNode();
591     CHECK_NULL_RETURN(frameNode, true);
592     auto id = frameNode->GetId();
593     int32_t targetId = imageSpanItem->nodeId_;
594     if (!isSpanStringMode_) {
595         CHECK_NULL_RETURN(id == targetId, true);
596     }
597     layoutWrapper->Measure(layoutConstrain);
598     PlaceholderStyle placeholderStyle;
599     auto baselineOffset = Dimension(0.0f);
600     auto imageLayoutProperty = DynamicCast<ImageLayoutProperty>(layoutWrapper->GetLayoutProperty());
601     if (imageLayoutProperty) {
602         placeholderStyle.verticalAlign = imageLayoutProperty->GetVerticalAlign().value_or(VerticalAlign::BOTTOM);
603         baselineOffset = imageLayoutProperty->GetBaselineOffset().value_or(Dimension(0.0f));
604     }
605     auto geometryNode = layoutWrapper->GetGeometryNode();
606     CHECK_NULL_RETURN(geometryNode, true);
607     placeholderStyle.width = geometryNode->GetMarginFrameSize().Width();
608     placeholderStyle.height = geometryNode->GetMarginFrameSize().Height();
609     placeholderStyle.baselineOffset = baselineOffset.ConvertToPxDistribute(
610         textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
611     return imageSpanItem->UpdatePlaceholderRun(placeholderStyle);
612 }
613 
CustomSpanMeasure(const RefPtr<CustomSpanItem> & customSpanItem,LayoutWrapper * layoutWrapper)614 bool MultipleParagraphLayoutAlgorithm::CustomSpanMeasure(
615     const RefPtr<CustomSpanItem>& customSpanItem, LayoutWrapper* layoutWrapper)
616 {
617     CHECK_NULL_RETURN(layoutWrapper, false);
618     auto layoutProperty = layoutWrapper->GetLayoutProperty();
619     CHECK_NULL_RETURN(layoutProperty, false);
620     auto frameNode = layoutWrapper->GetHostNode();
621     CHECK_NULL_RETURN(frameNode, false);
622     auto context = frameNode->GetContext();
623     CHECK_NULL_RETURN(context, false);
624     auto theme = context->GetTheme<TextTheme>();
625     CHECK_NULL_RETURN(theme, false);
626     auto width = 0.0f;
627     auto height = 0.0f;
628     auto fontSize = theme->GetTextStyle().GetFontSize().ConvertToVp() * context->GetFontScale();
629     auto textLayoutProperty = DynamicCast<TextLayoutProperty>(layoutProperty);
630     auto fontSizeOpt = textLayoutProperty->GetFontSize();
631     if (fontSizeOpt.has_value()) {
632         fontSize = fontSizeOpt.value().ConvertToVp() * context->GetFontScale();
633     }
634     if (customSpanItem->onMeasure.has_value()) {
635         auto onMeasure = customSpanItem->onMeasure.value();
636         CustomSpanMetrics customSpanMetrics = onMeasure({ fontSize });
637         width = static_cast<float>(customSpanMetrics.width * context->GetDipScale());
638         height = static_cast<float>(
639             customSpanMetrics.height.value_or(fontSize / context->GetFontScale()) * context->GetDipScale());
640     }
641     PlaceholderStyle placeholderStyle;
642     placeholderStyle.width = width;
643     placeholderStyle.height = height;
644     placeholderStyle.verticalAlign = VerticalAlign::NONE;
645     return customSpanItem->UpdatePlaceholderRun(placeholderStyle);
646 }
647 
PlaceholderSpanMeasure(const RefPtr<PlaceholderSpanItem> & placeholderSpanItem,const RefPtr<LayoutWrapper> & layoutWrapper,const LayoutConstraintF & layoutConstrain)648 bool MultipleParagraphLayoutAlgorithm::PlaceholderSpanMeasure(const RefPtr<PlaceholderSpanItem>& placeholderSpanItem,
649     const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& layoutConstrain)
650 {
651     auto frameNode = layoutWrapper->GetHostNode();
652     CHECK_NULL_RETURN(frameNode, true);
653     auto id = frameNode->GetId();
654     int32_t targetId = placeholderSpanItem->placeholderSpanNodeId;
655     CHECK_NULL_RETURN(id == targetId, true);
656     // find the Corresponding ImageNode for every ImageSpanItem
657     layoutWrapper->Measure(layoutConstrain);
658     auto geometryNode = layoutWrapper->GetGeometryNode();
659     CHECK_NULL_RETURN(geometryNode, true);
660     PlaceholderStyle placeholderStyle;
661     placeholderStyle.width = geometryNode->GetMarginFrameSize().Width();
662     placeholderStyle.height = geometryNode->GetMarginFrameSize().Height();
663     placeholderStyle.verticalAlign = VerticalAlign::NONE;
664     return placeholderSpanItem->UpdatePlaceholderRun(placeholderStyle);
665 }
666 
MeasureChildren(LayoutWrapper * layoutWrapper,const TextStyle & textStyle)667 void MultipleParagraphLayoutAlgorithm::MeasureChildren(LayoutWrapper* layoutWrapper, const TextStyle& textStyle)
668 {
669     CHECK_NULL_VOID(!spans_.empty());
670     CHECK_NULL_VOID(layoutWrapper);
671     auto layoutProperty = layoutWrapper->GetLayoutProperty();
672     CHECK_NULL_VOID(layoutProperty);
673     const auto& layoutConstrain = layoutProperty->CreateChildConstraint();
674     auto placeHolderLayoutConstrain = layoutConstrain;
675     placeHolderLayoutConstrain.maxSize.SetHeight(Infinity<float>());
676     placeHolderLayoutConstrain.percentReference.SetHeight(0);
677     const auto& children = GetAllChildrenWithBuild(layoutWrapper);
678     auto iterItems = children.begin();
679     bool needReCreateParagraph = false;
680     int32_t itemIndex = -1;
681     for (const auto& group : spans_) {
682         for (const auto& child : group) {
683             itemIndex++;
684             if (!child) {
685                 needReCreateParagraph = true;
686                 continue;
687             }
688             needReCreateParagraph |= child->CheckSpanNeedReCreate(itemIndex);
689             switch (child->spanItemType) {
690                 case SpanItemType::NORMAL:
691                     break;
692                 case SpanItemType::IMAGE: {
693                     if (iterItems == children.end() || !(*iterItems)) {
694                         continue;
695                     }
696                     auto imageSpanItem = AceType::DynamicCast<ImageSpanItem>(child);
697                     if (!imageSpanItem) {
698                         continue;
699                     }
700                     needReCreateParagraph |= ImageSpanMeasure(imageSpanItem, (*iterItems), layoutConstrain, textStyle);
701                     ++iterItems;
702                     break;
703                 }
704                 case SpanItemType::CustomSpan: {
705                     auto customSpanItem = AceType::DynamicCast<CustomSpanItem>(child);
706                     if (!customSpanItem) {
707                         continue;
708                     }
709                     needReCreateParagraph |= CustomSpanMeasure(customSpanItem, layoutWrapper);
710                     if (customSpanItem->isFrameNode) {
711                         ++iterItems; // CAPI custom span is frameNode,need to move the iterator backwards
712                     }
713                     break;
714                 }
715                 case SpanItemType::PLACEHOLDER: {
716                     if (iterItems == children.end() || !(*iterItems)) {
717                         continue;
718                     }
719                     auto placeholderSpanItem = AceType::DynamicCast<PlaceholderSpanItem>(child);
720                     if (!placeholderSpanItem) {
721                         continue;
722                     }
723                     needReCreateParagraph |=
724                         PlaceholderSpanMeasure(placeholderSpanItem, (*iterItems), placeHolderLayoutConstrain);
725                     ++iterItems;
726                     break;
727                 }
728                 case SpanItemType::SYMBOL:
729                     break;
730             }
731         }
732     }
733     CHECK_NULL_VOID(needReCreateParagraph);
734     layoutProperty->OnPropertyChangeMeasure();
735 }
736 
GetAllChildrenWithBuild(LayoutWrapper * layoutWrapper)737 ChildrenListWithGuard MultipleParagraphLayoutAlgorithm::GetAllChildrenWithBuild(LayoutWrapper* layoutWrapper)
738 {
739     return layoutWrapper->GetAllChildrenWithBuild();
740 }
741 
UpdateParagraphBySpan(LayoutWrapper * layoutWrapper,ParagraphStyle paraStyle,double maxWidth,const TextStyle & textStyle)742 bool MultipleParagraphLayoutAlgorithm::UpdateParagraphBySpan(
743     LayoutWrapper* layoutWrapper, ParagraphStyle paraStyle, double maxWidth, const TextStyle& textStyle)
744 {
745     CHECK_NULL_RETURN(layoutWrapper, false);
746     auto layoutProperty = layoutWrapper->GetLayoutProperty();
747     CHECK_NULL_RETURN(layoutProperty, false);
748     auto frameNode = layoutWrapper->GetHostNode();
749     CHECK_NULL_RETURN(frameNode, false);
750     InheritParentTextStyle(textStyle);
751     const auto& children = GetAllChildrenWithBuild(layoutWrapper);
752     auto iterItems = children.begin();
753     auto pattern = frameNode->GetPattern<TextPattern>();
754     CHECK_NULL_RETURN(pattern, false);
755     auto aiSpanMap = pattern->GetAISpanMap();
756     int32_t spanTextLength = 0;
757     std::vector<WeakPtr<FrameNode>> imageNodeList;
758     std::vector<CustomSpanPlaceholderInfo> customSpanPlaceholderInfo;
759     int32_t paragraphIndex = -1;
760     preParagraphsPlaceholderCount_ = 0;
761     currentParagraphPlaceholderCount_ = 0;
762     auto maxLines = static_cast<int32_t>(paraStyle.maxLines);
763     for (auto groupIt = spans_.begin(); groupIt != spans_.end(); groupIt++) {
764         auto& group = *(groupIt);
765         ParagraphStyle spanParagraphStyle = paraStyle;
766         if (paraStyle.maxLines != UINT32_MAX) {
767             if (!paragraphManager_->GetParagraphs().empty()) {
768                 maxLines -= static_cast<int32_t>(paragraphManager_->GetParagraphs().back().paragraph->GetLineCount());
769             }
770             spanParagraphStyle.maxLines = std::max(maxLines, 0);
771         }
772         RefPtr<SpanItem> paraStyleSpanItem = GetParagraphStyleSpanItem(group);
773         if (paraStyleSpanItem) {
774             ParagraphUtil::GetSpanParagraphStyle(layoutWrapper, paraStyleSpanItem, spanParagraphStyle);
775             if (paraStyleSpanItem->fontStyle->HasFontSize()) {
776                 spanParagraphStyle.fontSize = paraStyleSpanItem->fontStyle->GetFontSizeValue().ConvertToPxDistribute(
777                     textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
778             }
779             spanParagraphStyle.isEndAddParagraphSpacing =
780                 paraStyleSpanItem->textLineStyle->HasParagraphSpacing() &&
781                 Positive(paraStyleSpanItem->textLineStyle->GetParagraphSpacingValue().ConvertToPx()) &&
782                 std::next(groupIt) != spans_.end();
783             spanParagraphStyle.isFirstParagraphLineSpacing = (groupIt == spans_.begin());
784         }
785         auto&& paragraph = GetOrCreateParagraph(group, spanParagraphStyle, aiSpanMap);
786         CHECK_NULL_RETURN(paragraph, false);
787         auto paraStart = spanTextLength;
788         paragraphIndex++;
789         for (const auto& child : group) {
790             if (!child) {
791                 continue;
792             }
793             child->paragraphIndex = paragraphIndex;
794             child->SetTextPattern(pattern);
795             switch (child->spanItemType) {
796                 case SpanItemType::NORMAL:
797                     child->aiSpanMap = aiSpanMap;
798                     AddTextSpanToParagraph(child, spanTextLength, frameNode, paragraph);
799                     aiSpanMap = child->aiSpanMap;
800                     break;
801                 case SpanItemType::IMAGE: {
802                     if (iterItems == children.end() || !(*iterItems)) {
803                         continue;
804                     }
805                     auto imageSpanItem = AceType::DynamicCast<ImageSpanItem>(child);
806                     if (!imageSpanItem) {
807                         continue;
808                     }
809                     AddImageToParagraph(imageSpanItem, (*iterItems), paragraph, spanTextLength);
810                     auto imageNode = (*iterItems)->GetHostNode();
811                     imageNodeList.emplace_back(WeakClaim(RawPtr(imageNode)));
812                     iterItems++;
813                     break;
814                 }
815                 case SpanItemType::CustomSpan: {
816                     auto customSpanItem = AceType::DynamicCast<CustomSpanItem>(child);
817                     if (!customSpanItem) {
818                         continue;
819                     }
820                     CustomSpanPlaceholderInfo customSpanPlaceholder;
821                     customSpanPlaceholder.paragraphIndex = paragraphIndex;
822                     UpdateParagraphByCustomSpan(customSpanItem, paragraph, spanTextLength, customSpanPlaceholder);
823                     customSpanPlaceholderInfo.emplace_back(customSpanPlaceholder);
824                     if (customSpanItem->isFrameNode) {
825                         iterItems++; // CAPI custom span is frameNode,need to move the iterator backwards
826                     }
827                     break;
828                 }
829                 case SpanItemType::PLACEHOLDER: {
830                     if (iterItems == children.end() || !(*iterItems)) {
831                         continue;
832                     }
833                     auto placeholderSpanItem = AceType::DynamicCast<PlaceholderSpanItem>(child);
834                     if (!placeholderSpanItem) {
835                         continue;
836                     }
837                     AddPlaceHolderToParagraph(placeholderSpanItem, (*iterItems), paragraph, spanTextLength);
838                     iterItems++;
839                     break;
840                 }
841                 case SpanItemType::SYMBOL:
842                     AddSymbolSpanToParagraph(child, spanTextLength, frameNode, paragraph);
843             }
844             child->ResetReCreateAndReLayout();
845         }
846         preParagraphsPlaceholderCount_ += currentParagraphPlaceholderCount_;
847         currentParagraphPlaceholderCount_ = 0;
848         shadowOffset_ += GetShadowOffset(group);
849         if (!useParagraphCache_) {
850             HandleEmptyParagraph(paragraph, group);
851             paragraph->Build();
852             ParagraphUtil::ApplyIndent(spanParagraphStyle, paragraph, maxWidth, textStyle, GetIndentMaxWidth(maxWidth));
853             UpdateSymbolSpanEffect(frameNode, paragraph, group);
854         }
855         if (paraStyle.maxLines != UINT32_MAX) {
856             paragraph->Layout(static_cast<float>(maxWidth));
857         }
858         paragraphManager_->AddParagraph({ .paragraph = paragraph,
859             .paragraphStyle = spanParagraphStyle,
860             .start = paraStart,
861             .end = spanTextLength });
862     }
863     pattern->SetImageSpanNodeList(imageNodeList);
864     pattern->InitCustomSpanPlaceholderInfo(customSpanPlaceholderInfo);
865     return true;
866 }
867 
InheritParentTextStyle(const TextStyle & textStyle)868 void MultipleParagraphLayoutAlgorithm::InheritParentTextStyle(const TextStyle& textStyle)
869 {
870     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
871         inheritTextStyle_ = textStyle;
872     }
873     inheritTextStyle_.SetMaxLines(textStyle.GetMaxLines());
874     inheritTextStyle_.ResetTextBaselineOffset();
875 }
876 
AddSymbolSpanToParagraph(const RefPtr<SpanItem> & child,int32_t & spanTextLength,const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & paragraph)877 void MultipleParagraphLayoutAlgorithm::AddSymbolSpanToParagraph(const RefPtr<SpanItem>& child, int32_t& spanTextLength,
878     const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph)
879 {
880     child->SetIsParentText(frameNode->GetTag() == V2::TEXT_ETS_TAG);
881     auto pattern = frameNode->GetPattern<TextPattern>();
882     child->UpdateSymbolSpanParagraph(frameNode, inheritTextStyle_, paragraph, pattern && pattern->IsDragging());
883     spanTextLength += SYMBOL_SPAN_LENGTH;
884     child->length = SYMBOL_SPAN_LENGTH;
885     child->position = spanTextLength;
886     child->content = u"  ";
887 }
888 
AddTextSpanToParagraph(const RefPtr<SpanItem> & child,int32_t & spanTextLength,const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & paragraph)889 void MultipleParagraphLayoutAlgorithm::AddTextSpanToParagraph(const RefPtr<SpanItem>& child, int32_t& spanTextLength,
890     const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph)
891 {
892     child->length = child->content.length();
893     spanTextLength += static_cast<int32_t>(child->length);
894     child->position = spanTextLength;
895     child->UpdateParagraph(frameNode, paragraph, inheritTextStyle_, isMarquee_);
896 }
897 
AddImageToParagraph(RefPtr<ImageSpanItem> & imageSpanItem,const RefPtr<LayoutWrapper> & layoutWrapper,const RefPtr<Paragraph> & paragraph,int32_t & spanTextLength)898 void MultipleParagraphLayoutAlgorithm::AddImageToParagraph(RefPtr<ImageSpanItem>& imageSpanItem,
899     const RefPtr<LayoutWrapper>& layoutWrapper, const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength)
900 {
901     auto frameNode = layoutWrapper->GetHostNode();
902     CHECK_NULL_VOID(frameNode);
903     auto id = frameNode->GetId();
904     int32_t targetId = imageSpanItem->nodeId_;
905     if (!isSpanStringMode_) {
906         CHECK_NULL_VOID(id == targetId);
907     }
908     imageSpanItem->placeholderIndex = imageSpanItem->UpdateParagraph(frameNode, paragraph, inheritTextStyle_);
909     currentParagraphPlaceholderCount_++;
910     imageSpanItem->placeholderIndex += preParagraphsPlaceholderCount_;
911     imageSpanItem->content = u" ";
912     spanTextLength += 1;
913     imageSpanItem->position = spanTextLength;
914     imageSpanItem->length = 1;
915 }
916 
AddPlaceHolderToParagraph(RefPtr<PlaceholderSpanItem> & placeholderSpanItem,const RefPtr<LayoutWrapper> & layoutWrapper,const RefPtr<Paragraph> & paragraph,int32_t & spanTextLength)917 void MultipleParagraphLayoutAlgorithm::AddPlaceHolderToParagraph(RefPtr<PlaceholderSpanItem>& placeholderSpanItem,
918     const RefPtr<LayoutWrapper>& layoutWrapper, const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength)
919 {
920     auto frameNode = layoutWrapper->GetHostNode();
921     CHECK_NULL_VOID(frameNode);
922     auto id = frameNode->GetId();
923     int32_t targetId = placeholderSpanItem->placeholderSpanNodeId;
924     CHECK_NULL_VOID(id == targetId);
925     placeholderSpanItem->placeholderIndex =
926         placeholderSpanItem->UpdateParagraph(frameNode, paragraph, inheritTextStyle_);
927     currentParagraphPlaceholderCount_++;
928     placeholderSpanItem->placeholderIndex += preParagraphsPlaceholderCount_;
929     placeholderSpanItem->content = u" ";
930     spanTextLength += 1;
931     placeholderSpanItem->length = 1;
932     placeholderSpanItem->position = spanTextLength;
933 }
934 
UpdateParagraphByCustomSpan(RefPtr<CustomSpanItem> & customSpanItem,const RefPtr<Paragraph> & paragraph,int32_t & spanTextLength,CustomSpanPlaceholderInfo & customSpanPlaceholder)935 void MultipleParagraphLayoutAlgorithm::UpdateParagraphByCustomSpan(RefPtr<CustomSpanItem>& customSpanItem,
936     const RefPtr<Paragraph>& paragraph, int32_t& spanTextLength, CustomSpanPlaceholderInfo& customSpanPlaceholder)
937 {
938     customSpanItem->placeholderIndex = customSpanItem->UpdateParagraph(nullptr, paragraph, inheritTextStyle_);
939     currentParagraphPlaceholderCount_++;
940     customSpanItem->placeholderIndex += preParagraphsPlaceholderCount_;
941     customSpanItem->content = u" ";
942     spanTextLength += 1;
943     customSpanItem->length = 1;
944     customSpanItem->position = spanTextLength;
945     if (customSpanItem->onDraw.has_value()) {
946         customSpanPlaceholder.onDraw = customSpanItem->onDraw.value();
947     }
948     customSpanPlaceholder.customSpanIndex = customSpanItem->placeholderIndex;
949 }
950 
UpdateSymbolSpanEffect(RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & paragraph,const std::list<RefPtr<SpanItem>> & spans)951 void MultipleParagraphLayoutAlgorithm::UpdateSymbolSpanEffect(
952     RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& paragraph, const std::list<RefPtr<SpanItem>>& spans)
953 {
954     for (const auto& child : spans) {
955         if (!child || child->unicode == 0) {
956             continue;
957         }
958         if (child->GetTextStyle()->isSymbolGlyph_) {
959             paragraph->SetParagraphSymbolAnimation(frameNode);
960             return;
961         }
962     }
963 }
964 
GetMaxMeasureSize(const LayoutConstraintF & contentConstraint)965 SizeF MultipleParagraphLayoutAlgorithm::GetMaxMeasureSize(const LayoutConstraintF& contentConstraint)
966 {
967     auto maxSize = contentConstraint.selfIdealSize;
968     maxSize.UpdateIllegalSizeWithCheck(contentConstraint.maxSize);
969     return maxSize.ConvertToSizeT();
970 }
971 } // namespace OHOS::Ace::NG
972