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