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