• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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