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