1 /*
2 * Copyright (c) 2022 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/layout/layout_property.h"
17
18 #include <optional>
19
20 #include "base/geometry/ng/size_t.h"
21 #include "base/utils/utils.h"
22 #include "core/components/common/layout/constants.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/base/ui_node.h"
25 #include "core/components_ng/property/calc_length.h"
26 #include "core/components_ng/property/layout_constraint.h"
27 #include "core/components_ng/property/measure_utils.h"
28 #include "core/components_ng/property/safe_area_insets.h"
29 #include "core/components_v2/inspector/inspector_constants.h"
30 #include "core/pipeline_ng/pipeline_context.h"
31
32 namespace OHOS::Ace::NG {
33 namespace {
VisibleTypeToString(VisibleType type)34 std::string VisibleTypeToString(VisibleType type)
35 {
36 static const LinearEnumMapNode<VisibleType, std::string> visibilityMap[] = {
37 { VisibleType::VISIBLE, "Visibility.Visible" },
38 { VisibleType::INVISIBLE, "Visibility.Hidden" },
39 { VisibleType::GONE, "Visibility.None" },
40 };
41 auto idx = BinarySearchFindIndex(visibilityMap, ArraySize(visibilityMap), type);
42 if (idx >= 0) {
43 return visibilityMap[idx].value;
44 }
45 return "Visibility.Visible";
46 }
47
StringToVisibleType(const std::string & str)48 VisibleType StringToVisibleType(const std::string& str)
49 {
50 static const std::unordered_map<std::string, VisibleType> uMap {
51 { "Visibility.Visible", VisibleType::VISIBLE },
52 { "Visibility.Hidden", VisibleType::INVISIBLE },
53 { "Visibility.None", VisibleType::GONE },
54 };
55
56 return uMap.count(str) ? uMap.at(str) : VisibleType::VISIBLE;
57 }
58
TextDirectionToString(TextDirection type)59 std::string TextDirectionToString(TextDirection type)
60 {
61 static const LinearEnumMapNode<TextDirection, std::string> toStringMap[] = {
62 { TextDirection::LTR, "Direction.Ltr" },
63 { TextDirection::RTL, "Direction.Rtl" },
64 { TextDirection::INHERIT, "Direction.Inherit" },
65 { TextDirection::AUTO, "Direction.Auto" },
66 };
67 auto idx = BinarySearchFindIndex(toStringMap, ArraySize(toStringMap), type);
68 if (idx >= 0) {
69 return toStringMap[idx].value;
70 }
71 return "Direction.Ltr";
72 }
73
StringToTextDirection(const std::string & str)74 TextDirection StringToTextDirection(const std::string& str)
75 {
76 static const std::unordered_map<std::string, TextDirection> uMap {
77 { "Direction.Ltr", TextDirection::LTR },
78 { "Direction.Rtl", TextDirection::RTL },
79 { "Direction.Inherit", TextDirection::INHERIT },
80 { "Direction.Auto", TextDirection::AUTO },
81 };
82
83 return uMap.count(str) ? uMap.at(str) : TextDirection::LTR;
84 }
85 } // namespace
86
Reset()87 void LayoutProperty::Reset()
88 {
89 layoutConstraint_.reset();
90 calcLayoutConstraint_.reset();
91 padding_.reset();
92 margin_.reset();
93 borderWidth_.reset();
94 magicItemProperty_.reset();
95 positionProperty_.reset();
96 measureType_.reset();
97 layoutDirection_.reset();
98 propVisibility_.reset();
99 #ifdef ENABLE_DRAG_FRAMEWORK
100 propIsBindOverlay_.reset();
101 #endif // ENABLE_DRAG_FRAMEWORK
102 CleanDirty();
103 }
104
ToJsonValue(std::unique_ptr<JsonValue> & json) const105 void LayoutProperty::ToJsonValue(std::unique_ptr<JsonValue>& json) const
106 {
107 ACE_PROPERTY_TO_JSON_VALUE(calcLayoutConstraint_, MeasureProperty);
108 ACE_PROPERTY_TO_JSON_VALUE(positionProperty_, PositionProperty);
109 ACE_PROPERTY_TO_JSON_VALUE(magicItemProperty_, MagicItemProperty);
110 ACE_PROPERTY_TO_JSON_VALUE(flexItemProperty_, FlexItemProperty);
111 ACE_PROPERTY_TO_JSON_VALUE(gridProperty_, GridProperty);
112
113 if (padding_) {
114 json->Put("padding", padding_->ToJsonString().c_str());
115 } else {
116 json->Put("padding", "0.00vp");
117 }
118
119 if (margin_) {
120 json->Put("margin", margin_->ToJsonString().c_str());
121 } else {
122 json->Put("margin", "0.00vp");
123 }
124
125 json->Put("visibility", VisibleTypeToString(propVisibility_.value_or(VisibleType::VISIBLE)).c_str());
126 json->Put("direction", TextDirectionToString(GetLayoutDirection()).c_str());
127 }
128
FromJson(const std::unique_ptr<JsonValue> & json)129 void LayoutProperty::FromJson(const std::unique_ptr<JsonValue>& json)
130 {
131 UpdateCalcLayoutProperty(MeasureProperty::FromJson(json));
132 UpdateLayoutWeight(json->GetDouble("layoutWeight"));
133 UpdateAlignment(Alignment::GetAlignment(TextDirection::LTR, json->GetString("align")));
134 auto padding = json->GetString("padding");
135 if (padding != "0.0") {
136 UpdatePadding(PaddingProperty::FromJsonString(padding));
137 }
138 auto margin = json->GetString("margin");
139 if (margin != "0.0") {
140 UpdateMargin(MarginProperty::FromJsonString(margin));
141 }
142 UpdateVisibility(StringToVisibleType(json->GetString("visibility")));
143 UpdateLayoutDirection(StringToTextDirection(json->GetString("direction")));
144 }
145
Clone() const146 RefPtr<LayoutProperty> LayoutProperty::Clone() const
147 {
148 auto layoutProperty = MakeRefPtr<LayoutProperty>();
149 Clone(layoutProperty);
150 return layoutProperty;
151 }
152
Clone(RefPtr<LayoutProperty> layoutProperty) const153 void LayoutProperty::Clone(RefPtr<LayoutProperty> layoutProperty) const
154 {
155 layoutProperty->UpdateLayoutProperty(this);
156 }
157
UpdateLayoutProperty(const LayoutProperty * layoutProperty)158 void LayoutProperty::UpdateLayoutProperty(const LayoutProperty* layoutProperty)
159 {
160 layoutConstraint_ = layoutProperty->layoutConstraint_;
161 if (layoutProperty->gridProperty_) {
162 gridProperty_ = std::make_unique<GridProperty>(*layoutProperty->gridProperty_);
163 }
164 if (layoutProperty->calcLayoutConstraint_) {
165 calcLayoutConstraint_ = std::make_unique<MeasureProperty>(*layoutProperty->calcLayoutConstraint_);
166 }
167 if (layoutProperty->padding_) {
168 padding_ = std::make_unique<PaddingProperty>(*layoutProperty->padding_);
169 }
170 if (layoutProperty->margin_) {
171 margin_ = std::make_unique<PaddingProperty>(*layoutProperty->margin_);
172 }
173 if (layoutProperty->borderWidth_) {
174 borderWidth_ = std::make_unique<BorderWidthProperty>(*layoutProperty->borderWidth_);
175 }
176 if (layoutProperty->magicItemProperty_) {
177 magicItemProperty_ = std::make_unique<MagicItemProperty>(*layoutProperty->magicItemProperty_);
178 }
179 if (layoutProperty->positionProperty_) {
180 positionProperty_ = std::make_unique<PositionProperty>(*layoutProperty->positionProperty_);
181 }
182 if (layoutProperty->flexItemProperty_) {
183 flexItemProperty_ = std::make_unique<FlexItemProperty>(*layoutProperty->flexItemProperty_);
184 }
185 if (layoutProperty->safeAreaInsets_) {
186 safeAreaInsets_ = std::make_unique<SafeAreaInsets>(*layoutProperty->safeAreaInsets_);
187 }
188 if (layoutProperty->safeAreaExpandOpts_) {
189 safeAreaExpandOpts_ = std::make_unique<SafeAreaExpandOpts>(*layoutProperty->safeAreaExpandOpts_);
190 }
191 geometryTransition_ = layoutProperty->geometryTransition_;
192 propVisibility_ = layoutProperty->GetVisibility();
193 measureType_ = layoutProperty->measureType_;
194 layoutDirection_ = layoutProperty->layoutDirection_;
195 propertyChangeFlag_ = layoutProperty->propertyChangeFlag_;
196 #ifdef ENABLE_DRAG_FRAMEWORK
197 propIsBindOverlay_ = layoutProperty->propIsBindOverlay_;
198 #endif // ENABLE_DRAG_FRAMEWORK
199 isOverlayNode_ = layoutProperty->isOverlayNode_;
200 overlayOffsetX_ = layoutProperty->overlayOffsetX_;
201 overlayOffsetY_ = layoutProperty->overlayOffsetY_;
202 }
203
UpdateCalcLayoutProperty(const MeasureProperty & constraint)204 void LayoutProperty::UpdateCalcLayoutProperty(const MeasureProperty& constraint)
205 {
206 if (!calcLayoutConstraint_) {
207 calcLayoutConstraint_ = std::make_unique<MeasureProperty>(constraint);
208 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
209 return;
210 }
211 if (*calcLayoutConstraint_ == constraint) {
212 return;
213 }
214 calcLayoutConstraint_->selfIdealSize = constraint.selfIdealSize;
215 calcLayoutConstraint_->maxSize = constraint.maxSize;
216 calcLayoutConstraint_->minSize = constraint.minSize;
217 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
218 }
219
UpdateLayoutConstraint(const LayoutConstraintF & parentConstraint)220 void LayoutProperty::UpdateLayoutConstraint(const LayoutConstraintF& parentConstraint)
221 {
222 layoutConstraint_ = parentConstraint;
223 if (margin_) {
224 // TODO: add margin is negative case.
225 marginResult_.reset();
226 auto margin = CreateMargin();
227 MinusPaddingToSize(margin, layoutConstraint_->maxSize);
228 MinusPaddingToSize(margin, layoutConstraint_->minSize);
229 MinusPaddingToSize(margin, layoutConstraint_->percentReference);
230 MinusPaddingToSize(margin, layoutConstraint_->selfIdealSize);
231 MinusPaddingToSize(margin, layoutConstraint_->parentIdealSize);
232 }
233 if (calcLayoutConstraint_) {
234 if (calcLayoutConstraint_->maxSize.has_value()) {
235 layoutConstraint_->UpdateMaxSizeWithCheck(ConvertToSize(calcLayoutConstraint_->maxSize.value(),
236 parentConstraint.scaleProperty, parentConstraint.percentReference));
237 }
238 if (calcLayoutConstraint_->minSize.has_value()) {
239 layoutConstraint_->UpdateMinSizeWithCheck(ConvertToSize(calcLayoutConstraint_->minSize.value(),
240 parentConstraint.scaleProperty, parentConstraint.percentReference));
241 }
242 if (calcLayoutConstraint_->selfIdealSize.has_value()) {
243 LOGD("CalcLayoutConstraint->selfIdealSize = %{public}s",
244 calcLayoutConstraint_->selfIdealSize.value().ToString().c_str());
245 layoutConstraint_->UpdateIllegalSelfIdealSizeWithCheck(
246 ConvertToOptionalSize(calcLayoutConstraint_->selfIdealSize.value(), parentConstraint.scaleProperty,
247 parentConstraint.percentReference));
248 }
249 }
250
251 CheckSelfIdealSize();
252 CheckBorderAndPadding();
253 CheckAspectRatio();
254 }
255
CheckBorderAndPadding()256 void LayoutProperty::CheckBorderAndPadding()
257 {
258 auto selfWidth = layoutConstraint_->selfIdealSize.Width();
259 auto selfHeight = layoutConstraint_->selfIdealSize.Height();
260 if (!selfWidth && !selfHeight) {
261 return;
262 }
263 auto selfWidthFloat = selfWidth.value_or(Infinity<float>());
264 auto selfHeightFloat = selfHeight.value_or(Infinity<float>());
265 auto paddingWithBorder = CreatePaddingAndBorder();
266 auto deflateWidthF = paddingWithBorder.Width();
267 auto deflateHeightF = paddingWithBorder.Height();
268 if (LessOrEqual(deflateWidthF, selfWidthFloat) && LessOrEqual(deflateHeightF, selfHeightFloat)) {
269 return;
270 }
271 if (GreatNotEqual(deflateWidthF, selfWidthFloat)) {
272 layoutConstraint_->selfIdealSize.SetWidth(deflateWidthF);
273 }
274 if (GreatNotEqual(deflateHeightF, selfHeightFloat)) {
275 layoutConstraint_->selfIdealSize.SetHeight(deflateHeightF);
276 }
277 }
278
CheckAspectRatio()279 void LayoutProperty::CheckAspectRatio()
280 {
281 auto hasAspectRatio = magicItemProperty_ ? magicItemProperty_->HasAspectRatio() : false;
282 if (!hasAspectRatio) {
283 return;
284 }
285 auto aspectRatio = magicItemProperty_->GetAspectRatioValue();
286 // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and aspectRatio are
287 // all set, the height is not used.
288 auto maxWidth = layoutConstraint_->maxSize.Width();
289 auto maxHeight = layoutConstraint_->maxSize.Height();
290 if (maxHeight > maxWidth / aspectRatio) {
291 maxHeight = maxWidth / aspectRatio;
292 }
293 layoutConstraint_->maxSize.SetWidth(maxWidth);
294 layoutConstraint_->maxSize.SetHeight(maxHeight);
295 std::optional<float> selfWidth;
296 std::optional<float> selfHeight;
297 if (layoutConstraint_->selfIdealSize.Width()) {
298 selfWidth = layoutConstraint_->selfIdealSize.Width().value();
299 selfHeight = selfWidth.value() / aspectRatio;
300 if (selfHeight > maxHeight) {
301 selfHeight = maxHeight;
302 selfWidth = selfHeight.value() * aspectRatio;
303 }
304 } else if (layoutConstraint_->selfIdealSize.Height()) {
305 selfHeight = layoutConstraint_->selfIdealSize.Height().value();
306 selfWidth = selfHeight.value() * aspectRatio;
307 if (selfWidth > maxWidth) {
308 selfWidth = maxWidth;
309 selfHeight = selfWidth.value() / aspectRatio;
310 }
311 }
312
313 if (selfHeight) {
314 layoutConstraint_->selfIdealSize.SetHeight(selfHeight);
315 }
316 if (selfWidth) {
317 layoutConstraint_->selfIdealSize.SetWidth(selfWidth);
318 }
319 // TODO: after measure done, need to check AspectRatio again.
320 }
321
BuildGridProperty(const RefPtr<FrameNode> & host)322 void LayoutProperty::BuildGridProperty(const RefPtr<FrameNode>& host)
323 {
324 CHECK_NULL_VOID_NOLOG(gridProperty_);
325 auto parent = host->GetAncestorNodeOfFrame();
326 while (parent) {
327 if (parent->GetTag() == V2::GRIDCONTAINER_ETS_TAG) {
328 auto containerLayout = parent->GetLayoutProperty();
329 gridProperty_->UpdateContainer(containerLayout, host);
330 UpdateUserDefinedIdealSize(CalcSize(CalcLength(gridProperty_->GetWidth()), std::nullopt));
331 break;
332 }
333 parent = parent->GetAncestorNodeOfFrame();
334 }
335 }
336
UpdateGridProperty(std::optional<int32_t> span,std::optional<int32_t> offset,GridSizeType type)337 void LayoutProperty::UpdateGridProperty(std::optional<int32_t> span, std::optional<int32_t> offset, GridSizeType type)
338 {
339 if (!gridProperty_) {
340 gridProperty_ = std::make_unique<GridProperty>();
341 }
342
343 bool isSpanUpdated = (span.has_value() && gridProperty_->UpdateSpan(span.value(), type));
344 bool isOffsetUpdated = (offset.has_value() && gridProperty_->UpdateOffset(offset.value(), type));
345 if (isSpanUpdated || isOffsetUpdated) {
346 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
347 }
348 }
349
UpdateGridOffset(const RefPtr<FrameNode> & host)350 bool LayoutProperty::UpdateGridOffset(const RefPtr<FrameNode>& host)
351 {
352 CHECK_NULL_RETURN_NOLOG(gridProperty_, false);
353 auto optOffset = gridProperty_->GetOffset();
354 if (optOffset == UNDEFINED_DIMENSION) {
355 return false;
356 }
357
358 RefPtr<FrameNode> parent = host->GetAncestorNodeOfFrame();
359 if (!parent) {
360 return false;
361 }
362 auto parentOffset = parent->GetOffsetRelativeToWindow();
363 auto globalOffset = gridProperty_->GetContainerPosition();
364
365 OffsetF offset(optOffset.ConvertToPx(), 0);
366 offset = offset + globalOffset - parentOffset;
367 const auto& geometryNode = host->GetGeometryNode();
368 if (offset.GetX() == geometryNode->GetFrameOffset().GetX()) {
369 return false;
370 }
371 offset.SetY(geometryNode->GetFrameOffset().GetY());
372 geometryNode->SetFrameOffset(offset);
373 return true;
374 }
375
CheckSelfIdealSize()376 void LayoutProperty::CheckSelfIdealSize()
377 {
378 if (measureType_ == MeasureType::MATCH_PARENT) {
379 layoutConstraint_->UpdateIllegalSelfIdealSizeWithCheck(layoutConstraint_->parentIdealSize);
380 }
381 if (!calcLayoutConstraint_) {
382 return;
383 }
384 if (calcLayoutConstraint_->maxSize.has_value()) {
385 layoutConstraint_->selfIdealSize.UpdateSizeWhenSmaller(ConvertToSize(calcLayoutConstraint_->maxSize.value(),
386 layoutConstraint_->scaleProperty, layoutConstraint_->percentReference));
387 }
388 if (calcLayoutConstraint_->minSize.has_value()) {
389 layoutConstraint_->selfIdealSize.UpdateSizeWhenLarger(ConvertToSize(calcLayoutConstraint_->minSize.value(),
390 layoutConstraint_->scaleProperty, layoutConstraint_->percentReference));
391 }
392 }
393
CreateChildConstraint() const394 LayoutConstraintF LayoutProperty::CreateChildConstraint() const
395 {
396 CHECK_NULL_RETURN(layoutConstraint_, {});
397 auto layoutConstraint = contentConstraint_.value();
398 layoutConstraint.parentIdealSize = layoutConstraint.selfIdealSize;
399 // update max size when ideal size has value.
400 if (layoutConstraint.parentIdealSize.Width()) {
401 layoutConstraint.maxSize.SetWidth(layoutConstraint.parentIdealSize.Width().value());
402 layoutConstraint.percentReference.SetWidth(layoutConstraint.parentIdealSize.Width().value());
403 }
404 if (layoutConstraint.parentIdealSize.Height()) {
405 layoutConstraint.maxSize.SetHeight(layoutConstraint.parentIdealSize.Height().value());
406 layoutConstraint.percentReference.SetHeight(layoutConstraint.parentIdealSize.Height().value());
407 }
408 // for child constraint, reset current selfIdealSize and minSize.
409 layoutConstraint.selfIdealSize.Reset();
410 layoutConstraint.minSize.Reset();
411 return layoutConstraint;
412 }
413
UpdateContentConstraint()414 void LayoutProperty::UpdateContentConstraint()
415 {
416 CHECK_NULL_VOID(layoutConstraint_);
417 contentConstraint_ = layoutConstraint_.value();
418 // update percent reference when parent has size.
419 if (contentConstraint_->parentIdealSize.Width()) {
420 contentConstraint_->percentReference.SetWidth(contentConstraint_->parentIdealSize.Width().value());
421 }
422 if (contentConstraint_->parentIdealSize.Height()) {
423 contentConstraint_->percentReference.SetHeight(contentConstraint_->parentIdealSize.Height().value());
424 }
425 if (padding_) {
426 auto paddingF = ConvertToPaddingPropertyF(
427 *padding_, contentConstraint_->scaleProperty, contentConstraint_->percentReference.Width());
428 contentConstraint_->MinusPadding(paddingF.left, paddingF.right, paddingF.top, paddingF.bottom);
429 }
430 if (borderWidth_) {
431 auto borderWidthF = ConvertToBorderWidthPropertyF(
432 *borderWidth_, contentConstraint_->scaleProperty, contentConstraint_->percentReference.Width());
433 contentConstraint_->MinusPadding(
434 borderWidthF.leftDimen, borderWidthF.rightDimen, borderWidthF.topDimen, borderWidthF.bottomDimen);
435 }
436 }
437
CreatePaddingAndBorder()438 PaddingPropertyF LayoutProperty::CreatePaddingAndBorder()
439 {
440 if (layoutConstraint_.has_value()) {
441 auto padding = ConvertToPaddingPropertyF(
442 padding_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
443 auto borderWidth = ConvertToBorderWidthPropertyF(
444 borderWidth_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
445
446 return PaddingPropertyF { padding.left.value_or(0) + borderWidth.leftDimen.value_or(0),
447 padding.right.value_or(0) + borderWidth.rightDimen.value_or(0),
448 padding.top.value_or(0) + borderWidth.topDimen.value_or(0),
449 padding.bottom.value_or(0) + borderWidth.bottomDimen.value_or(0) };
450 }
451 auto padding = ConvertToPaddingPropertyF(
452 padding_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
453 auto borderWidth = ConvertToBorderWidthPropertyF(
454 borderWidth_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
455
456 return PaddingPropertyF { padding.left.value_or(0) + borderWidth.leftDimen.value_or(0),
457 padding.right.value_or(0) + borderWidth.rightDimen.value_or(0),
458 padding.top.value_or(0) + borderWidth.topDimen.value_or(0),
459 padding.bottom.value_or(0) + borderWidth.bottomDimen.value_or(0) };
460 }
461
CreatePaddingAndBorderWithDefault(float paddingHorizontalDefault,float paddingVerticalDefault,float borderHorizontalDefault,float borderVerticalDefault)462 PaddingPropertyF LayoutProperty::CreatePaddingAndBorderWithDefault(float paddingHorizontalDefault,
463 float paddingVerticalDefault, float borderHorizontalDefault, float borderVerticalDefault)
464 {
465 if (layoutConstraint_.has_value()) {
466 auto padding = ConvertToPaddingPropertyF(
467 padding_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
468 auto borderWidth = ConvertToBorderWidthPropertyF(
469 borderWidth_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
470 return PaddingPropertyF { padding.left.value_or(paddingHorizontalDefault) +
471 borderWidth.leftDimen.value_or(borderHorizontalDefault),
472 padding.right.value_or(paddingHorizontalDefault) + borderWidth.rightDimen.value_or(borderHorizontalDefault),
473 padding.top.value_or(paddingVerticalDefault) + borderWidth.topDimen.value_or(borderVerticalDefault),
474 padding.bottom.value_or(paddingVerticalDefault) + borderWidth.bottomDimen.value_or(borderVerticalDefault) };
475 }
476 auto padding = ConvertToPaddingPropertyF(
477 padding_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
478 auto borderWidth = ConvertToBorderWidthPropertyF(
479 borderWidth_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
480
481 return PaddingPropertyF { padding.left.value_or(paddingHorizontalDefault) +
482 borderWidth.leftDimen.value_or(borderHorizontalDefault),
483 padding.right.value_or(paddingHorizontalDefault) + borderWidth.rightDimen.value_or(borderHorizontalDefault),
484 padding.top.value_or(paddingVerticalDefault) + borderWidth.topDimen.value_or(borderVerticalDefault),
485 padding.bottom.value_or(paddingVerticalDefault) + borderWidth.bottomDimen.value_or(borderVerticalDefault) };
486 }
487
CreatePaddingWithoutBorder()488 PaddingPropertyF LayoutProperty::CreatePaddingWithoutBorder()
489 {
490 if (layoutConstraint_.has_value()) {
491 return ConvertToPaddingPropertyF(
492 padding_, layoutConstraint_->scaleProperty, layoutConstraint_->percentReference.Width());
493 }
494
495 return ConvertToPaddingPropertyF(
496 padding_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
497 }
498
CreateMargin()499 MarginPropertyF LayoutProperty::CreateMargin()
500 {
501 CHECK_NULL_RETURN_NOLOG(margin_, MarginPropertyF());
502 if (!marginResult_.has_value() && margin_) {
503 if (layoutConstraint_.has_value()) {
504 marginResult_ = ConvertToMarginPropertyF(
505 margin_, layoutConstraint_->scaleProperty, layoutConstraint_->percentReference.Width());
506 } else {
507 // root node
508 marginResult_ = ConvertToMarginPropertyF(
509 margin_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
510 }
511 }
512 return marginResult_.value_or(MarginPropertyF());
513 }
514
SetHost(const WeakPtr<FrameNode> & host)515 void LayoutProperty::SetHost(const WeakPtr<FrameNode>& host)
516 {
517 host_ = host;
518 }
519
GetHost() const520 RefPtr<FrameNode> LayoutProperty::GetHost() const
521 {
522 return host_.Upgrade();
523 }
524
OnVisibilityUpdate(VisibleType visible,bool allowTransition)525 void LayoutProperty::OnVisibilityUpdate(VisibleType visible, bool allowTransition)
526 {
527 auto host = GetHost();
528 CHECK_NULL_VOID(host);
529 // store the previous visibility value.
530 auto preVisible = host->GetLayoutProperty()->GetVisibilityValue(VisibleType::VISIBLE);
531
532 // update visibility value.
533 propVisibility_ = visible;
534 host->OnVisibleChange(visible == VisibleType::VISIBLE);
535 if (allowTransition) {
536 if (preVisible == VisibleType::VISIBLE && (visible == VisibleType::INVISIBLE || visible == VisibleType::GONE)) {
537 // only trigger transition when visibility changes between visible and invisible.
538 host->GetRenderContext()->OnNodeDisappear(false);
539 } else if ((preVisible == VisibleType::INVISIBLE || preVisible == VisibleType::GONE) &&
540 visible == VisibleType::VISIBLE) {
541 host->GetRenderContext()->OnNodeAppear(false);
542 }
543 }
544
545 auto parent = host->GetAncestorNodeOfFrame();
546 CHECK_NULL_VOID_NOLOG(parent);
547 // if visible is not changed to/from VisibleType::Gone, only need to update render tree.
548 if (preVisible != VisibleType::GONE && visible != VisibleType::GONE) {
549 parent->MarkNeedSyncRenderTree();
550 parent->RebuildRenderContextTree();
551 return;
552 }
553 UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
554 parent->MarkNeedSyncRenderTree();
555 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
556 }
557
UpdateSafeAreaExpandOpts(const SafeAreaExpandOpts & opts)558 void LayoutProperty::UpdateSafeAreaExpandOpts(const SafeAreaExpandOpts& opts)
559 {
560 if (!safeAreaExpandOpts_) {
561 safeAreaExpandOpts_ = std::make_unique<SafeAreaExpandOpts>();
562 }
563 if (*safeAreaExpandOpts_ != opts) {
564 *safeAreaExpandOpts_ = opts;
565 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
566 }
567 }
568
UpdateSafeAreaInsets(const SafeAreaInsets & safeArea)569 void LayoutProperty::UpdateSafeAreaInsets(const SafeAreaInsets& safeArea)
570 {
571 if (!safeAreaInsets_) {
572 safeAreaInsets_ = std::make_unique<SafeAreaInsets>();
573 }
574 if (*safeAreaInsets_ != safeArea) {
575 *safeAreaInsets_ = safeArea;
576 }
577 }
578
HasFixedWidth() const579 bool LayoutProperty::HasFixedWidth() const
580 {
581 CHECK_NULL_RETURN_NOLOG(calcLayoutConstraint_, false);
582 auto&& idealSize = calcLayoutConstraint_->selfIdealSize;
583 return (idealSize && idealSize->WidthFixed());
584 }
585
HasFixedHeight() const586 bool LayoutProperty::HasFixedHeight() const
587 {
588 CHECK_NULL_RETURN_NOLOG(calcLayoutConstraint_, false);
589 auto&& idealSize = calcLayoutConstraint_->selfIdealSize;
590 return (idealSize && idealSize->HeightFixed());
591 }
592
HasAspectRatio() const593 bool LayoutProperty::HasAspectRatio() const
594 {
595 if (!magicItemProperty_) {
596 return false;
597 }
598 return magicItemProperty_->HasAspectRatio();
599 }
600
GetAspectRatio() const601 float LayoutProperty::GetAspectRatio() const
602 {
603 if (magicItemProperty_ && magicItemProperty_->HasAspectRatio()) {
604 return magicItemProperty_->GetAspectRatioValue();
605 }
606 return 0.0f;
607 }
608
UpdateAspectRatio(float ratio)609 void LayoutProperty::UpdateAspectRatio(float ratio)
610 {
611 if (!magicItemProperty_) {
612 magicItemProperty_ = std::make_unique<MagicItemProperty>();
613 }
614 if (magicItemProperty_->UpdateAspectRatio(ratio)) {
615 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
616 }
617 }
618
ResetAspectRatio()619 void LayoutProperty::ResetAspectRatio()
620 {
621 if (!magicItemProperty_) {
622 return;
623 }
624 if (magicItemProperty_->HasAspectRatio()) {
625 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
626 }
627 magicItemProperty_->ResetAspectRatio();
628 }
629
UpdateGeometryTransition(const std::string & id,bool followWithoutTransition)630 void LayoutProperty::UpdateGeometryTransition(const std::string& id, bool followWithoutTransition)
631 {
632 auto host = GetHost();
633 CHECK_NULL_VOID(host);
634
635 auto geometryTransitionOld = GetGeometryTransition();
636 auto geometryTransitionNew =
637 ElementRegister::GetInstance()->GetOrCreateGeometryTransition(id, host_, followWithoutTransition);
638 CHECK_NULL_VOID_NOLOG(geometryTransitionOld != geometryTransitionNew);
639 if (geometryTransitionOld) {
640 geometryTransitionOld->OnFollowWithoutTransition();
641 // unregister node from old geometry transition
642 geometryTransitionOld->Update(host_, nullptr);
643 // register node into new geometry transition
644 if (geometryTransitionNew) {
645 geometryTransitionNew->Update(nullptr, host_);
646 }
647 } else if (geometryTransitionNew) {
648 geometryTransitionNew->Build(host_, true);
649 }
650 geometryTransition_ = geometryTransitionNew;
651
652 LOGD("GeometryTransition: node: %{public}d update id, old id: %{public}s, new id: %{public}s", host->GetId(),
653 geometryTransitionOld ? geometryTransitionOld->GetId().c_str() : "empty",
654 geometryTransitionNew ? id.c_str() : "empty");
655 ElementRegister::GetInstance()->DumpGeometryTransition();
656 }
657
UpdateLayoutDirection(TextDirection value)658 void LayoutProperty::UpdateLayoutDirection(TextDirection value)
659 {
660 if (layoutDirection_ == value) {
661 return;
662 }
663 layoutDirection_ = value;
664 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
665 }
666
UpdateLayoutWeight(float value)667 void LayoutProperty::UpdateLayoutWeight(float value)
668 {
669 if (!magicItemProperty_) {
670 magicItemProperty_ = std::make_unique<MagicItemProperty>();
671 }
672 if (magicItemProperty_->UpdateLayoutWeight(value)) {
673 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
674 }
675 }
676
UpdateBorderWidth(const BorderWidthProperty & value)677 void LayoutProperty::UpdateBorderWidth(const BorderWidthProperty& value)
678 {
679 if (!borderWidth_) {
680 borderWidth_ = std::make_unique<BorderWidthProperty>();
681 }
682 if (borderWidth_->UpdateWithCheck(value)) {
683 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
684 }
685 }
686
UpdateAlignment(Alignment value)687 void LayoutProperty::UpdateAlignment(Alignment value)
688 {
689 if (!positionProperty_) {
690 positionProperty_ = std::make_unique<PositionProperty>();
691 }
692 if (positionProperty_->UpdateAlignment(value)) {
693 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT;
694 }
695 }
696
UpdateMargin(const MarginProperty & value)697 void LayoutProperty::UpdateMargin(const MarginProperty& value)
698 {
699 if (!margin_) {
700 margin_ = std::make_unique<MarginProperty>();
701 }
702 if (margin_->UpdateWithCheck(value)) {
703 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
704 }
705 }
706
UpdatePadding(const PaddingProperty & value)707 void LayoutProperty::UpdatePadding(const PaddingProperty& value)
708 {
709 if (!padding_) {
710 padding_ = std::make_unique<PaddingProperty>();
711 }
712 if (padding_->UpdateWithCheck(value)) {
713 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
714 }
715 }
716
UpdateUserDefinedIdealSize(const CalcSize & value)717 void LayoutProperty::UpdateUserDefinedIdealSize(const CalcSize& value)
718 {
719 if (!calcLayoutConstraint_) {
720 calcLayoutConstraint_ = std::make_unique<MeasureProperty>();
721 }
722 if (calcLayoutConstraint_->UpdateSelfIdealSizeWithCheck(value)) {
723 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
724 }
725 }
726
ClearUserDefinedIdealSize(bool clearWidth,bool clearHeight)727 void LayoutProperty::ClearUserDefinedIdealSize(bool clearWidth, bool clearHeight)
728 {
729 if (!calcLayoutConstraint_) {
730 return;
731 }
732 if (calcLayoutConstraint_->ClearSelfIdealSize(clearWidth, clearHeight)) {
733 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
734 }
735 }
736
UpdateCalcMinSize(const CalcSize & value)737 void LayoutProperty::UpdateCalcMinSize(const CalcSize& value)
738 {
739 if (!calcLayoutConstraint_) {
740 calcLayoutConstraint_ = std::make_unique<MeasureProperty>();
741 }
742 if (calcLayoutConstraint_->UpdateMinSizeWithCheck(value)) {
743 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
744 }
745 }
746
UpdateCalcMaxSize(const CalcSize & value)747 void LayoutProperty::UpdateCalcMaxSize(const CalcSize& value)
748 {
749 if (!calcLayoutConstraint_) {
750 calcLayoutConstraint_ = std::make_unique<MeasureProperty>();
751 }
752 if (calcLayoutConstraint_->UpdateMaxSizeWithCheck(value)) {
753 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
754 }
755 }
756
UpdateMarginSelfIdealSize(const SizeF & value)757 void LayoutProperty::UpdateMarginSelfIdealSize(const SizeF& value)
758 {
759 if (!layoutConstraint_.has_value()) {
760 layoutConstraint_ = LayoutConstraintF();
761 }
762 if (layoutConstraint_->UpdateSelfMarginSizeWithCheck(OptionalSizeF(value))) {
763 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
764 }
765 }
766
ResetCalcMinSize()767 void LayoutProperty::ResetCalcMinSize()
768 {
769 if (!calcLayoutConstraint_) {
770 return;
771 }
772 if (calcLayoutConstraint_->minSize.has_value()) {
773 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
774 }
775 calcLayoutConstraint_->minSize.reset();
776 }
777
ResetCalcMaxSize()778 void LayoutProperty::ResetCalcMaxSize()
779 {
780 if (!calcLayoutConstraint_) {
781 return;
782 }
783 if (calcLayoutConstraint_->maxSize.has_value()) {
784 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
785 }
786 calcLayoutConstraint_->maxSize.reset();
787 }
788
ResetCalcMinSize(bool resetWidth)789 void LayoutProperty::ResetCalcMinSize(bool resetWidth)
790 {
791 if (!calcLayoutConstraint_) {
792 return;
793 }
794 CHECK_NULL_VOID(calcLayoutConstraint_->minSize.has_value());
795 bool resetSizeHasValue = resetWidth ? calcLayoutConstraint_->minSize.value().Width().has_value()
796 : calcLayoutConstraint_->minSize.value().Height().has_value();
797 CHECK_NULL_VOID(resetSizeHasValue);
798 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
799 if (resetWidth) {
800 calcLayoutConstraint_->minSize.value().SetWidth(std::nullopt);
801 } else {
802 calcLayoutConstraint_->minSize.value().SetHeight(std::nullopt);
803 }
804 }
805
ResetCalcMaxSize(bool resetWidth)806 void LayoutProperty::ResetCalcMaxSize(bool resetWidth)
807 {
808 if (!calcLayoutConstraint_) {
809 return;
810 }
811 CHECK_NULL_VOID(calcLayoutConstraint_->maxSize.has_value());
812 bool resetSizeHasValue = resetWidth ? calcLayoutConstraint_->maxSize.value().Width().has_value()
813 : calcLayoutConstraint_->maxSize.value().Height().has_value();
814 CHECK_NULL_VOID(resetSizeHasValue);
815 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
816 if (resetWidth) {
817 calcLayoutConstraint_->maxSize.value().SetWidth(std::nullopt);
818 } else {
819 calcLayoutConstraint_->maxSize.value().SetHeight(std::nullopt);
820 }
821 }
822
UpdateFlexGrow(float flexGrow)823 void LayoutProperty::UpdateFlexGrow(float flexGrow)
824 {
825 if (!flexItemProperty_) {
826 flexItemProperty_ = std::make_unique<FlexItemProperty>();
827 }
828 if (flexItemProperty_->UpdateFlexGrow(flexGrow)) {
829 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
830 }
831 }
832
ResetFlexGrow()833 void LayoutProperty::ResetFlexGrow()
834 {
835 if (!flexItemProperty_) {
836 return;
837 }
838 if (flexItemProperty_->HasFlexGrow()) {
839 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
840 }
841 flexItemProperty_->ResetFlexGrow();
842 }
843
UpdateFlexShrink(float flexShrink)844 void LayoutProperty::UpdateFlexShrink(float flexShrink)
845 {
846 if (!flexItemProperty_) {
847 flexItemProperty_ = std::make_unique<FlexItemProperty>();
848 }
849 if (flexItemProperty_->UpdateFlexShrink(flexShrink)) {
850 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
851 }
852 }
853
ResetFlexShrink()854 void LayoutProperty::ResetFlexShrink()
855 {
856 if (!flexItemProperty_) {
857 return;
858 }
859 if (flexItemProperty_->HasFlexShrink()) {
860 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
861 }
862 flexItemProperty_->ResetFlexShrink();
863 }
864
UpdateFlexBasis(const Dimension & flexBasis)865 void LayoutProperty::UpdateFlexBasis(const Dimension& flexBasis)
866 {
867 if (!flexItemProperty_) {
868 flexItemProperty_ = std::make_unique<FlexItemProperty>();
869 }
870 if (flexItemProperty_->UpdateFlexBasis(flexBasis)) {
871 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
872 }
873 }
874
UpdateAlignSelf(const FlexAlign & flexAlign)875 void LayoutProperty::UpdateAlignSelf(const FlexAlign& flexAlign)
876 {
877 if (!flexItemProperty_) {
878 flexItemProperty_ = std::make_unique<FlexItemProperty>();
879 }
880 if (flexItemProperty_->UpdateAlignSelf(flexAlign)) {
881 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
882 }
883 }
884
ResetAlignSelf()885 void LayoutProperty::ResetAlignSelf()
886 {
887 if (!flexItemProperty_) {
888 return;
889 }
890 if (flexItemProperty_->HasAlignSelf()) {
891 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
892 }
893 flexItemProperty_->ResetAlignSelf();
894 }
895
UpdateAlignRules(const std::map<AlignDirection,AlignRule> & alignRules)896 void LayoutProperty::UpdateAlignRules(const std::map<AlignDirection, AlignRule>& alignRules)
897 {
898 if (!flexItemProperty_) {
899 flexItemProperty_ = std::make_unique<FlexItemProperty>();
900 }
901 if (flexItemProperty_->UpdateAlignRules(alignRules)) {
902 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
903 }
904 }
905
UpdateDisplayIndex(int32_t displayIndex)906 void LayoutProperty::UpdateDisplayIndex(int32_t displayIndex)
907 {
908 if (!flexItemProperty_) {
909 flexItemProperty_ = std::make_unique<FlexItemProperty>();
910 }
911 if (flexItemProperty_->UpdateDisplayIndex(displayIndex)) {
912 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
913 }
914 }
915
CreateContentConstraint() const916 LayoutConstraintF LayoutProperty::CreateContentConstraint() const
917 {
918 auto layoutConstraint = contentConstraint_.value_or(LayoutConstraintF());
919 layoutConstraint.maxSize.UpdateSizeWhenSmaller(layoutConstraint.selfIdealSize.ConvertToSizeT());
920 return layoutConstraint;
921 }
922
UpdateLayoutConstraint(const RefPtr<LayoutProperty> & layoutProperty)923 void LayoutProperty::UpdateLayoutConstraint(const RefPtr<LayoutProperty>& layoutProperty)
924 {
925 layoutConstraint_ = layoutProperty->layoutConstraint_;
926 contentConstraint_ = layoutProperty->contentConstraint_;
927 gridProperty_ =
928 (layoutProperty->gridProperty_) ? std::make_unique<GridProperty>(*layoutProperty->gridProperty_) : nullptr;
929 }
930
UpdateVisibility(const VisibleType & value,bool allowTransition)931 void LayoutProperty::UpdateVisibility(const VisibleType& value, bool allowTransition)
932 {
933 if (propVisibility_.has_value()) {
934 if (NearEqual(propVisibility_.value(), value)) {
935 LOGD("the Visibility is same, just ignore");
936 return;
937 }
938 }
939 OnVisibilityUpdate(value, allowTransition);
940 }
941
SetOverlayOffset(const std::optional<Dimension> & overlayOffsetX,const std::optional<Dimension> & overlayOffsetY)942 void LayoutProperty::SetOverlayOffset(
943 const std::optional<Dimension>& overlayOffsetX, const std::optional<Dimension>& overlayOffsetY)
944 {
945 bool xChanged = true;
946 bool yChanged = false;
947 if ((!overlayOffsetX.has_value() && overlayOffsetX_.Value() == 0) ||
948 (overlayOffsetX.has_value() && overlayOffsetX.value() == overlayOffsetX_)) {
949 xChanged = false;
950 }
951
952 if ((!overlayOffsetY.has_value() && overlayOffsetY_.Value() == 0) ||
953 (overlayOffsetY.has_value() && overlayOffsetY.value() == overlayOffsetY_)) {
954 yChanged = false;
955 }
956
957 if (!xChanged && !yChanged) {
958 return;
959 }
960
961 if (overlayOffsetX.has_value()) {
962 overlayOffsetX_ = overlayOffsetX.value();
963 } else {
964 overlayOffsetX_.Reset();
965 }
966
967 if (overlayOffsetY.has_value()) {
968 overlayOffsetY_ = overlayOffsetY.value();
969 } else {
970 overlayOffsetY_.Reset();
971 }
972
973 propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
974 }
975
GetOverlayOffset(Dimension & overlayOffsetX,Dimension & overlayOffsetY)976 void LayoutProperty::GetOverlayOffset(Dimension& overlayOffsetX, Dimension& overlayOffsetY)
977 {
978 overlayOffsetX = overlayOffsetX_;
979 overlayOffsetY = overlayOffsetY_;
980 }
981
UpdateAllGeometryTransition(const RefPtr<UINode> & parent)982 void LayoutProperty::UpdateAllGeometryTransition(const RefPtr<UINode>& parent)
983 {
984 std::queue<RefPtr<UINode>> q;
985 q.push(parent);
986 while (!q.empty()) {
987 auto node = q.front();
988 q.pop();
989 auto frameNode = AceType::DynamicCast<FrameNode>(node);
990 if (frameNode) {
991 auto layoutProperty = frameNode->GetLayoutProperty();
992 if (layoutProperty && layoutProperty->GetGeometryTransition()) {
993 auto geometryTransitionId = layoutProperty->GetGeometryTransition()->GetId();
994 layoutProperty->UpdateGeometryTransition("");
995 layoutProperty->UpdateGeometryTransition(geometryTransitionId);
996 }
997 }
998 const auto& children = node->GetChildren();
999 for (const auto& child : children) {
1000 q.push(child);
1001 }
1002 }
1003 }
1004
GetPercentSensitive()1005 std::pair<bool, bool> LayoutProperty::GetPercentSensitive()
1006 {
1007 if (!contentConstraint_.has_value()) {
1008 return { false, false };
1009 }
1010 std::pair<bool, bool> res = { false, false };
1011 const auto& constraint = contentConstraint_.value();
1012 if (GreaterOrEqualToInfinity(constraint.maxSize.Height())) {
1013 if (calcLayoutConstraint_ && calcLayoutConstraint_->PercentHeight()) {
1014 res.second = true;
1015 }
1016 }
1017 if (GreaterOrEqualToInfinity(constraint.maxSize.Width())) {
1018 if (calcLayoutConstraint_ && calcLayoutConstraint_->PercentWidth()) {
1019 res.first = true;
1020 }
1021 }
1022 return res;
1023 }
1024
UpdatePercentSensitive(bool width,bool height)1025 std::pair<bool, bool> LayoutProperty::UpdatePercentSensitive(bool width, bool height)
1026 {
1027 if (!contentConstraint_.has_value()) {
1028 return { false, false };
1029 }
1030 const auto& constraint = contentConstraint_.value();
1031 if (GreaterOrEqualToInfinity(constraint.maxSize.Height())) {
1032 heightPercentSensitive_ = heightPercentSensitive_ || height;
1033 }
1034 if (GreaterOrEqualToInfinity(constraint.maxSize.Width())) {
1035 widthPercentSensitive_ = heightPercentSensitive_ || width;
1036 }
1037 return { widthPercentSensitive_, heightPercentSensitive_ };
1038 }
1039
ConstraintEqual(const std::optional<LayoutConstraintF> & preLayoutConstraint,const std::optional<LayoutConstraintF> & preContentConstraint)1040 bool LayoutProperty::ConstraintEqual(const std::optional<LayoutConstraintF>& preLayoutConstraint,
1041 const std::optional<LayoutConstraintF>& preContentConstraint)
1042 {
1043 if (!preLayoutConstraint || !layoutConstraint_) {
1044 return false;
1045 }
1046 if (!preContentConstraint || !contentConstraint_) {
1047 return false;
1048 }
1049 const auto& layout = layoutConstraint_.value();
1050 const auto& content = contentConstraint_.value();
1051 if (GreaterOrEqualToInfinity(layout.maxSize.Width()) && !widthPercentSensitive_) {
1052 return (layout.EqualWithoutPercentWidth(preLayoutConstraint.value()) &&
1053 content.EqualWithoutPercentWidth(preContentConstraint.value()));
1054 }
1055 if (GreaterOrEqualToInfinity(layout.maxSize.Height()) && !heightPercentSensitive_) {
1056 return (layout.EqualWithoutPercentHeight(preLayoutConstraint.value()) &&
1057 content.EqualWithoutPercentHeight(preContentConstraint.value()));
1058 }
1059 return (preLayoutConstraint == layoutConstraint_ && preContentConstraint == contentConstraint_);
1060 }
1061 } // namespace OHOS::Ace::NG
1062