• 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 "base/utils/string_expression.h"
17 #include "core/components_ng/layout/layout_property.h"
18 
19 #include "core/pipeline_ng/pipeline_context.h"
20 #include "core/components_ng/property/grid_property.h"
21 
22 namespace OHOS::Ace::NG {
23 namespace {
24 // safeaAreaPadding does not provide default param
25 struct DefaultPaddingBorderParam {
26     float horizontalPadding = 0.0f;
27     float verticalPadding = 0.0f;
28     float horizontalBorder = 0.0f;
29     float verticalBorder = 0.0f;
30 };
31 
CombinePaddingsAndBorder(const PaddingPropertyF & safeAreaPadding,const PaddingPropertyF & padding,const BorderWidthPropertyF & borderWidth,const DefaultPaddingBorderParam & defaultParam)32 PaddingPropertyF CombinePaddingsAndBorder(const PaddingPropertyF& safeAreaPadding, const PaddingPropertyF& padding,
33     const BorderWidthPropertyF& borderWidth, const DefaultPaddingBorderParam& defaultParam)
34 {
35     PaddingPropertyF result;
36     result.left = safeAreaPadding.left.value_or(0.0f) + padding.left.value_or(defaultParam.horizontalPadding) +
37                   borderWidth.leftDimen.value_or(defaultParam.horizontalBorder);
38     result.right = safeAreaPadding.right.value_or(0.0f) + padding.right.value_or(defaultParam.horizontalPadding) +
39                    borderWidth.rightDimen.value_or(defaultParam.horizontalBorder);
40     result.top = safeAreaPadding.top.value_or(0.0f) + padding.top.value_or(defaultParam.verticalPadding) +
41                  borderWidth.topDimen.value_or(defaultParam.verticalBorder);
42     result.bottom = safeAreaPadding.bottom.value_or(0.0f) + padding.bottom.value_or(defaultParam.verticalPadding) +
43                     borderWidth.bottomDimen.value_or(defaultParam.verticalBorder);
44     return result;
45 }
46 
VisibleTypeToString(VisibleType type)47 std::string VisibleTypeToString(VisibleType type)
48 {
49     static const LinearEnumMapNode<VisibleType, std::string> visibilityMap[] = {
50         { VisibleType::VISIBLE, "Visibility.Visible" },
51         { VisibleType::INVISIBLE, "Visibility.Hidden" },
52         { VisibleType::GONE, "Visibility.None" },
53     };
54     auto idx = BinarySearchFindIndex(visibilityMap, ArraySize(visibilityMap), type);
55     if (idx >= 0) {
56         return visibilityMap[idx].value;
57     }
58     return "Visibility.Visible";
59 }
60 
StringToVisibleType(const std::string & str)61 VisibleType StringToVisibleType(const std::string& str)
62 {
63     static const std::unordered_map<std::string, VisibleType> uMap {
64         { "Visibility.Visible", VisibleType::VISIBLE },
65         { "Visibility.Hidden", VisibleType::INVISIBLE },
66         { "Visibility.None", VisibleType::GONE },
67     };
68 
69     auto iter = uMap.find(str);
70     if (iter != uMap.end()) {
71         return iter->second;
72     }
73     return VisibleType::VISIBLE;
74 }
75 
TextDirectionToString(TextDirection type)76 std::string TextDirectionToString(TextDirection type)
77 {
78     static const LinearEnumMapNode<TextDirection, std::string> toStringMap[] = {
79         { TextDirection::LTR, "Direction.Ltr" },
80         { TextDirection::RTL, "Direction.Rtl" },
81         { TextDirection::INHERIT, "Direction.Inherit" },
82         { TextDirection::AUTO, "Direction.Auto" },
83     };
84     auto idx = BinarySearchFindIndex(toStringMap, ArraySize(toStringMap), type);
85     if (idx >= 0) {
86         return toStringMap[idx].value;
87     }
88     return "Direction.Ltr";
89 }
90 
StringToTextDirection(const std::string & str)91 TextDirection StringToTextDirection(const std::string& str)
92 {
93     static const std::unordered_map<std::string, TextDirection> uMap {
94         { "Direction.Ltr", TextDirection::LTR },
95         { "Direction.Rtl", TextDirection::RTL },
96         { "Direction.Inherit", TextDirection::INHERIT },
97         { "Direction.Auto", TextDirection::AUTO },
98     };
99 
100     auto iter = uMap.find(str);
101     if (iter != uMap.end()) {
102         return iter->second;
103     }
104     return TextDirection::LTR;
105 }
106 
ConstrainContentByBorderAndPadding(std::optional<LayoutConstraintF> & contentConstraint,std::optional<LayoutConstraintF> & layoutConstraint,std::unique_ptr<BorderWidthProperty> & borderWidth,std::unique_ptr<PaddingProperty> & padding)107 void ConstrainContentByBorderAndPadding(std::optional<LayoutConstraintF>& contentConstraint,
108     std::optional<LayoutConstraintF>& layoutConstraint, std::unique_ptr<BorderWidthProperty>& borderWidth,
109     std::unique_ptr<PaddingProperty>& padding)
110 {
111     if (padding) {
112         auto paddingF = ConvertToPaddingPropertyF(
113             *padding, contentConstraint->scaleProperty, contentConstraint->percentReference.Width());
114         contentConstraint->MinusPaddingToNonNegativeSize(paddingF.left, paddingF.right, paddingF.top, paddingF.bottom);
115     }
116     CHECK_NULL_VOID(borderWidth);
117     auto borderWidthF = ConvertToBorderWidthPropertyF(
118         *borderWidth, contentConstraint->scaleProperty, layoutConstraint->percentReference.Width());
119     contentConstraint->MinusPaddingToNonNegativeSize(
120         borderWidthF.leftDimen, borderWidthF.rightDimen, borderWidthF.topDimen, borderWidthF.bottomDimen);
121 }
122 
TruncateSafeAreaPadding(const std::optional<float> & range,std::optional<float> & start,std::optional<float> & end)123 void TruncateSafeAreaPadding(const std::optional<float>& range, std::optional<float>& start, std::optional<float>& end)
124 {
125     if (range && start && GreatNotEqual(start.value(), range.value())) {
126         start = range;
127     }
128     if (range && end) {
129         if (start) {
130             end = std::min(range.value() - start.value(), end.value());
131         } else {
132             end = std::min(range, end);
133         }
134     }
135 }
136 } // namespace
137 
138 LayoutProperty::LayoutProperty() = default;
139 
140 LayoutProperty::~LayoutProperty() = default;
141 
Reset()142 void LayoutProperty::Reset()
143 {
144     layoutConstraint_.reset();
145     calcLayoutConstraint_.reset();
146     padding_.reset();
147     safeAreaPadding_.reset();
148     margin_.reset();
149     borderWidth_.reset();
150     outerBorderWidth_.reset();
151     magicItemProperty_.Reset();
152     positionProperty_.reset();
153     measureType_.reset();
154     layoutDirection_.reset();
155     propVisibility_.reset();
156     propIsBindOverlay_.reset();
157     CleanDirty();
158 }
159 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const160 void LayoutProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
161 {
162     ACE_PROPERTY_TO_JSON_VALUE(calcLayoutConstraint_, MeasureProperty);
163     ACE_PROPERTY_TO_JSON_VALUE(positionProperty_, PositionProperty);
164     magicItemProperty_.ToJsonValue(json, filter);
165     ACE_PROPERTY_TO_JSON_VALUE(flexItemProperty_, FlexItemProperty);
166     ACE_PROPERTY_TO_JSON_VALUE(gridProperty_, GridProperty);
167     /* no fixed attr below, just return */
168     if (filter.IsFastFilter()) {
169         return;
170     }
171 
172     PaddingToJsonValue(json, filter);
173     MarginToJsonValue(json, filter);
174     SafeAreaPaddingToJsonValue(json, filter);
175 
176     json->PutExtAttr("visibility",
177         VisibleTypeToString(propVisibility_.value_or(VisibleType::VISIBLE)).c_str(), filter);
178     json->PutExtAttr("direction", TextDirectionToString(GetLayoutDirection()).c_str(), filter);
179     json->PutExtAttr("pixelRound", PixelRoundToJsonValue().c_str(), filter);
180 }
181 
PaddingToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const182 void LayoutProperty::PaddingToJsonValue(std::unique_ptr<JsonValue>& json,
183     const InspectorFilter& filter) const
184 {
185     if (padding_) {
186         if (!padding_->top.has_value() || !padding_->right.has_value()
187             || !padding_->left.has_value() || !padding_->bottom.has_value()) {
188             auto paddingJsonValue = JsonUtil::Create(true);
189             paddingJsonValue->Put("top", padding_->top.has_value()
190                 ? padding_->top.value().ToString().c_str() : "0.00vp");
191             paddingJsonValue->Put("right", padding_->right.has_value()
192                 ? padding_->right.value().ToString().c_str() : "0.00vp");
193             paddingJsonValue->Put("bottom", padding_->bottom.has_value()
194                 ? padding_->bottom.value().ToString().c_str() : "0.00vp");
195             paddingJsonValue->Put("left", padding_->left.has_value()
196                 ? padding_->left.value().ToString().c_str() : "0.00vp");
197             json->PutExtAttr("padding", paddingJsonValue->ToString().c_str(), filter);
198         } else {
199             json->PutExtAttr("padding", padding_->ToJsonString().c_str(), filter);
200         }
201     } else {
202         json->PutExtAttr("padding", "0.00vp", filter);
203     }
204 }
205 
MarginToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const206 void LayoutProperty::MarginToJsonValue(std::unique_ptr<JsonValue>& json,
207     const InspectorFilter& filter) const
208 {
209     if (margin_) {
210         if (!margin_->top.has_value() || !margin_->right.has_value()
211             || !margin_->left.has_value() || !margin_->bottom.has_value()) {
212             auto marginJsonValue = JsonUtil::Create(true);
213             marginJsonValue->Put("top", margin_->top.has_value()
214                 ? margin_->top.value().ToString().c_str() : "0.00vp");
215             marginJsonValue->Put("right", margin_->right.has_value()
216                 ? margin_->right.value().ToString().c_str() : "0.00vp");
217             marginJsonValue->Put("bottom", margin_->bottom.has_value()
218                 ? margin_->bottom.value().ToString().c_str() : "0.00vp");
219             marginJsonValue->Put("left", margin_->left.has_value()
220                 ? margin_->left.value().ToString().c_str() : "0.00vp");
221             json->PutExtAttr("margin", marginJsonValue->ToString().c_str(), filter);
222         } else {
223             json->PutExtAttr("margin", margin_->ToJsonString().c_str(), filter);
224         }
225     } else {
226         json->PutExtAttr("margin", "0.00vp", filter);
227     }
228 }
229 
SafeAreaPaddingToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const230 void LayoutProperty::SafeAreaPaddingToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
231 {
232     if (!safeAreaPadding_) {
233         json->PutExtAttr("safeAreaPadding", "0.00vp", filter);
234         return;
235     }
236     auto hasAllValue = safeAreaPadding_->top.has_value() && safeAreaPadding_->right.has_value() &&
237                        safeAreaPadding_->left.has_value() && safeAreaPadding_->bottom.has_value();
238     if (hasAllValue) {
239         json->PutExtAttr("safeAreaPadding", safeAreaPadding_->ToJsonString().c_str(), filter);
240         return;
241     }
242     auto safeAreaPaddingJsonValue = JsonUtil::Create(true);
243     safeAreaPaddingJsonValue->Put(
244         "top", safeAreaPadding_->top.has_value() ? safeAreaPadding_->top.value().ToString().c_str() : "0.00vp");
245     safeAreaPaddingJsonValue->Put(
246         "right", safeAreaPadding_->right.has_value() ? safeAreaPadding_->right.value().ToString().c_str() : "0.00vp");
247     safeAreaPaddingJsonValue->Put("bottom",
248         safeAreaPadding_->bottom.has_value() ? safeAreaPadding_->bottom.value().ToString().c_str() : "0.00vp");
249     safeAreaPaddingJsonValue->Put(
250         "left", safeAreaPadding_->left.has_value() ? safeAreaPadding_->left.value().ToString().c_str() : "0.00vp");
251     json->PutExtAttr("safeAreaPadding", safeAreaPaddingJsonValue->ToString().c_str(), filter);
252 }
253 
FromJson(const std::unique_ptr<JsonValue> & json)254 void LayoutProperty::FromJson(const std::unique_ptr<JsonValue>& json)
255 {
256     UpdateCalcLayoutProperty(MeasureProperty::FromJson(json));
257     UpdateLayoutWeight(json->GetDouble("layoutWeight"));
258     UpdateAlignment(Alignment::GetAlignment(TextDirection::LTR, json->GetString("align")));
259     auto padding = json->GetString("padding");
260     if (padding != "0.0") {
261         UpdatePadding(PaddingProperty::FromJsonString(padding));
262     }
263     auto margin = json->GetString("margin");
264     if (margin != "0.0") {
265         UpdateMargin(MarginProperty::FromJsonString(margin));
266     }
267     auto safeAreaPadding = json->GetString("safeAreaPadding");
268     if (safeAreaPadding != "0.0") {
269         UpdateSafeAreaPadding(PaddingProperty::FromJsonString(safeAreaPadding));
270     }
271     UpdateVisibility(StringToVisibleType(json->GetString("visibility")));
272     UpdateLayoutDirection(StringToTextDirection(json->GetString("direction")));
273 }
274 
PixelRoundToJsonValue() const275 const std::string LayoutProperty::PixelRoundToJsonValue() const
276 {
277     auto res = JsonUtil::Create(true);
278     if (pixelRoundFlag_ & static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_START)) {
279         res->Put("start", "PixelRoundCalcPolicy.FORCE_CEIL");
280     } else if (pixelRoundFlag_ & static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_START)) {
281         res->Put("start", "PixelRoundCalcPolicy.FORCE_FLOOR");
282     } else {
283         res->Put("start", "PixelRoundCalcPolicy.NO_FORCE_ROUND");
284     }
285     if (pixelRoundFlag_ & static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_TOP)) {
286         res->Put("top", "PixelRoundCalcPolicy.FORCE_CEIL");
287     } else if (pixelRoundFlag_ & static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_TOP)) {
288         res->Put("top", "PixelRoundCalcPolicy.FORCE_FLOOR");
289     } else {
290         res->Put("top", "PixelRoundCalcPolicy.NO_FORCE_ROUND");
291     }
292     if (pixelRoundFlag_ & static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_END)) {
293         res->Put("end", "PixelRoundCalcPolicy.FORCE_CEIL");
294     } else if (pixelRoundFlag_ & static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_END)) {
295         res->Put("end", "PixelRoundCalcPolicy.FORCE_FLOOR");
296     } else {
297         res->Put("end", "PixelRoundCalcPolicy.NO_FORCE_ROUND");
298     }
299     if (pixelRoundFlag_ & static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_BOTTOM)) {
300         res->Put("bottom", "PixelRoundCalcPolicy.FORCE_CEIL");
301     } else if (pixelRoundFlag_ & static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_BOTTOM)) {
302         res->Put("bottom", "PixelRoundCalcPolicy.FORCE_FLOOR");
303     } else {
304         res->Put("bottom", "PixelRoundCalcPolicy.NO_FORCE_ROUND");
305     }
306     return res->ToString();
307 }
308 
Clone() const309 RefPtr<LayoutProperty> LayoutProperty::Clone() const
310 {
311     auto layoutProperty = MakeRefPtr<LayoutProperty>();
312     Clone(layoutProperty);
313     return layoutProperty;
314 }
315 
Clone(RefPtr<LayoutProperty> layoutProperty) const316 void LayoutProperty::Clone(RefPtr<LayoutProperty> layoutProperty) const
317 {
318     layoutProperty->UpdateLayoutProperty(this);
319 }
320 
DecideMirror()321 bool LayoutProperty::DecideMirror()
322 {
323     auto host = GetHost();
324     CHECK_NULL_RETURN(host, false);
325     auto layoutProperty = host->GetLayoutProperty();
326     CHECK_NULL_RETURN(layoutProperty, false);
327     return layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
328 }
329 
UpdateLayoutProperty(const LayoutProperty * layoutProperty)330 void LayoutProperty::UpdateLayoutProperty(const LayoutProperty* layoutProperty)
331 {
332     CHECK_NULL_VOID(layoutProperty);
333     layoutConstraint_ = layoutProperty->layoutConstraint_;
334     if (layoutProperty->gridProperty_) {
335         gridProperty_ = std::make_unique<GridProperty>(*layoutProperty->gridProperty_);
336     }
337     if (layoutProperty->calcLayoutConstraint_) {
338         calcLayoutConstraint_ = std::make_unique<MeasureProperty>(*layoutProperty->calcLayoutConstraint_);
339     }
340     if (layoutProperty->padding_) {
341         padding_ = std::make_unique<PaddingProperty>(*layoutProperty->padding_);
342     }
343     if (layoutProperty->margin_) {
344         margin_ = std::make_unique<PaddingProperty>(*layoutProperty->margin_);
345     }
346     if (layoutProperty->borderWidth_) {
347         borderWidth_ = std::make_unique<BorderWidthProperty>(*layoutProperty->borderWidth_);
348     }
349     magicItemProperty_ = layoutProperty->magicItemProperty_;
350     if (layoutProperty->positionProperty_) {
351         positionProperty_ = std::make_unique<PositionProperty>(*layoutProperty->positionProperty_);
352     }
353     if (layoutProperty->flexItemProperty_) {
354         flexItemProperty_ = std::make_unique<FlexItemProperty>(*layoutProperty->flexItemProperty_);
355     }
356     if (layoutProperty->safeAreaInsets_) {
357         safeAreaInsets_ = std::make_unique<SafeAreaInsets>(*layoutProperty->safeAreaInsets_);
358     }
359     if (layoutProperty->safeAreaExpandOpts_) {
360         safeAreaExpandOpts_ = std::make_unique<SafeAreaExpandOpts>(*layoutProperty->safeAreaExpandOpts_);
361     }
362     geometryTransition_ = layoutProperty->geometryTransition_;
363     propVisibility_ = layoutProperty->GetVisibility();
364     measureType_ = layoutProperty->measureType_;
365     layoutDirection_ = layoutProperty->layoutDirection_;
366     propertyChangeFlag_ = layoutProperty->propertyChangeFlag_;
367     propIsBindOverlay_ = layoutProperty->propIsBindOverlay_;
368     isOverlayNode_ = layoutProperty->isOverlayNode_;
369     overlayOffsetX_ = layoutProperty->overlayOffsetX_;
370     overlayOffsetY_ = layoutProperty->overlayOffsetY_;
371 }
372 
UpdateCalcLayoutProperty(const MeasureProperty & constraint)373 void LayoutProperty::UpdateCalcLayoutProperty(const MeasureProperty& constraint)
374 {
375     if (!calcLayoutConstraint_) {
376         calcLayoutConstraint_ = std::make_unique<MeasureProperty>(constraint);
377         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
378         return;
379     }
380     if (*calcLayoutConstraint_ == constraint) {
381         return;
382     }
383     calcLayoutConstraint_->selfIdealSize = constraint.selfIdealSize;
384     calcLayoutConstraint_->maxSize = constraint.maxSize;
385     calcLayoutConstraint_->minSize = constraint.minSize;
386     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
387 }
388 
CalcToString(const CalcSize & calcSize)389 std::pair<std::vector<std::string>, std::vector<std::string>> LayoutProperty::CalcToString(const CalcSize& calcSize)
390 {
391     std::vector<std::string> widthString;
392     std::vector<std::string> heightString;
393     if (calcSize.Width().has_value() && !calcSize.Width()->CalcValue().empty()) {
394         widthString = StringExpression::ConvertDal2Rpn(calcSize.Width()->CalcValue());
395     }
396     if (calcSize.Height().has_value() && !calcSize.Height()->CalcValue().empty()) {
397         heightString = StringExpression::ConvertDal2Rpn(calcSize.Height()->CalcValue());
398     }
399     return std::pair<std::vector<std::string>, std::vector<std::string>>(widthString, heightString);
400 }
401 
UpdateLayoutConstraint(const LayoutConstraintF & parentConstraint)402 void LayoutProperty::UpdateLayoutConstraint(const LayoutConstraintF& parentConstraint)
403 {
404     layoutConstraint_ = parentConstraint;
405     if (!needLazyLayout_) {
406         layoutConstraint_->viewPosRef.reset();
407     }
408     if (margin_) {
409         marginResult_.reset();
410         auto margin = CreateMargin();
411         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
412             MinusPaddingToNonNegativeSize(margin, layoutConstraint_->maxSize);
413             MinusPaddingToNonNegativeSize(margin, layoutConstraint_->minSize);
414             MinusPaddingToNonNegativeSize(margin, layoutConstraint_->percentReference);
415         } else {
416             MinusPaddingToSize(margin, layoutConstraint_->maxSize);
417             MinusPaddingToSize(margin, layoutConstraint_->minSize);
418             MinusPaddingToSize(margin, layoutConstraint_->percentReference);
419         }
420         // already has non negative protection
421         MinusPaddingToSize(margin, layoutConstraint_->selfIdealSize);
422         MinusPaddingToSize(margin, layoutConstraint_->parentIdealSize);
423     }
424     auto originMax = layoutConstraint_->maxSize;
425 
426     CheckCalcLayoutConstraint(parentConstraint);
427     CheckSelfIdealSize(originMax);
428     CheckBorderAndPadding();
429     CheckAspectRatio();
430 }
431 
CheckCalcLayoutConstraint(const LayoutConstraintF & parentConstraint)432 void LayoutProperty::CheckCalcLayoutConstraint(const LayoutConstraintF& parentConstraint)
433 {
434     if (calcLayoutConstraint_) {
435         if (calcLayoutConstraint_->maxSize.has_value()) {
436             if (!calcLayoutConstraint_->preMaxSize.has_value() ||
437                 calcLayoutConstraint_->preMaxSize.value() != calcLayoutConstraint_->maxSize.value()) {
438                 calcMaxSizeRpn_ = CalcToString(calcLayoutConstraint_->maxSize.value());
439                 calcLayoutConstraint_->preMaxSize = calcLayoutConstraint_->maxSize;
440             }
441             layoutConstraint_->UpdateMaxSizeWithCheck(ConvertToSize(calcLayoutConstraint_->maxSize.value(),
442                 parentConstraint.scaleProperty, parentConstraint.percentReference, calcMaxSizeRpn_));
443         }
444         if (calcLayoutConstraint_->minSize.has_value()) {
445             if (!calcLayoutConstraint_->preMinSize.has_value() ||
446                 calcLayoutConstraint_->preMinSize.value() != calcLayoutConstraint_->minSize.value()) {
447                 calcMinSizeRpn_ = CalcToString(calcLayoutConstraint_->minSize.value());
448                 calcLayoutConstraint_->preMinSize = calcLayoutConstraint_->minSize;
449             }
450             layoutConstraint_->UpdateMinSizeWithCheck(ConvertToSize(calcLayoutConstraint_->minSize.value(),
451                 parentConstraint.scaleProperty, parentConstraint.percentReference, calcMinSizeRpn_));
452         }
453         if (calcLayoutConstraint_->selfIdealSize.has_value()) {
454             if (!calcLayoutConstraint_->preSelfIdealSize.has_value() ||
455                 calcLayoutConstraint_->preSelfIdealSize.value() != calcLayoutConstraint_->selfIdealSize.value()) {
456                 calcSelfIdealSizeRpn_ = CalcToString(calcLayoutConstraint_->selfIdealSize.value());
457                 calcLayoutConstraint_->preSelfIdealSize = calcLayoutConstraint_->selfIdealSize;
458             }
459             layoutConstraint_->UpdateIllegalSelfIdealSizeWithCheck(
460                 ConvertToOptionalSize(calcLayoutConstraint_->selfIdealSize.value(), parentConstraint.scaleProperty,
461                     parentConstraint.percentReference, calcSelfIdealSizeRpn_));
462         }
463     }
464 }
465 
UpdateLayoutConstraintWithLayoutRect()466 void LayoutProperty::UpdateLayoutConstraintWithLayoutRect()
467 {
468     CHECK_NULL_VOID(layoutRect_);
469     auto size = layoutRect_.value().GetSize();
470     layoutConstraint_ = {
471         .scaleProperty = ScaleProperty::CreateScaleProperty(),
472         .minSize = size,
473         .maxSize = size,
474         .percentReference = size,
475         .selfIdealSize = OptionalSizeF(size),
476     };
477 }
478 
CheckBorderAndPadding()479 void LayoutProperty::CheckBorderAndPadding()
480 {
481     auto selfWidth = layoutConstraint_->selfIdealSize.Width();
482     auto selfHeight = layoutConstraint_->selfIdealSize.Height();
483     if (!selfWidth && !selfHeight) {
484         return;
485     }
486     auto selfWidthFloat = selfWidth.value_or(Infinity<float>());
487     auto selfHeightFloat = selfHeight.value_or(Infinity<float>());
488     auto paddingWithBorder = CreatePaddingAndBorder(true, true);
489     auto deflateWidthF = paddingWithBorder.Width();
490     auto deflateHeightF = paddingWithBorder.Height();
491     if (LessOrEqual(deflateWidthF, selfWidthFloat) && LessOrEqual(deflateHeightF, selfHeightFloat)) {
492         return;
493     }
494     if (GreatNotEqual(deflateWidthF, selfWidthFloat)) {
495         layoutConstraint_->selfIdealSize.SetWidth(deflateWidthF);
496     }
497     if (GreatNotEqual(deflateHeightF, selfHeightFloat)) {
498         layoutConstraint_->selfIdealSize.SetHeight(deflateHeightF);
499     }
500 }
501 
CheckAspectRatio()502 void LayoutProperty::CheckAspectRatio()
503 {
504     if (!magicItemProperty_.HasAspectRatio()) {
505         return;
506     }
507     auto aspectRatio = magicItemProperty_.GetAspectRatioValue();
508     // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and aspectRatio are
509     // all set, the height is not used.
510     auto maxWidth = layoutConstraint_->maxSize.Width();
511     auto maxHeight = layoutConstraint_->maxSize.Height();
512     if (maxHeight > maxWidth / aspectRatio) {
513         maxHeight = maxWidth / aspectRatio;
514     }
515     layoutConstraint_->maxSize.SetWidth(maxWidth);
516     layoutConstraint_->maxSize.SetHeight(maxHeight);
517     std::optional<float> selfWidth;
518     std::optional<float> selfHeight;
519     if (layoutConstraint_->selfIdealSize.Width()) {
520         selfWidth = layoutConstraint_->selfIdealSize.Width().value();
521         selfHeight = selfWidth.value() / aspectRatio;
522         if (selfHeight > maxHeight) {
523             selfHeight = maxHeight;
524             selfWidth = selfHeight.value() * aspectRatio;
525         }
526     } else if (layoutConstraint_->selfIdealSize.Height()) {
527         selfHeight = layoutConstraint_->selfIdealSize.Height().value();
528         selfWidth = selfHeight.value() * aspectRatio;
529         if (selfWidth > maxWidth) {
530             selfWidth = maxWidth;
531             selfHeight = selfWidth.value() / aspectRatio;
532         }
533     }
534 
535     if (selfHeight) {
536         layoutConstraint_->selfIdealSize.SetHeight(selfHeight);
537     }
538     if (selfWidth) {
539         layoutConstraint_->selfIdealSize.SetWidth(selfWidth);
540     }
541 }
542 
BuildGridProperty(const RefPtr<FrameNode> & host)543 void LayoutProperty::BuildGridProperty(const RefPtr<FrameNode>& host)
544 {
545     CHECK_NULL_VOID(gridProperty_);
546     auto parent = host->GetAncestorNodeOfFrame(false);
547     while (parent) {
548         if (parent->GetTag() == V2::GRIDCONTAINER_ETS_TAG) {
549             auto containerLayout = parent->GetLayoutProperty();
550             gridProperty_->UpdateContainer(containerLayout, host);
551             UpdateUserDefinedIdealSize(CalcSize(CalcLength(gridProperty_->GetWidth()), std::nullopt));
552             break;
553         }
554         parent = parent->GetAncestorNodeOfFrame(false);
555     }
556 }
557 
UpdateGridProperty(std::optional<int32_t> span,std::optional<int32_t> offset,GridSizeType type)558 void LayoutProperty::UpdateGridProperty(std::optional<int32_t> span, std::optional<int32_t> offset, GridSizeType type)
559 {
560     if (!gridProperty_) {
561         gridProperty_ = std::make_unique<GridProperty>();
562     }
563 
564     bool isSpanUpdated = (span.has_value() && gridProperty_->UpdateSpan(span.value(), type));
565     bool isOffsetUpdated = (offset.has_value() && gridProperty_->UpdateOffset(offset.value(), type));
566     if (isSpanUpdated || isOffsetUpdated) {
567         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
568     }
569 }
570 
UpdateGridOffset(const RefPtr<FrameNode> & host)571 bool LayoutProperty::UpdateGridOffset(const RefPtr<FrameNode>& host)
572 {
573     CHECK_NULL_RETURN(gridProperty_, false);
574     auto optOffset = gridProperty_->GetOffset();
575     if (optOffset == UNDEFINED_DIMENSION) {
576         return false;
577     }
578 
579     RefPtr<FrameNode> parent = host->GetAncestorNodeOfFrame(false);
580     if (!parent) {
581         return false;
582     }
583     auto parentOffset = parent->GetOffsetRelativeToWindow();
584     auto globalOffset = gridProperty_->GetContainerPosition();
585 
586     OffsetF offset(optOffset.ConvertToPx(), 0);
587     offset = offset + globalOffset - parentOffset;
588     const auto& geometryNode = host->GetGeometryNode();
589     if (offset.GetX() == geometryNode->GetFrameOffset().GetX()) {
590         return false;
591     }
592     offset.SetY(geometryNode->GetFrameOffset().GetY());
593     geometryNode->SetFrameOffset(offset);
594     return true;
595 }
596 
CheckSelfIdealSize(const SizeF & originMax)597 void LayoutProperty::CheckSelfIdealSize(const SizeF& originMax)
598 {
599     if (measureType_ == MeasureType::MATCH_PARENT) {
600         layoutConstraint_->UpdateIllegalSelfIdealSizeWithCheck(layoutConstraint_->parentIdealSize);
601     }
602     if (!calcLayoutConstraint_) {
603         return;
604     }
605     SizeF minSize(-1.0f, -1.0f);
606     SizeF maxSize(-1.0f, -1.0f);
607     if (calcLayoutConstraint_->maxSize.has_value()) {
608         maxSize = ConvertToSize(calcLayoutConstraint_->maxSize.value(), layoutConstraint_->scaleProperty,
609             layoutConstraint_->percentReference, calcMaxSizeRpn_);
610     }
611     if (calcLayoutConstraint_->minSize.has_value()) {
612         minSize = ConvertToSize(calcLayoutConstraint_->minSize.value(), layoutConstraint_->scaleProperty,
613             layoutConstraint_->percentReference, calcMinSizeRpn_);
614     }
615     if (calcLayoutConstraint_->maxSize.has_value()) {
616         layoutConstraint_->selfIdealSize.UpdateWidthWhenSmaller(maxSize);
617         if (GreatNotEqual(maxSize.Width(), 0.0f) && GreatOrEqual(maxSize.Width(), minSize.Width())) {
618             layoutConstraint_->UpdateMaxWidthWithCheck(maxSize);
619         } else if (GreatNotEqual(maxSize.Width(), 0.0f) && LessNotEqual(maxSize.Width(), minSize.Width())) {
620             layoutConstraint_->maxSize.SetWidth(minSize.Width());
621         } else {
622             layoutConstraint_->maxSize.SetWidth(originMax.Width());
623         }
624         layoutConstraint_->selfIdealSize.UpdateHeightWhenSmaller(maxSize);
625         if (GreatNotEqual(maxSize.Height(), 0.0f) && GreatOrEqual(maxSize.Height(), minSize.Height())) {
626             layoutConstraint_->UpdateMaxHeightWithCheck(maxSize);
627         } else if (GreatNotEqual(maxSize.Height(), 0.0f) && LessNotEqual(maxSize.Height(), minSize.Height())) {
628             layoutConstraint_->maxSize.SetHeight(minSize.Height());
629         } else {
630             layoutConstraint_->maxSize.SetHeight(originMax.Height());
631         }
632     }
633     layoutConstraint_->UpdateMinSizeWithCheck(minSize);
634     layoutConstraint_->selfIdealSize.UpdateSizeWhenLarger(minSize);
635 }
636 
CreateChildConstraint() const637 LayoutConstraintF LayoutProperty::CreateChildConstraint() const
638 {
639     CHECK_NULL_RETURN(layoutConstraint_, {});
640     auto layoutConstraint = contentConstraint_.value();
641     layoutConstraint.parentIdealSize = layoutConstraint.selfIdealSize;
642     // update max size when ideal size has value.
643     if (layoutConstraint.parentIdealSize.Width()) {
644         layoutConstraint.maxSize.SetWidth(layoutConstraint.parentIdealSize.Width().value());
645         layoutConstraint.percentReference.SetWidth(layoutConstraint.parentIdealSize.Width().value());
646     }
647     if (layoutConstraint.parentIdealSize.Height()) {
648         layoutConstraint.maxSize.SetHeight(layoutConstraint.parentIdealSize.Height().value());
649         layoutConstraint.percentReference.SetHeight(layoutConstraint.parentIdealSize.Height().value());
650     }
651     // for child constraint, reset current selfIdealSize and minSize.
652     layoutConstraint.selfIdealSize.Reset();
653     layoutConstraint.minSize.Reset();
654     return layoutConstraint;
655 }
656 
UpdateContentConstraint()657 void LayoutProperty::UpdateContentConstraint()
658 {
659     CHECK_NULL_VOID(layoutConstraint_);
660     contentConstraint_ = layoutConstraint_.value();
661     // update percent reference when parent has size.
662     if (contentConstraint_->parentIdealSize.Width()) {
663         contentConstraint_->percentReference.SetWidth(contentConstraint_->parentIdealSize.Width().value());
664     }
665     if (contentConstraint_->parentIdealSize.Height()) {
666         contentConstraint_->percentReference.SetHeight(contentConstraint_->parentIdealSize.Height().value());
667     }
668     ConstraintContentByPadding();
669     ConstraintContentByBorder();
670     ConstraintContentBySafeAreaPadding();
671     if (needLazyLayout_ && contentConstraint_->viewPosRef.has_value()) {
672         ConstraintViewPosRef(contentConstraint_->viewPosRef.value());
673     }
674 }
675 
ConstraintViewPosRef(ViewPosReference & posRef)676 void LayoutProperty::ConstraintViewPosRef(ViewPosReference& posRef)
677 {
678     auto axis = posRef.axis;
679     float adjStart = 0.0f;
680     float adjEnd = 0.0f;
681     if (padding_) {
682         auto paddingF = ConvertToPaddingPropertyF(
683             *padding_, contentConstraint_->scaleProperty, contentConstraint_->percentReference.Width());
684         adjStart = axis == Axis::HORIZONTAL ? paddingF.left.value_or(0) : paddingF.top.value_or(0);
685         adjEnd = axis == Axis::HORIZONTAL ? paddingF.right.value_or(0) : paddingF.bottom.value_or(0);
686     }
687     if (borderWidth_) {
688         auto border = ConvertToBorderWidthPropertyF(
689             *borderWidth_, contentConstraint_->scaleProperty, layoutConstraint_->percentReference.Width());
690         adjStart += axis == Axis::HORIZONTAL ? border.leftDimen.value_or(0) : border.topDimen.value_or(0);
691         adjEnd += axis == Axis::HORIZONTAL ? border.rightDimen.value_or(0) : border.bottomDimen.value_or(0);
692     }
693     if (margin_) {
694         auto margin = CreateMargin();
695         adjStart += axis == Axis::HORIZONTAL ? margin.left.value_or(0) : margin.top.value_or(0);
696         adjEnd += axis == Axis::HORIZONTAL ? margin.right.value_or(0) : margin.bottom.value_or(0);
697     }
698     if (posRef.referenceEdge == ReferenceEdge::START) {
699         posRef.referencePos = posRef.referencePos + adjStart;
700     } else {
701         posRef.referencePos = posRef.referencePos - adjEnd;
702     }
703 }
704 
ConstraintContentByPadding()705 void LayoutProperty::ConstraintContentByPadding()
706 {
707     CHECK_NULL_VOID(padding_);
708     auto paddingF = ConvertToPaddingPropertyF(
709         *padding_, contentConstraint_->scaleProperty, contentConstraint_->percentReference.Width());
710     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
711         contentConstraint_->MinusPaddingToNonNegativeSize(paddingF.left, paddingF.right, paddingF.top, paddingF.bottom);
712     } else {
713         contentConstraint_->MinusPadding(paddingF.left, paddingF.right, paddingF.top, paddingF.bottom);
714     }
715 }
716 
ConstraintContentByBorder()717 void LayoutProperty::ConstraintContentByBorder()
718 {
719     CHECK_NULL_VOID(borderWidth_);
720     auto host = GetHost();
721     if (host) {
722         auto pattern = host->GetPattern();
723         if (pattern && pattern->BorderUnoccupied()) {
724             return;
725         }
726     }
727 
728     auto borderWidthF = ConvertToBorderWidthPropertyF(
729         *borderWidth_, contentConstraint_->scaleProperty, layoutConstraint_->percentReference.Width());
730     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
731         contentConstraint_->MinusPaddingToNonNegativeSize(
732             borderWidthF.leftDimen, borderWidthF.rightDimen, borderWidthF.topDimen, borderWidthF.bottomDimen);
733     } else {
734         contentConstraint_->MinusPadding(
735             borderWidthF.leftDimen, borderWidthF.rightDimen, borderWidthF.topDimen, borderWidthF.bottomDimen);
736     }
737 }
738 
ConstraintContentBySafeAreaPadding()739 void LayoutProperty::ConstraintContentBySafeAreaPadding()
740 {
741     CHECK_NULL_VOID(safeAreaPadding_);
742     auto safeAreaPaddingF = ConvertToPaddingPropertyF(
743         *safeAreaPadding_, contentConstraint_->scaleProperty, contentConstraint_->percentReference.Width(), true, true);
744     contentConstraint_->MinusPaddingToNonNegativeSize(
745         safeAreaPaddingF.left, safeAreaPaddingF.right, safeAreaPaddingF.top, safeAreaPaddingF.bottom);
746 }
747 
GetOrCreateSafeAreaPadding(bool forceReCreate)748 PaddingPropertyF LayoutProperty::GetOrCreateSafeAreaPadding(bool forceReCreate)
749 {
750     auto host = GetHost();
751     CHECK_NULL_RETURN(host, CreateSafeAreaPadding());
752     const auto& geometryNode = host->GetGeometryNode();
753     CHECK_NULL_RETURN(geometryNode, CreateSafeAreaPadding());
754     auto& resolvedSafeAreaPadding = geometryNode->GetResolvedSingleSafeAreaPadding();
755     if (forceReCreate || !resolvedSafeAreaPadding) {
756         host->ResetSafeAreaPadding();
757         auto safeAreaPadding = CreateSafeAreaPadding();
758         geometryNode->SetResolvedSingleSafeAreaPadding(safeAreaPadding);
759         return safeAreaPadding;
760     }
761     return *(resolvedSafeAreaPadding.get());
762 }
763 
CreateSafeAreaPadding()764 PaddingPropertyF LayoutProperty::CreateSafeAreaPadding()
765 {
766     if (layoutConstraint_.has_value()) {
767         std::optional<LayoutConstraintF> contentWithSafeArea = layoutConstraint_.value();
768         ConstrainContentByBorderAndPadding(contentWithSafeArea, layoutConstraint_, borderWidth_, padding_);
769         PaddingPropertyF truncatedSafeAreaPadding = ConvertToPaddingPropertyF(safeAreaPadding_,
770             ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width(), true, true);
771         TruncateSafeAreaPadding(
772             contentWithSafeArea->selfIdealSize.Height(), truncatedSafeAreaPadding.top, truncatedSafeAreaPadding.bottom);
773 
774         bool isRtl = DecideMirror() && safeAreaPadding_ &&
775                      (safeAreaPadding_->start.has_value() || safeAreaPadding_->end.has_value());
776         TruncateSafeAreaPadding(contentWithSafeArea->selfIdealSize.Width(),
777             isRtl ? truncatedSafeAreaPadding.right : truncatedSafeAreaPadding.left,
778             isRtl ? truncatedSafeAreaPadding.left : truncatedSafeAreaPadding.right);
779         return truncatedSafeAreaPadding;
780     }
781     return ConvertToPaddingPropertyF(
782         safeAreaPadding_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth(), true, true);
783 }
784 
CreatePaddingAndBorder(bool includeSafeAreaPadding,bool forceReCreate)785 PaddingPropertyF LayoutProperty::CreatePaddingAndBorder(bool includeSafeAreaPadding, bool forceReCreate)
786 {
787     PaddingPropertyF safeAreaPadding;
788     if (includeSafeAreaPadding) {
789         safeAreaPadding = GetOrCreateSafeAreaPadding(forceReCreate);
790     }
791     if (layoutConstraint_.has_value()) {
792         auto padding = ConvertToPaddingPropertyF(
793             padding_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
794         auto borderWidth = ConvertToBorderWidthPropertyF(
795             borderWidth_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
796         auto host = GetHost();
797         if (host) {
798             auto pattern = host->GetPattern();
799             if (pattern && pattern->BorderUnoccupied()) {
800                 borderWidth = BorderWidthPropertyF();
801             }
802         }
803         return CombinePaddingsAndBorder(safeAreaPadding, padding, borderWidth, {});
804     }
805     auto padding = ConvertToPaddingPropertyF(
806         padding_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
807     auto borderWidth = ConvertToBorderWidthPropertyF(
808         borderWidth_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
809     return CombinePaddingsAndBorder(safeAreaPadding, padding, borderWidth, {});
810 }
811 
CreatePaddingAndBorderWithDefault(float paddingHorizontalDefault,float paddingVerticalDefault,float borderHorizontalDefault,float borderVerticalDefault)812 PaddingPropertyF LayoutProperty::CreatePaddingAndBorderWithDefault(float paddingHorizontalDefault,
813     float paddingVerticalDefault, float borderHorizontalDefault, float borderVerticalDefault)
814 {
815     auto safeAreaPadding = GetOrCreateSafeAreaPadding();
816     DefaultPaddingBorderParam defaultParem = { .horizontalPadding = paddingHorizontalDefault,
817         .verticalPadding = paddingVerticalDefault,
818         .horizontalBorder = borderHorizontalDefault,
819         .verticalBorder = borderVerticalDefault };
820     if (layoutConstraint_.has_value()) {
821         auto padding = ConvertToPaddingPropertyF(
822             padding_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
823         auto borderWidth = ConvertToBorderWidthPropertyF(
824             borderWidth_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
825         return CombinePaddingsAndBorder(safeAreaPadding, padding, borderWidth, defaultParem);
826     }
827     auto padding = ConvertToPaddingPropertyF(
828         padding_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
829     auto borderWidth = ConvertToBorderWidthPropertyF(
830         borderWidth_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
831     return CombinePaddingsAndBorder(safeAreaPadding, padding, borderWidth, defaultParem);
832 }
833 
CreatePaddingWithoutBorder(bool useRootConstraint,bool roundPixel)834 PaddingPropertyF LayoutProperty::CreatePaddingWithoutBorder(bool useRootConstraint, bool roundPixel)
835 {
836     auto safeAreaPadding = GetOrCreateSafeAreaPadding();
837     if (layoutConstraint_.has_value()) {
838         auto padding = ConvertToPaddingPropertyF(
839             padding_, layoutConstraint_->scaleProperty, layoutConstraint_->percentReference.Width(), roundPixel);
840         auto totalPadding = CombinePaddingsAndBorder(safeAreaPadding, padding, {}, {});
841         return totalPadding;
842     }
843 
844     auto padding = ConvertToPaddingPropertyF(padding_, ScaleProperty::CreateScaleProperty(),
845         useRootConstraint ? PipelineContext::GetCurrentRootWidth() : 0.0f, roundPixel);
846     auto totalPadding = CombinePaddingsAndBorder(safeAreaPadding, padding, {}, {});
847     return totalPadding;
848 }
849 
CreateBorder()850 BorderWidthPropertyF LayoutProperty::CreateBorder()
851 {
852     // no pixel rounding
853     if (layoutConstraint_.has_value()) {
854         return ConvertToBorderWidthPropertyF(
855             borderWidth_, layoutConstraint_->scaleProperty, layoutConstraint_->percentReference.Width(), false);
856     }
857 
858     return ConvertToBorderWidthPropertyF(
859         borderWidth_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth(), false);
860 }
861 
CreateMargin()862 MarginPropertyF LayoutProperty::CreateMargin()
863 {
864     CHECK_NULL_RETURN(margin_, MarginPropertyF());
865     if (!marginResult_.has_value() && margin_) {
866         if (layoutConstraint_.has_value()) {
867             marginResult_ = ConvertToMarginPropertyF(
868                 margin_, layoutConstraint_->scaleProperty, layoutConstraint_->percentReference.Width());
869         } else {
870             // root node
871             marginResult_ = ConvertToMarginPropertyF(
872                 margin_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
873         }
874     }
875     return marginResult_.value_or(MarginPropertyF());
876 }
877 
CreateMarginWithoutCache()878 MarginPropertyF LayoutProperty::CreateMarginWithoutCache()
879 {
880     CHECK_NULL_RETURN(margin_, MarginPropertyF());
881     auto host = GetHost();
882     CHECK_NULL_RETURN(host, MarginPropertyF());
883     const auto& parentConstraint = host->GetGeometryNode()->GetParentLayoutConstraint();
884     // no pixel rounding
885     if (parentConstraint) {
886         return ConvertToMarginPropertyF(
887             margin_, parentConstraint->scaleProperty, parentConstraint->percentReference.Width(), false);
888     }
889     // the root width is not considered at present.
890     return ConvertToMarginPropertyF(margin_, ScaleProperty::CreateScaleProperty(), 0.0f, false);
891 }
892 
SetHost(const WeakPtr<FrameNode> & host)893 void LayoutProperty::SetHost(const WeakPtr<FrameNode>& host)
894 {
895     host_ = host;
896 }
897 
GetHost() const898 RefPtr<FrameNode> LayoutProperty::GetHost() const
899 {
900     return host_.Upgrade();
901 }
902 
OnVisibilityUpdate(VisibleType visible,bool allowTransition,bool isUserSet)903 void LayoutProperty::OnVisibilityUpdate(VisibleType visible, bool allowTransition, bool isUserSet)
904 {
905     auto host = GetHost();
906     CHECK_NULL_VOID(host);
907     // store the previous visibility value.
908     auto preVisibility = propVisibility_;
909 
910     // update visibility value.
911     propVisibility_ = visible;
912     auto pipeline = host->GetContext();
913     uint64_t vsyncTime = 0;
914     if (pipeline) {
915         vsyncTime = pipeline->GetVsyncTime();
916     }
917     host->AddVisibilityDumpInfo({ vsyncTime, { visible, isUserSet } });
918 
919     host->NotifyVisibleChange(preVisibility.value_or(VisibleType::VISIBLE), visible);
920     if (allowTransition && preVisibility) {
921         if (preVisibility.value() == VisibleType::VISIBLE && visible != VisibleType::VISIBLE) {
922             auto renderContext = host->GetRenderContext();
923             CHECK_NULL_VOID(renderContext);
924             renderContext->OnNodeDisappear(false);
925         } else if (preVisibility.value() != VisibleType::VISIBLE && visible == VisibleType::VISIBLE) {
926             auto renderContext = host->GetRenderContext();
927             CHECK_NULL_VOID(renderContext);
928             renderContext->OnNodeAppear(false);
929         }
930     }
931 
932     auto parent = host->GetAncestorNodeOfFrame(false);
933     CHECK_NULL_VOID(parent);
934     // if visible is not changed to/from VisibleType::Gone, only need to update render tree.
935     if (preVisibility.value_or(VisibleType::VISIBLE) != VisibleType::GONE && visible != VisibleType::GONE) {
936         parent->MarkNeedSyncRenderTree();
937         parent->RebuildRenderContextTree();
938         return;
939     }
940     UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
941     parent->MarkNeedSyncRenderTree();
942     parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
943 }
944 
UpdateSafeAreaExpandOpts(const SafeAreaExpandOpts & opts)945 void LayoutProperty::UpdateSafeAreaExpandOpts(const SafeAreaExpandOpts& opts)
946 {
947     if (!safeAreaExpandOpts_) {
948         safeAreaExpandOpts_ = std::make_unique<SafeAreaExpandOpts>();
949     }
950     if (*safeAreaExpandOpts_ != opts) {
951         *safeAreaExpandOpts_ = opts;
952         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
953         safeAreaExpandOpts_->switchToNone = !opts.Expansive();
954     }
955 }
956 
UpdateSafeAreaInsets(const SafeAreaInsets & safeArea)957 void LayoutProperty::UpdateSafeAreaInsets(const SafeAreaInsets& safeArea)
958 {
959     if (!safeAreaInsets_) {
960         safeAreaInsets_ = std::make_unique<SafeAreaInsets>();
961     }
962     if (*safeAreaInsets_ != safeArea) {
963         *safeAreaInsets_ = safeArea;
964     }
965 }
966 
HasFixedWidth(bool checkPercent) const967 bool LayoutProperty::HasFixedWidth(bool checkPercent) const
968 {
969     CHECK_NULL_RETURN(calcLayoutConstraint_, false);
970     auto&& idealSize = calcLayoutConstraint_->selfIdealSize;
971     return (idealSize && idealSize->WidthFixed(checkPercent));
972 }
973 
HasFixedHeight(bool checkPercent) const974 bool LayoutProperty::HasFixedHeight(bool checkPercent) const
975 {
976     CHECK_NULL_RETURN(calcLayoutConstraint_, false);
977     auto&& idealSize = calcLayoutConstraint_->selfIdealSize;
978     return (idealSize && idealSize->HeightFixed(checkPercent));
979 }
980 
HasAspectRatio() const981 bool LayoutProperty::HasAspectRatio() const
982 {
983     return magicItemProperty_.HasAspectRatio();
984 }
985 
GetAspectRatio() const986 float LayoutProperty::GetAspectRatio() const
987 {
988     if (magicItemProperty_.HasAspectRatio()) {
989         return magicItemProperty_.GetAspectRatioValue();
990     }
991     return 0.0f;
992 }
993 
UpdateAspectRatio(float ratio)994 void LayoutProperty::UpdateAspectRatio(float ratio)
995 {
996     if (magicItemProperty_.UpdateAspectRatio(ratio)) {
997         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
998     }
999 }
1000 
ResetAspectRatio()1001 void LayoutProperty::ResetAspectRatio()
1002 {
1003     if (magicItemProperty_.HasAspectRatio()) {
1004         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1005         magicItemProperty_.ResetAspectRatio();
1006     }
1007 }
1008 
UpdateGeometryTransition(const std::string & id,bool followWithoutTransition,bool doRegisterSharedTransition)1009 void LayoutProperty::UpdateGeometryTransition(const std::string& id,
1010     bool followWithoutTransition, bool doRegisterSharedTransition)
1011 {
1012     auto host = GetHost();
1013     CHECK_NULL_VOID(host);
1014 
1015     auto geometryTransitionOld = GetGeometryTransition();
1016     auto geometryTransitionNew =
1017         ElementRegister::GetInstance()->GetOrCreateGeometryTransition(id,
1018             followWithoutTransition, doRegisterSharedTransition);
1019     CHECK_NULL_VOID(geometryTransitionOld != geometryTransitionNew);
1020     if (geometryTransitionOld) {
1021         if (geometryTransitionOld->Update(host_, host_)) {
1022             geometryTransitionOld->OnFollowWithoutTransition();
1023         }
1024         // unregister node from old geometry transition
1025         geometryTransitionOld->Update(host_, nullptr);
1026         // register node into new geometry transition
1027         if (geometryTransitionNew && !geometryTransitionNew->Update(nullptr, host_)) {
1028             TAG_LOGE(AceLogTag::ACE_GEOMETRY_TRANSITION, "redundant node%{public}d has same geoid: %{public}s",
1029                 host->GetId(), id.c_str());
1030         }
1031     } else if (geometryTransitionNew) {
1032         if (geometryTransitionNew->IsInAndOutValid()) {
1033             TAG_LOGE(AceLogTag::ACE_GEOMETRY_TRANSITION, "redundant node%{public}d has same geoid: %{public}s",
1034                 host->GetId(), id.c_str());
1035         }
1036         geometryTransitionNew->Build(host_, true);
1037     }
1038     geometryTransition_ = geometryTransitionNew;
1039 
1040     TAG_LOGD(AceLogTag::ACE_GEOMETRY_TRANSITION, "node: %{public}d update id, old id: %{public}s, new id: %{public}s",
1041         host->GetId(), geometryTransitionOld ? geometryTransitionOld->GetId().c_str() : "empty",
1042         geometryTransitionNew ? id.c_str() : "empty");
1043     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1044 }
1045 
ResetGeometryTransition()1046 void LayoutProperty::ResetGeometryTransition()
1047 {
1048     if (!GetGeometryTransition()) {
1049         return;
1050     }
1051     UpdateGeometryTransition("");
1052 }
1053 
UpdateLayoutDirection(TextDirection value)1054 void LayoutProperty::UpdateLayoutDirection(TextDirection value)
1055 {
1056     if (layoutDirection_ == value) {
1057         return;
1058     }
1059     layoutDirection_ = value;
1060     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1061     OnPropertyChangeMeasure();
1062 }
1063 
GetNonAutoLayoutDirection() const1064 TextDirection LayoutProperty::GetNonAutoLayoutDirection() const
1065 {
1066     auto direction = layoutDirection_.value_or(TextDirection::AUTO);
1067     return direction != TextDirection::AUTO
1068                ? direction
1069                : (AceApplicationInfo::GetInstance().IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR);
1070 }
1071 
UpdateLayoutWeight(float value)1072 void LayoutProperty::UpdateLayoutWeight(float value)
1073 {
1074     if (magicItemProperty_.UpdateLayoutWeight(value)) {
1075         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1076     }
1077 }
1078 
UpdateChainWeight(const ChainWeightPair & value)1079 void LayoutProperty::UpdateChainWeight(const ChainWeightPair& value)
1080 {
1081     if (flexItemProperty_->UpdateChainWeight(value)) {
1082         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1083     }
1084 }
1085 
UpdateBorderWidth(const BorderWidthProperty & value)1086 void LayoutProperty::UpdateBorderWidth(const BorderWidthProperty& value)
1087 {
1088     if (!borderWidth_) {
1089         borderWidth_ = std::make_unique<BorderWidthProperty>();
1090     }
1091     if (borderWidth_->UpdateWithCheck(value)) {
1092         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1093     }
1094 }
1095 
UpdateOuterBorderWidth(const BorderWidthProperty & value)1096 void LayoutProperty::UpdateOuterBorderWidth(const BorderWidthProperty& value)
1097 {
1098     if (!outerBorderWidth_) {
1099         outerBorderWidth_ = std::make_unique<BorderWidthProperty>();
1100     }
1101     if (outerBorderWidth_->UpdateWithCheck(value)) {
1102         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1103     }
1104 }
1105 
UpdateAlignment(Alignment value)1106 void LayoutProperty::UpdateAlignment(Alignment value)
1107 {
1108     if (!positionProperty_) {
1109         positionProperty_ = std::make_unique<PositionProperty>();
1110     }
1111     if (positionProperty_->UpdateAlignment(value)) {
1112         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT;
1113     }
1114 }
1115 
UpdateMargin(const MarginProperty & value)1116 void LayoutProperty::UpdateMargin(const MarginProperty& value)
1117 {
1118     if (!margin_) {
1119         margin_ = std::make_unique<MarginProperty>();
1120     }
1121     if (margin_->UpdateWithCheck(value)) {
1122         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1123     }
1124 }
1125 
UpdatePadding(const PaddingProperty & value)1126 void LayoutProperty::UpdatePadding(const PaddingProperty& value)
1127 {
1128     if (!padding_) {
1129         padding_ = std::make_unique<PaddingProperty>();
1130     }
1131     if (padding_->UpdateWithCheck(value)) {
1132         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1133     }
1134 }
1135 
UpdateSafeAreaPadding(const PaddingProperty & value)1136 void LayoutProperty::UpdateSafeAreaPadding(const PaddingProperty& value)
1137 {
1138     if (!safeAreaPadding_) {
1139         safeAreaPadding_ = std::make_unique<PaddingProperty>();
1140     }
1141     if (safeAreaPadding_->UpdateWithCheck(value)) {
1142         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1143     }
1144 }
1145 
ResetSafeAreaPadding()1146 void LayoutProperty::ResetSafeAreaPadding()
1147 {
1148     if (!safeAreaPadding_) {
1149         return;
1150     }
1151     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1152     safeAreaPadding_.reset();
1153 }
1154 
UpdateUserDefinedIdealSize(const CalcSize & value)1155 void LayoutProperty::UpdateUserDefinedIdealSize(const CalcSize& value)
1156 {
1157     if (!calcLayoutConstraint_) {
1158         calcLayoutConstraint_ = std::make_unique<MeasureProperty>();
1159     }
1160     if (calcLayoutConstraint_->UpdateSelfIdealSizeWithCheck(value)) {
1161         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1162     }
1163 }
1164 
ClearUserDefinedIdealSize(bool clearWidth,bool clearHeight)1165 void LayoutProperty::ClearUserDefinedIdealSize(bool clearWidth, bool clearHeight)
1166 {
1167     if (!calcLayoutConstraint_) {
1168         return;
1169     }
1170     if (calcLayoutConstraint_->ClearSelfIdealSize(clearWidth, clearHeight)) {
1171         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1172     }
1173 }
1174 
UpdateCalcMinSize(const CalcSize & value)1175 void LayoutProperty::UpdateCalcMinSize(const CalcSize& value)
1176 {
1177     if (!calcLayoutConstraint_) {
1178         calcLayoutConstraint_ = std::make_unique<MeasureProperty>();
1179     }
1180     if (calcLayoutConstraint_->UpdateMinSizeWithCheck(value)) {
1181         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1182     }
1183 }
1184 
UpdateCalcMaxSize(const CalcSize & value)1185 void LayoutProperty::UpdateCalcMaxSize(const CalcSize& value)
1186 {
1187     if (!calcLayoutConstraint_) {
1188         calcLayoutConstraint_ = std::make_unique<MeasureProperty>();
1189     }
1190     if (calcLayoutConstraint_->UpdateMaxSizeWithCheck(value)) {
1191         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1192     }
1193 }
1194 
UpdateMarginSelfIdealSize(const SizeF & value)1195 void LayoutProperty::UpdateMarginSelfIdealSize(const SizeF& value)
1196 {
1197     if (!layoutConstraint_.has_value()) {
1198         layoutConstraint_ = LayoutConstraintF();
1199     }
1200     if (layoutConstraint_->UpdateSelfMarginSizeWithCheck(OptionalSizeF(value))) {
1201         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1202     }
1203 }
1204 
ResetCalcMinSize()1205 void LayoutProperty::ResetCalcMinSize()
1206 {
1207     if (!calcLayoutConstraint_) {
1208         return;
1209     }
1210     if (calcLayoutConstraint_->minSize.has_value()) {
1211         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1212     }
1213     calcLayoutConstraint_->minSize.reset();
1214     calcLayoutConstraint_->preMinSize.reset();
1215 }
1216 
ResetCalcMaxSize()1217 void LayoutProperty::ResetCalcMaxSize()
1218 {
1219     if (!calcLayoutConstraint_) {
1220         return;
1221     }
1222     if (calcLayoutConstraint_->maxSize.has_value()) {
1223         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1224     }
1225     calcLayoutConstraint_->maxSize.reset();
1226     calcLayoutConstraint_->preMaxSize.reset();
1227 }
1228 
ResetCalcMinSize(bool resetWidth)1229 void LayoutProperty::ResetCalcMinSize(bool resetWidth)
1230 {
1231     if (!calcLayoutConstraint_) {
1232         return;
1233     }
1234     CHECK_NULL_VOID(calcLayoutConstraint_->minSize.has_value());
1235     bool resetSizeHasValue = resetWidth ? calcLayoutConstraint_->minSize.value().Width().has_value()
1236                                         : calcLayoutConstraint_->minSize.value().Height().has_value();
1237     CHECK_NULL_VOID(resetSizeHasValue);
1238     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1239     if (resetWidth) {
1240         calcLayoutConstraint_->minSize.value().SetWidth(std::nullopt);
1241     } else {
1242         calcLayoutConstraint_->minSize.value().SetHeight(std::nullopt);
1243     }
1244 }
1245 
ResetCalcMaxSize(bool resetWidth)1246 void LayoutProperty::ResetCalcMaxSize(bool resetWidth)
1247 {
1248     if (!calcLayoutConstraint_) {
1249         return;
1250     }
1251     CHECK_NULL_VOID(calcLayoutConstraint_->maxSize.has_value());
1252     bool resetSizeHasValue = resetWidth ? calcLayoutConstraint_->maxSize.value().Width().has_value()
1253                                         : calcLayoutConstraint_->maxSize.value().Height().has_value();
1254     CHECK_NULL_VOID(resetSizeHasValue);
1255     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1256     if (resetWidth) {
1257         calcLayoutConstraint_->maxSize.value().SetWidth(std::nullopt);
1258     } else {
1259         calcLayoutConstraint_->maxSize.value().SetHeight(std::nullopt);
1260     }
1261 }
1262 
UpdateFlexGrow(float flexGrow)1263 void LayoutProperty::UpdateFlexGrow(float flexGrow)
1264 {
1265     if (!flexItemProperty_) {
1266         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1267     }
1268     if (flexItemProperty_->UpdateFlexGrow(flexGrow)) {
1269         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1270     }
1271 }
1272 
ResetFlexGrow()1273 void LayoutProperty::ResetFlexGrow()
1274 {
1275     if (!flexItemProperty_) {
1276         return;
1277     }
1278     if (flexItemProperty_->HasFlexGrow()) {
1279         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1280     }
1281     flexItemProperty_->ResetFlexGrow();
1282 }
1283 
UpdateFlexShrink(float flexShrink)1284 void LayoutProperty::UpdateFlexShrink(float flexShrink)
1285 {
1286     if (!flexItemProperty_) {
1287         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1288     }
1289     if (flexItemProperty_->UpdateFlexShrink(flexShrink)) {
1290         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1291     }
1292 }
1293 
ResetFlexShrink()1294 void LayoutProperty::ResetFlexShrink()
1295 {
1296     if (!flexItemProperty_) {
1297         return;
1298     }
1299     if (flexItemProperty_->HasFlexShrink()) {
1300         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1301     }
1302     flexItemProperty_->ResetFlexShrink();
1303 }
1304 
UpdateFlexBasis(const Dimension & flexBasis)1305 void LayoutProperty::UpdateFlexBasis(const Dimension& flexBasis)
1306 {
1307     if (!flexItemProperty_) {
1308         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1309     }
1310     if (flexItemProperty_->UpdateFlexBasis(flexBasis)) {
1311         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1312     }
1313 }
1314 
UpdateAlignSelf(const FlexAlign & flexAlign)1315 void LayoutProperty::UpdateAlignSelf(const FlexAlign& flexAlign)
1316 {
1317     if (!flexItemProperty_) {
1318         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1319     }
1320     if (flexItemProperty_->UpdateAlignSelf(flexAlign)) {
1321         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1322     }
1323 }
1324 
ResetAlignSelf()1325 void LayoutProperty::ResetAlignSelf()
1326 {
1327     if (!flexItemProperty_) {
1328         return;
1329     }
1330     if (flexItemProperty_->HasAlignSelf()) {
1331         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1332     }
1333     flexItemProperty_->ResetAlignSelf();
1334 }
1335 
UpdateAlignRules(const std::map<AlignDirection,AlignRule> & alignRules)1336 void LayoutProperty::UpdateAlignRules(const std::map<AlignDirection, AlignRule>& alignRules)
1337 {
1338     if (!flexItemProperty_) {
1339         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1340     }
1341     if (flexItemProperty_->UpdateAlignRules(alignRules)) {
1342         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1343     }
1344 }
1345 
UpdateChainStyle(const ChainInfo & chainInfo)1346 void LayoutProperty::UpdateChainStyle(const ChainInfo& chainInfo)
1347 {
1348     if (!flexItemProperty_) {
1349         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1350     }
1351     if (!chainInfo.direction.has_value()) {
1352         ChainInfo nullChainInfo;
1353         if (flexItemProperty_->UpdateHorizontalChainStyle(nullChainInfo)) {
1354             propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1355         }
1356         if (flexItemProperty_->UpdateVerticalChainStyle(nullChainInfo)) {
1357             propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1358         }
1359     }
1360     if (chainInfo.direction == LineDirection::HORIZONTAL) {
1361         if (flexItemProperty_->UpdateHorizontalChainStyle(chainInfo)) {
1362             propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1363         }
1364     } else {
1365         if (flexItemProperty_->UpdateVerticalChainStyle(chainInfo)) {
1366             propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1367         }
1368     }
1369 }
1370 
UpdateBias(const BiasPair & biasPair)1371 void LayoutProperty::UpdateBias(const BiasPair& biasPair)
1372 {
1373     if (!flexItemProperty_) {
1374         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1375     }
1376     if (flexItemProperty_->UpdateBias(biasPair)) {
1377         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1378     }
1379 }
1380 
UpdateDisplayIndex(int32_t displayIndex)1381 void LayoutProperty::UpdateDisplayIndex(int32_t displayIndex)
1382 {
1383     if (!flexItemProperty_) {
1384         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1385     }
1386     if (flexItemProperty_->UpdateDisplayIndex(displayIndex)) {
1387         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT;
1388     }
1389 }
1390 
CreateContentConstraint() const1391 LayoutConstraintF LayoutProperty::CreateContentConstraint() const
1392 {
1393     auto layoutConstraint = contentConstraint_.value_or(LayoutConstraintF());
1394     layoutConstraint.maxSize.UpdateSizeWhenSmaller(layoutConstraint.selfIdealSize.ConvertToSizeT());
1395     return layoutConstraint;
1396 }
1397 
UpdateLayoutConstraint(const RefPtr<LayoutProperty> & layoutProperty)1398 void LayoutProperty::UpdateLayoutConstraint(const RefPtr<LayoutProperty>& layoutProperty)
1399 {
1400     layoutConstraint_ = layoutProperty->layoutConstraint_;
1401     contentConstraint_ = layoutProperty->contentConstraint_;
1402     gridProperty_ =
1403         (layoutProperty->gridProperty_) ? std::make_unique<GridProperty>(*layoutProperty->gridProperty_) : nullptr;
1404 }
1405 
UpdateVisibility(const VisibleType & value,bool allowTransition,bool isUserSet)1406 void LayoutProperty::UpdateVisibility(const VisibleType& value, bool allowTransition, bool isUserSet)
1407 {
1408     isUserSetVisibility_ = isUserSet;
1409     if (propVisibility_.has_value()) {
1410         if (NearEqual(propVisibility_.value(), value)) {
1411             return;
1412         }
1413     }
1414     OnVisibilityUpdate(value, allowTransition, isUserSet);
1415 }
1416 
SetOverlayOffset(const std::optional<Dimension> & overlayOffsetX,const std::optional<Dimension> & overlayOffsetY)1417 void LayoutProperty::SetOverlayOffset(
1418     const std::optional<Dimension>& overlayOffsetX, const std::optional<Dimension>& overlayOffsetY)
1419 {
1420     bool xChanged = true;
1421     bool yChanged = false;
1422     if ((!overlayOffsetX.has_value() && overlayOffsetX_.Value() == 0) ||
1423         (overlayOffsetX.has_value() && overlayOffsetX.value() == overlayOffsetX_)) {
1424         xChanged = false;
1425     }
1426 
1427     if ((!overlayOffsetY.has_value() && overlayOffsetY_.Value() == 0) ||
1428         (overlayOffsetY.has_value() && overlayOffsetY.value() == overlayOffsetY_)) {
1429         yChanged = false;
1430     }
1431 
1432     if (!xChanged && !yChanged) {
1433         return;
1434     }
1435 
1436     if (overlayOffsetX.has_value()) {
1437         overlayOffsetX_ = overlayOffsetX.value();
1438     } else {
1439         overlayOffsetX_.Reset();
1440     }
1441 
1442     if (overlayOffsetY.has_value()) {
1443         overlayOffsetY_ = overlayOffsetY.value();
1444     } else {
1445         overlayOffsetY_.Reset();
1446     }
1447 
1448     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1449 }
1450 
GetOverlayOffset(Dimension & overlayOffsetX,Dimension & overlayOffsetY)1451 void LayoutProperty::GetOverlayOffset(Dimension& overlayOffsetX, Dimension& overlayOffsetY)
1452 {
1453     overlayOffsetX = overlayOffsetX_;
1454     overlayOffsetY = overlayOffsetY_;
1455 }
1456 
UpdateAllGeometryTransition(const RefPtr<UINode> & parent)1457 void LayoutProperty::UpdateAllGeometryTransition(const RefPtr<UINode>& parent)
1458 {
1459     std::queue<RefPtr<UINode>> q;
1460     q.push(parent);
1461     while (!q.empty()) {
1462         auto node = q.front();
1463         q.pop();
1464         auto frameNode = AceType::DynamicCast<FrameNode>(node);
1465         if (frameNode) {
1466             auto layoutProperty = frameNode->GetLayoutProperty();
1467             if (layoutProperty && layoutProperty->GetGeometryTransition()) {
1468                 auto geometryTransitionId = layoutProperty->GetGeometryTransition()->GetId();
1469                 layoutProperty->UpdateGeometryTransition("");
1470                 layoutProperty->UpdateGeometryTransition(geometryTransitionId);
1471             }
1472         }
1473         const auto& children = node->GetChildren();
1474         for (const auto& child : children) {
1475             q.push(child);
1476         }
1477     }
1478 }
1479 
GetPercentSensitive()1480 std::pair<bool, bool> LayoutProperty::GetPercentSensitive()
1481 {
1482     if (!contentConstraint_.has_value()) {
1483         return { false, false };
1484     }
1485     std::pair<bool, bool> res = { false, false };
1486     const auto& constraint = contentConstraint_.value();
1487     if (GreaterOrEqualToInfinity(constraint.maxSize.Height())) {
1488         if (calcLayoutConstraint_ && calcLayoutConstraint_->PercentHeight()) {
1489             res.second = true;
1490         }
1491     }
1492     if (GreaterOrEqualToInfinity(constraint.maxSize.Width())) {
1493         if (calcLayoutConstraint_ && calcLayoutConstraint_->PercentWidth()) {
1494             res.first = true;
1495         }
1496     }
1497     return res;
1498 }
1499 
UpdatePercentSensitive(bool width,bool height)1500 std::pair<bool, bool> LayoutProperty::UpdatePercentSensitive(bool width, bool height)
1501 {
1502     if (!contentConstraint_.has_value()) {
1503         return { false, false };
1504     }
1505     const auto& constraint = contentConstraint_.value();
1506     if (GreaterOrEqualToInfinity(constraint.maxSize.Height())) {
1507         heightPercentSensitive_ = heightPercentSensitive_ || height;
1508     }
1509     if (GreaterOrEqualToInfinity(constraint.maxSize.Width())) {
1510         widthPercentSensitive_ = heightPercentSensitive_ || width;
1511     }
1512     return { widthPercentSensitive_, heightPercentSensitive_ };
1513 }
1514 
ConstraintEqual(const std::optional<LayoutConstraintF> & preLayoutConstraint,const std::optional<LayoutConstraintF> & preContentConstraint)1515 bool LayoutProperty::ConstraintEqual(const std::optional<LayoutConstraintF>& preLayoutConstraint,
1516     const std::optional<LayoutConstraintF>& preContentConstraint)
1517 {
1518     if (!preLayoutConstraint || !layoutConstraint_) {
1519         return false;
1520     }
1521     if (!preContentConstraint || !contentConstraint_) {
1522         return false;
1523     }
1524     bool isNeedPercent = false;
1525     auto host = GetHost();
1526     if (host) {
1527         auto pattern = host->GetPattern();
1528         isNeedPercent = pattern ? pattern->IsNeedPercent() : false;
1529     }
1530     const auto& layout = layoutConstraint_.value();
1531     const auto& content = contentConstraint_.value();
1532     if (!isNeedPercent && GreaterOrEqualToInfinity(layout.maxSize.Width()) && !widthPercentSensitive_) {
1533         return (layout.EqualWithoutPercentWidth(preLayoutConstraint.value()) &&
1534                 content.EqualWithoutPercentWidth(preContentConstraint.value()));
1535     }
1536     if (!isNeedPercent && GreaterOrEqualToInfinity(layout.maxSize.Height()) && !heightPercentSensitive_) {
1537         return (layout.EqualWithoutPercentHeight(preLayoutConstraint.value()) &&
1538                 content.EqualWithoutPercentHeight(preContentConstraint.value()));
1539     }
1540     return (preLayoutConstraint == layoutConstraint_ && preContentConstraint == contentConstraint_);
1541 }
1542 
CheckPositionLocalizedEdges(TextDirection layoutDirection)1543 void LayoutProperty::CheckPositionLocalizedEdges(TextDirection layoutDirection)
1544 {
1545     auto host = GetHost();
1546     CHECK_NULL_VOID(host);
1547     const auto& target = host->GetRenderContext();
1548     CHECK_NULL_VOID(target);
1549     EdgesParam edges;
1550     auto positionEdges = target->GetPositionEdgesValue(EdgesParam {});
1551     if (!positionEdges.start.has_value() && !positionEdges.end.has_value()) {
1552         return;
1553     }
1554     if (positionEdges.top.has_value()) {
1555         edges.SetTop(positionEdges.top.value_or(Dimension(0.0)));
1556     }
1557     if (positionEdges.bottom.has_value()) {
1558         edges.SetBottom(positionEdges.bottom.value_or(Dimension(0.0)));
1559     }
1560     if (positionEdges.start.has_value()) {
1561         edges.start = positionEdges.start.value();
1562         if (layoutDirection == TextDirection::RTL) {
1563             edges.SetRight(positionEdges.start.value_or(Dimension(0.0)));
1564         } else {
1565             edges.SetLeft(positionEdges.start.value_or(Dimension(0.0)));
1566         }
1567     }
1568     if (positionEdges.end.has_value()) {
1569         edges.end = positionEdges.end.value();
1570         if (layoutDirection == TextDirection::RTL) {
1571             edges.SetLeft(positionEdges.end.value_or(Dimension(0.0)));
1572         } else {
1573             edges.SetRight(positionEdges.end.value_or(Dimension(0.0)));
1574         }
1575     }
1576     target->UpdatePositionEdges(edges);
1577 }
1578 
CheckMarkAnchorPosition(TextDirection layoutDirection)1579 void LayoutProperty::CheckMarkAnchorPosition(TextDirection layoutDirection)
1580 {
1581     auto host = GetHost();
1582     CHECK_NULL_VOID(host);
1583     const auto& target = host->GetRenderContext();
1584     CHECK_NULL_VOID(target);
1585     CalcDimension x;
1586     CalcDimension y;
1587     auto anchor = target->GetAnchorValue({});
1588     if (!markAnchorStart_.has_value()) {
1589         return;
1590     }
1591     OffsetT<Dimension> offset(Dimension(0.0), Dimension(0.0));
1592     if (markAnchorStart_.has_value()) {
1593         x = layoutDirection == TextDirection::RTL ? -markAnchorStart_.value() : markAnchorStart_.value();
1594         offset.SetX(x);
1595     }
1596     offset.SetY(anchor.GetY());
1597     target->UpdateAnchor(offset);
1598 }
1599 
CheckOffsetLocalizedEdges(TextDirection layoutDirection)1600 void LayoutProperty::CheckOffsetLocalizedEdges(TextDirection layoutDirection)
1601 {
1602     auto host = GetHost();
1603     CHECK_NULL_VOID(host);
1604     const auto& target = host->GetRenderContext();
1605     CHECK_NULL_VOID(target);
1606     EdgesParam edges;
1607     auto offsetEdges = target->GetOffsetEdgesValue(EdgesParam {});
1608     if (!offsetEdges.start.has_value() && !offsetEdges.end.has_value()) {
1609         return;
1610     }
1611     if (offsetEdges.top.has_value()) {
1612         edges.SetTop(offsetEdges.top.value_or(Dimension(0.0)));
1613     }
1614     if (offsetEdges.bottom.has_value()) {
1615         edges.SetBottom(offsetEdges.bottom.value_or(Dimension(0.0)));
1616     }
1617     if (offsetEdges.start.has_value()) {
1618         edges.start = offsetEdges.start.value();
1619         if (layoutDirection == TextDirection::RTL) {
1620             edges.SetRight(offsetEdges.start.value_or(Dimension(0.0)));
1621         } else {
1622             edges.SetLeft(offsetEdges.start.value_or(Dimension(0.0)));
1623         }
1624     }
1625     if (offsetEdges.end.has_value()) {
1626         edges.end = offsetEdges.end.value();
1627         if (layoutDirection == TextDirection::RTL) {
1628             edges.SetLeft(offsetEdges.end.value_or(Dimension(0.0)));
1629         } else {
1630             edges.SetRight(offsetEdges.end.value_or(Dimension(0.0)));
1631         }
1632     }
1633     target->UpdateOffsetEdges(edges);
1634 }
1635 
CheckLocalizedBorderRadiuses(const TextDirection & direction)1636 void LayoutProperty::CheckLocalizedBorderRadiuses(const TextDirection& direction)
1637 {
1638     auto host = GetHost();
1639     CHECK_NULL_VOID(host);
1640     const auto& target = host->GetRenderContext();
1641     CHECK_NULL_VOID(target);
1642     BorderRadiusProperty borderRadius;
1643     BorderRadiusProperty borderRadiusProperty = target->GetBorderRadiusValue(BorderRadiusProperty {});
1644     if (!borderRadiusProperty.radiusTopStart.has_value() && !borderRadiusProperty.radiusTopEnd.has_value() &&
1645         !borderRadiusProperty.radiusBottomStart.has_value() && !borderRadiusProperty.radiusBottomEnd.has_value()) {
1646         return;
1647     }
1648     if (borderRadiusProperty.radiusTopStart.has_value()) {
1649         borderRadius.radiusTopStart = borderRadiusProperty.radiusTopStart;
1650         if (direction == TextDirection::RTL) {
1651             borderRadius.radiusTopRight = borderRadiusProperty.radiusTopStart;
1652         } else {
1653             borderRadius.radiusTopLeft = borderRadiusProperty.radiusTopStart;
1654         }
1655     }
1656     if (borderRadiusProperty.radiusTopEnd.has_value()) {
1657         borderRadius.radiusTopEnd = borderRadiusProperty.radiusTopEnd;
1658         if (direction == TextDirection::RTL) {
1659             borderRadius.radiusTopLeft = borderRadiusProperty.radiusTopEnd;
1660         } else {
1661             borderRadius.radiusTopRight = borderRadiusProperty.radiusTopEnd;
1662         }
1663     }
1664     if (borderRadiusProperty.radiusBottomStart.has_value()) {
1665         borderRadius.radiusBottomStart = borderRadiusProperty.radiusBottomStart;
1666         if (direction == TextDirection::RTL) {
1667             borderRadius.radiusBottomRight = borderRadiusProperty.radiusBottomStart;
1668         } else {
1669             borderRadius.radiusBottomLeft = borderRadiusProperty.radiusBottomStart;
1670         }
1671     }
1672     if (borderRadiusProperty.radiusBottomEnd.has_value()) {
1673         borderRadius.radiusBottomEnd = borderRadiusProperty.radiusBottomEnd;
1674         if (direction == TextDirection::RTL) {
1675             borderRadius.radiusBottomLeft = borderRadiusProperty.radiusBottomEnd;
1676         } else {
1677             borderRadius.radiusBottomRight = borderRadiusProperty.radiusBottomEnd;
1678         }
1679     }
1680     target->UpdateBorderRadius(borderRadius);
1681 }
1682 
CheckLocalizedOuterBorderColor(const TextDirection & direction)1683 void LayoutProperty::CheckLocalizedOuterBorderColor(const TextDirection& direction)
1684 {
1685     auto host = GetHost();
1686     CHECK_NULL_VOID(host);
1687     const auto& target = host->GetRenderContext();
1688     CHECK_NULL_VOID(target);
1689     NG::BorderColorProperty borderColors;
1690     borderColors.multiValued = true;
1691     auto outerBorderColorProperty = target->GetOuterBorderColorValue(BorderColorProperty {});
1692     if (!outerBorderColorProperty.startColor.has_value() && !outerBorderColorProperty.endColor.has_value()) {
1693         return;
1694     }
1695     if (outerBorderColorProperty.startColor.has_value()) {
1696         borderColors.startColor = outerBorderColorProperty.startColor;
1697         if (direction == TextDirection::RTL) {
1698             borderColors.rightColor = outerBorderColorProperty.startColor;
1699         } else {
1700             borderColors.leftColor = outerBorderColorProperty.startColor;
1701         }
1702     }
1703     if (outerBorderColorProperty.endColor.has_value()) {
1704         borderColors.endColor = outerBorderColorProperty.endColor;
1705         if (direction == TextDirection::RTL) {
1706             borderColors.leftColor = outerBorderColorProperty.endColor;
1707         } else {
1708             borderColors.rightColor = outerBorderColorProperty.endColor;
1709         }
1710     }
1711     if (outerBorderColorProperty.topColor.has_value()) {
1712         borderColors.topColor = outerBorderColorProperty.topColor;
1713     }
1714     if (outerBorderColorProperty.bottomColor.has_value()) {
1715         borderColors.topColor = outerBorderColorProperty.bottomColor;
1716     }
1717     target->UpdateOuterBorderColor(borderColors);
1718 }
1719 
CheckLocalizedPadding(const RefPtr<LayoutProperty> & layoutProperty,const TextDirection & direction)1720 void LayoutProperty::CheckLocalizedPadding(const RefPtr<LayoutProperty>& layoutProperty, const TextDirection& direction)
1721 {
1722     CHECK_NULL_VOID(layoutProperty);
1723     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
1724     CHECK_NULL_VOID(paddingProperty);
1725     if (!paddingProperty->start.has_value() && !paddingProperty->end.has_value()) {
1726         return;
1727     }
1728     PaddingProperty padding;
1729     if (paddingProperty->start.has_value()) {
1730         padding.start = paddingProperty->start;
1731         if (direction == TextDirection::RTL) {
1732             padding.right = paddingProperty->start;
1733         } else {
1734             padding.left = paddingProperty->start;
1735         }
1736     }
1737     if (paddingProperty->end.has_value()) {
1738         padding.end = paddingProperty->end;
1739         if (direction == TextDirection::RTL) {
1740             padding.left = paddingProperty->end;
1741         } else {
1742             padding.right = paddingProperty->end;
1743         }
1744     }
1745     if (paddingProperty->top.has_value()) {
1746         padding.top = paddingProperty->top;
1747     }
1748     if (paddingProperty->bottom.has_value()) {
1749         padding.bottom = paddingProperty->bottom;
1750     }
1751     if (padding.left.has_value() && !padding.right.has_value()) {
1752         padding.right = std::optional<CalcLength>(CalcLength(0));
1753     }
1754     if (!padding.left.has_value() && padding.right.has_value()) {
1755         padding.left = std::optional<CalcLength>(CalcLength(0));
1756     }
1757     LocalizedPaddingOrMarginChange(padding, padding_);
1758 }
1759 
CheckLocalizedMargin(const RefPtr<LayoutProperty> & layoutProperty,const TextDirection & direction)1760 void LayoutProperty::CheckLocalizedMargin(const RefPtr<LayoutProperty>& layoutProperty, const TextDirection& direction)
1761 {
1762     CHECK_NULL_VOID(layoutProperty);
1763     const auto& marginProperty = layoutProperty->GetMarginProperty();
1764     CHECK_NULL_VOID(marginProperty);
1765     if (!marginProperty->start.has_value() && !marginProperty->end.has_value()) {
1766         return;
1767     }
1768     MarginProperty margin;
1769     if (marginProperty->start.has_value()) {
1770         margin.start = marginProperty->start;
1771         if (direction == TextDirection::RTL) {
1772             margin.right = marginProperty->start;
1773         } else {
1774             margin.left = marginProperty->start;
1775         }
1776     }
1777     if (marginProperty->end.has_value()) {
1778         margin.end = marginProperty->end;
1779         if (direction == TextDirection::RTL) {
1780             margin.left = marginProperty->end;
1781         } else {
1782             margin.right = marginProperty->end;
1783         }
1784     }
1785     if (marginProperty->top.has_value()) {
1786         margin.top = marginProperty->top;
1787     }
1788     if (marginProperty->bottom.has_value()) {
1789         margin.bottom = marginProperty->bottom;
1790     }
1791     if (margin.left.has_value() && !margin.right.has_value()) {
1792         margin.right = std::optional<CalcLength>(CalcLength(0));
1793     }
1794     if (!margin.left.has_value() && margin.right.has_value()) {
1795         margin.left = std::optional<CalcLength>(CalcLength(0));
1796     }
1797     LocalizedPaddingOrMarginChange(margin, margin_);
1798 }
1799 
CheckLocalizedSafeAreaPadding(const TextDirection & direction)1800 void LayoutProperty::CheckLocalizedSafeAreaPadding(const TextDirection& direction)
1801 {
1802     const auto& safeAreaPaddingProperty = GetSafeAreaPaddingProperty();
1803     CHECK_NULL_VOID(safeAreaPaddingProperty);
1804     if (!safeAreaPaddingProperty->start.has_value() && !safeAreaPaddingProperty->end.has_value()) {
1805         return;
1806     }
1807     PaddingProperty safeAreaPadding;
1808     if (safeAreaPaddingProperty->start.has_value()) {
1809         safeAreaPadding.start = safeAreaPaddingProperty->start;
1810         if (direction == TextDirection::RTL) {
1811             safeAreaPadding.right = safeAreaPaddingProperty->start;
1812         } else {
1813             safeAreaPadding.left = safeAreaPaddingProperty->start;
1814         }
1815     }
1816     if (safeAreaPaddingProperty->end.has_value()) {
1817         safeAreaPadding.end = safeAreaPaddingProperty->end;
1818         if (direction == TextDirection::RTL) {
1819             safeAreaPadding.left = safeAreaPaddingProperty->end;
1820         } else {
1821             safeAreaPadding.right = safeAreaPaddingProperty->end;
1822         }
1823     }
1824     if (safeAreaPaddingProperty->top.has_value()) {
1825         safeAreaPadding.top = safeAreaPaddingProperty->top;
1826     }
1827     if (safeAreaPaddingProperty->bottom.has_value()) {
1828         safeAreaPadding.bottom = safeAreaPaddingProperty->bottom;
1829     }
1830     if (safeAreaPadding.left.has_value() && !safeAreaPadding.right.has_value()) {
1831         safeAreaPadding.right = std::optional<CalcLength>(CalcLength(0));
1832     }
1833     if (!safeAreaPadding.left.has_value() && safeAreaPadding.right.has_value()) {
1834         safeAreaPadding.left = std::optional<CalcLength>(CalcLength(0));
1835     }
1836     LocalizedPaddingOrMarginChange(safeAreaPadding, safeAreaPadding_);
1837 }
1838 
LocalizedPaddingOrMarginChange(const PaddingProperty & value,std::unique_ptr<PaddingProperty> & padding)1839 void LayoutProperty::LocalizedPaddingOrMarginChange(
1840     const PaddingProperty& value, std::unique_ptr<PaddingProperty>& padding)
1841 {
1842     if (value != *padding || padding->start != value.start || padding->end != value.end) {
1843         padding->start = value.start;
1844         padding->end = value.end;
1845         padding->left = value.left;
1846         padding->right = value.right;
1847         padding->top = value.top;
1848         padding->bottom = value.bottom;
1849         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1850     }
1851 }
1852 
CheckLocalizedEdgeWidths(const RefPtr<LayoutProperty> & layoutProperty,const TextDirection & direction)1853 void LayoutProperty::CheckLocalizedEdgeWidths(
1854     const RefPtr<LayoutProperty>& layoutProperty, const TextDirection& direction)
1855 {
1856     CHECK_NULL_VOID(layoutProperty);
1857     auto host = GetHost();
1858     CHECK_NULL_VOID(host);
1859     const auto& target = host->GetRenderContext();
1860     CHECK_NULL_VOID(target);
1861     auto borderWidthProperty = target->GetBorderWidth();
1862     CHECK_NULL_VOID(borderWidthProperty);
1863     if (!borderWidthProperty->startDimen.has_value() && !borderWidthProperty->endDimen.has_value()) {
1864         return;
1865     }
1866     BorderWidthProperty borderWidth;
1867     if (borderWidthProperty->startDimen.has_value()) {
1868         borderWidth.startDimen = borderWidthProperty->startDimen;
1869         if (direction == TextDirection::RTL) {
1870             borderWidth.rightDimen = borderWidthProperty->startDimen;
1871         } else {
1872             borderWidth.leftDimen = borderWidthProperty->startDimen;
1873         }
1874     }
1875     if (borderWidthProperty->endDimen.has_value()) {
1876         borderWidth.endDimen = borderWidthProperty->endDimen;
1877         if (direction == TextDirection::RTL) {
1878             borderWidth.leftDimen = borderWidthProperty->endDimen;
1879         } else {
1880             borderWidth.rightDimen = borderWidthProperty->endDimen;
1881         }
1882     }
1883     if (borderWidthProperty->topDimen.has_value()) {
1884         borderWidth.topDimen = borderWidthProperty->topDimen;
1885     }
1886     if (borderWidthProperty->bottomDimen.has_value()) {
1887         borderWidth.bottomDimen = borderWidthProperty->bottomDimen;
1888     }
1889     if (borderWidth.leftDimen.has_value() && !borderWidth.rightDimen.has_value()) {
1890         borderWidth.rightDimen = std::optional<Dimension>(Dimension(0));
1891     }
1892     if (!borderWidth.leftDimen.has_value() && borderWidth.rightDimen.has_value()) {
1893         borderWidth.leftDimen = std::optional<Dimension>(Dimension(0));
1894     }
1895     borderWidth.multiValued = true;
1896     layoutProperty->UpdateBorderWidth(borderWidth);
1897     target->UpdateBorderWidth(borderWidth);
1898 }
1899 
CheckLocalizedEdgeColors(const TextDirection & direction)1900 void LayoutProperty::CheckLocalizedEdgeColors(const TextDirection& direction)
1901 {
1902     auto host = GetHost();
1903     CHECK_NULL_VOID(host);
1904     const auto& target = host->GetRenderContext();
1905     CHECK_NULL_VOID(target);
1906     BorderColorProperty borderColors;
1907     BorderColorProperty colorProperty = target->GetBorderColorValue(BorderColorProperty {});
1908     if (!colorProperty.startColor.has_value() && !colorProperty.endColor.has_value()) {
1909         return;
1910     }
1911     if (colorProperty.startColor.has_value()) {
1912         borderColors.startColor = colorProperty.startColor;
1913         if (direction == TextDirection::RTL) {
1914             borderColors.rightColor = colorProperty.startColor;
1915         } else {
1916             borderColors.leftColor = colorProperty.startColor;
1917         }
1918     }
1919     if (colorProperty.endColor.has_value()) {
1920         borderColors.endColor = colorProperty.endColor;
1921         if (direction == TextDirection::RTL) {
1922             borderColors.leftColor = colorProperty.endColor;
1923         } else {
1924             borderColors.rightColor = colorProperty.endColor;
1925         }
1926     }
1927     if (colorProperty.topColor.has_value()) {
1928         borderColors.topColor = colorProperty.topColor;
1929     }
1930     if (colorProperty.bottomColor.has_value()) {
1931         borderColors.bottomColor = colorProperty.bottomColor;
1932     }
1933     borderColors.multiValued = true;
1934     target->UpdateBorderColor(borderColors);
1935 }
1936 
CheckLocalizedBorderImageSlice(const TextDirection & direction)1937 void LayoutProperty::CheckLocalizedBorderImageSlice(const TextDirection& direction)
1938 {
1939     auto host = GetHost();
1940     CHECK_NULL_VOID(host);
1941     const auto& target = host->GetRenderContext();
1942     CHECK_NULL_VOID(target);
1943     auto borderImage = target->GetBorderImage();
1944     CHECK_NULL_VOID(borderImage);
1945     auto borderImageProperty = borderImage.value();
1946     CHECK_NULL_VOID(borderImageProperty);
1947     auto isGreaterThanFourteen =
1948         AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN);
1949     if (isGreaterThanFourteen) {
1950         if (!borderImageProperty->borderImageStart_->GetBorderImageSlice().IsValid() &&
1951             !borderImageProperty->borderImageEnd_->GetBorderImageSlice().IsValid()) {
1952             return;
1953         }
1954     } else {
1955         if (!borderImageProperty->borderImageStart_.has_value() && !borderImageProperty->borderImageEnd_.has_value()) {
1956             return;
1957         }
1958     }
1959     Dimension leftSlice;
1960     Dimension rightSlice;
1961     Dimension startSlice;
1962     Dimension endSlice;
1963     if (isGreaterThanFourteen ? borderImageProperty->borderImageStart_->GetBorderImageSlice().IsValid()
1964                             : borderImageProperty->borderImageStart_.has_value()) {
1965         startSlice = borderImageProperty->borderImageStart_->GetBorderImageSlice();
1966         borderImageProperty->SetEdgeSlice(BorderImageDirection::START, startSlice);
1967         if (direction == TextDirection::RTL) {
1968             rightSlice = borderImageProperty->borderImageStart_->GetBorderImageSlice();
1969         } else {
1970             leftSlice = borderImageProperty->borderImageStart_->GetBorderImageSlice();
1971         }
1972     }
1973     if (isGreaterThanFourteen ? borderImageProperty->borderImageEnd_->GetBorderImageSlice().IsValid()
1974                             : borderImageProperty->borderImageEnd_.has_value()) {
1975         endSlice = borderImageProperty->borderImageEnd_->GetBorderImageSlice();
1976         borderImageProperty->SetEdgeSlice(BorderImageDirection::END, endSlice);
1977         if (direction == TextDirection::RTL) {
1978             leftSlice = borderImageProperty->borderImageEnd_->GetBorderImageSlice();
1979         } else {
1980             rightSlice = borderImageProperty->borderImageEnd_->GetBorderImageSlice();
1981         }
1982     }
1983     borderImageProperty->SetEdgeSlice(BorderImageDirection::LEFT, leftSlice);
1984     borderImageProperty->SetEdgeSlice(BorderImageDirection::RIGHT, rightSlice);
1985     target->UpdateBorderImage(borderImageProperty);
1986 }
1987 
CheckLocalizedBorderImageWidth(const TextDirection & direction)1988 void LayoutProperty::CheckLocalizedBorderImageWidth(const TextDirection& direction)
1989 {
1990     auto host = GetHost();
1991     CHECK_NULL_VOID(host);
1992     const auto& target = host->GetRenderContext();
1993     CHECK_NULL_VOID(target);
1994     auto borderImage = target->GetBorderImage();
1995     CHECK_NULL_VOID(borderImage);
1996     auto borderImageProperty = borderImage.value();
1997     CHECK_NULL_VOID(borderImageProperty);
1998     auto isGreaterThanFourteen =
1999         AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN);
2000     if (isGreaterThanFourteen) {
2001         if (!borderImageProperty->borderImageStart_->GetBorderImageWidth().IsValid() &&
2002             !borderImageProperty->borderImageEnd_->GetBorderImageWidth().IsValid()) {
2003             return;
2004         }
2005     } else {
2006         if (!borderImageProperty->borderImageStart_.has_value() && !borderImageProperty->borderImageEnd_.has_value()) {
2007             return;
2008         }
2009     }
2010     Dimension leftWidth;
2011     Dimension rightWidth;
2012     Dimension startWidth;
2013     Dimension endWidth;
2014     if (isGreaterThanFourteen ? borderImageProperty->borderImageStart_->GetBorderImageWidth().IsValid()
2015                               : borderImageProperty->borderImageStart_.has_value()) {
2016         startWidth = borderImageProperty->borderImageStart_->GetBorderImageWidth();
2017         borderImageProperty->SetEdgeWidth(BorderImageDirection::START, startWidth);
2018         if (direction == TextDirection::RTL) {
2019             rightWidth = borderImageProperty->borderImageStart_->GetBorderImageWidth();
2020         } else {
2021             leftWidth = borderImageProperty->borderImageStart_->GetBorderImageWidth();
2022         }
2023     }
2024     if (isGreaterThanFourteen ? borderImageProperty->borderImageEnd_->GetBorderImageWidth().IsValid()
2025                               : borderImageProperty->borderImageEnd_.has_value()) {
2026         endWidth = borderImageProperty->borderImageEnd_->GetBorderImageWidth();
2027         borderImageProperty->SetEdgeWidth(BorderImageDirection::END, endWidth);
2028         if (direction == TextDirection::RTL) {
2029             leftWidth = borderImageProperty->borderImageEnd_->GetBorderImageWidth();
2030         } else {
2031             rightWidth = borderImageProperty->borderImageEnd_->GetBorderImageWidth();
2032         }
2033     }
2034     borderImageProperty->SetEdgeWidth(BorderImageDirection::LEFT, leftWidth);
2035     borderImageProperty->SetEdgeWidth(BorderImageDirection::RIGHT, rightWidth);
2036     target->UpdateBorderImage(borderImageProperty);
2037 }
2038 
CheckLocalizedBorderImageOutset(const TextDirection & direction)2039 void LayoutProperty::CheckLocalizedBorderImageOutset(const TextDirection& direction)
2040 {
2041     auto host = GetHost();
2042     CHECK_NULL_VOID(host);
2043     const auto& target = host->GetRenderContext();
2044     CHECK_NULL_VOID(target);
2045     auto borderImage = target->GetBorderImage();
2046     CHECK_NULL_VOID(borderImage);
2047     auto borderImageProperty = borderImage.value();
2048     CHECK_NULL_VOID(borderImageProperty);
2049     auto isGreaterThanFourteen =
2050         AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN);
2051     if (isGreaterThanFourteen) {
2052         if (!borderImageProperty->borderImageStart_->GetBorderImageOutset().IsValid() &&
2053             !borderImageProperty->borderImageEnd_->GetBorderImageOutset().IsValid()) {
2054             return;
2055         }
2056     } else {
2057         if (!borderImageProperty->borderImageStart_.has_value() && !borderImageProperty->borderImageEnd_.has_value()) {
2058             return;
2059         }
2060     }
2061 
2062     Dimension leftOutset;
2063     Dimension rightOutset;
2064     Dimension startOutset;
2065     Dimension endOutset;
2066     if (isGreaterThanFourteen ? borderImageProperty->borderImageStart_->GetBorderImageOutset().IsValid()
2067                               : borderImageProperty->borderImageStart_.has_value()) {
2068         startOutset = borderImageProperty->borderImageStart_->GetBorderImageOutset();
2069         borderImageProperty->SetEdgeOutset(BorderImageDirection::START, startOutset);
2070         if (direction == TextDirection::RTL) {
2071             rightOutset = borderImageProperty->borderImageStart_->GetBorderImageOutset();
2072         } else {
2073             leftOutset = borderImageProperty->borderImageStart_->GetBorderImageOutset();
2074         }
2075     }
2076     if (isGreaterThanFourteen ? borderImageProperty->borderImageEnd_->GetBorderImageOutset().IsValid()
2077                               : borderImageProperty->borderImageEnd_.has_value()) {
2078         endOutset = borderImageProperty->borderImageEnd_->GetBorderImageOutset();
2079         borderImageProperty->SetEdgeOutset(BorderImageDirection::END, endOutset);
2080         if (direction == TextDirection::RTL) {
2081             leftOutset = borderImageProperty->borderImageEnd_->GetBorderImageOutset();
2082         } else {
2083             rightOutset = borderImageProperty->borderImageEnd_->GetBorderImageOutset();
2084         }
2085     }
2086     borderImageProperty->SetEdgeOutset(BorderImageDirection::LEFT, leftOutset);
2087     borderImageProperty->SetEdgeOutset(BorderImageDirection::RIGHT, rightOutset);
2088     target->UpdateBorderImage(borderImageProperty);
2089 }
2090 
GetGeometryTransition() const2091 RefPtr<GeometryTransition> LayoutProperty::GetGeometryTransition() const
2092 {
2093     return geometryTransition_.Upgrade();
2094 }
2095 } // namespace OHOS::Ace::NG
2096