• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/layout/layout_property.h"
17 
18 #include <optional>
19 
20 #include "base/geometry/ng/size_t.h"
21 #include "base/utils/utils.h"
22 #include "core/components/common/layout/constants.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/base/inspector_filter.h"
25 #include "core/components_ng/base/ui_node.h"
26 #include "core/components_ng/property/calc_length.h"
27 #include "core/components_ng/property/layout_constraint.h"
28 #include "core/components_ng/property/measure_utils.h"
29 #include "core/components_ng/property/safe_area_insets.h"
30 #include "core/components_v2/inspector/inspector_constants.h"
31 #include "core/pipeline_ng/pipeline_context.h"
32 
33 namespace OHOS::Ace::NG {
34 namespace {
VisibleTypeToString(VisibleType type)35 std::string VisibleTypeToString(VisibleType type)
36 {
37     static const LinearEnumMapNode<VisibleType, std::string> visibilityMap[] = {
38         { VisibleType::VISIBLE, "Visibility.Visible" },
39         { VisibleType::INVISIBLE, "Visibility.Hidden" },
40         { VisibleType::GONE, "Visibility.None" },
41     };
42     auto idx = BinarySearchFindIndex(visibilityMap, ArraySize(visibilityMap), type);
43     if (idx >= 0) {
44         return visibilityMap[idx].value;
45     }
46     return "Visibility.Visible";
47 }
48 
StringToVisibleType(const std::string & str)49 VisibleType StringToVisibleType(const std::string& str)
50 {
51     static const std::unordered_map<std::string, VisibleType> uMap {
52         { "Visibility.Visible", VisibleType::VISIBLE },
53         { "Visibility.Hidden", VisibleType::INVISIBLE },
54         { "Visibility.None", VisibleType::GONE },
55     };
56 
57     auto iter = uMap.find(str);
58     if (iter != uMap.end()) {
59         return iter->second;
60     }
61     return VisibleType::VISIBLE;
62 }
63 
TextDirectionToString(TextDirection type)64 std::string TextDirectionToString(TextDirection type)
65 {
66     static const LinearEnumMapNode<TextDirection, std::string> toStringMap[] = {
67         { TextDirection::LTR, "Direction.Ltr" },
68         { TextDirection::RTL, "Direction.Rtl" },
69         { TextDirection::INHERIT, "Direction.Inherit" },
70         { TextDirection::AUTO, "Direction.Auto" },
71     };
72     auto idx = BinarySearchFindIndex(toStringMap, ArraySize(toStringMap), type);
73     if (idx >= 0) {
74         return toStringMap[idx].value;
75     }
76     return "Direction.Ltr";
77 }
78 
StringToTextDirection(const std::string & str)79 TextDirection StringToTextDirection(const std::string& str)
80 {
81     static const std::unordered_map<std::string, TextDirection> uMap {
82         { "Direction.Ltr", TextDirection::LTR },
83         { "Direction.Rtl", TextDirection::RTL },
84         { "Direction.Inherit", TextDirection::INHERIT },
85         { "Direction.Auto", TextDirection::AUTO },
86     };
87 
88     auto iter = uMap.find(str);
89     if (iter != uMap.end()) {
90         return iter->second;
91     }
92     return TextDirection::LTR;
93 }
94 } // namespace
95 
Reset()96 void LayoutProperty::Reset()
97 {
98     layoutConstraint_.reset();
99     calcLayoutConstraint_.reset();
100     padding_.reset();
101     margin_.reset();
102     borderWidth_.reset();
103     outerBorderWidth_.reset();
104     magicItemProperty_.Reset();
105     positionProperty_.reset();
106     measureType_.reset();
107     layoutDirection_.reset();
108     propVisibility_.reset();
109     propIsBindOverlay_.reset();
110     CleanDirty();
111 }
112 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const113 void LayoutProperty::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
114 {
115     ACE_PROPERTY_TO_JSON_VALUE(calcLayoutConstraint_, MeasureProperty);
116     ACE_PROPERTY_TO_JSON_VALUE(positionProperty_, PositionProperty);
117     magicItemProperty_.ToJsonValue(json, filter);
118     ACE_PROPERTY_TO_JSON_VALUE(flexItemProperty_, FlexItemProperty);
119     ACE_PROPERTY_TO_JSON_VALUE(gridProperty_, GridProperty);
120     /* no fixed attr below, just return */
121     if (filter.IsFastFilter()) {
122         return;
123     }
124 
125     PaddingToJsonValue(json, filter);
126     MarginToJsonValue(json, filter);
127 
128     json->PutExtAttr("visibility",
129         VisibleTypeToString(propVisibility_.value_or(VisibleType::VISIBLE)).c_str(), filter);
130     json->PutExtAttr("direction", TextDirectionToString(GetLayoutDirection()).c_str(), filter);
131     json->PutExtAttr("pixelRound", PixelRoundToJsonValue().c_str(), filter);
132 }
133 
PaddingToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const134 void LayoutProperty::PaddingToJsonValue(std::unique_ptr<JsonValue>& json,
135     const InspectorFilter& filter) const
136 {
137     if (padding_) {
138         if (!padding_->top.has_value() || !padding_->right.has_value()
139             || !padding_->left.has_value() || !padding_->bottom.has_value()) {
140             auto paddingJsonValue = JsonUtil::Create(true);
141             paddingJsonValue->Put("top", padding_->top.has_value()
142                 ? padding_->top.value().ToString().c_str() : "0.00vp");
143             paddingJsonValue->Put("right", padding_->right.has_value()
144                 ? padding_->right.value().ToString().c_str() : "0.00vp");
145             paddingJsonValue->Put("bottom", padding_->bottom.has_value()
146                 ? padding_->bottom.value().ToString().c_str() : "0.00vp");
147             paddingJsonValue->Put("left", padding_->left.has_value()
148                 ? padding_->left.value().ToString().c_str() : "0.00vp");
149             json->PutExtAttr("padding", paddingJsonValue->ToString().c_str(), filter);
150         } else {
151             json->PutExtAttr("padding", padding_->ToJsonString().c_str(), filter);
152         }
153     } else {
154         json->PutExtAttr("padding", "0.00vp", filter);
155     }
156 }
157 
MarginToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const158 void LayoutProperty::MarginToJsonValue(std::unique_ptr<JsonValue>& json,
159     const InspectorFilter& filter) const
160 {
161     if (margin_) {
162         if (!margin_->top.has_value() || !margin_->right.has_value()
163             || !margin_->left.has_value() || !margin_->bottom.has_value()) {
164             auto marginJsonValue = JsonUtil::Create(true);
165             marginJsonValue->Put("top", margin_->top.has_value()
166                 ? margin_->top.value().ToString().c_str() : "0.00vp");
167             marginJsonValue->Put("right", margin_->right.has_value()
168                 ? margin_->right.value().ToString().c_str() : "0.00vp");
169             marginJsonValue->Put("bottom", margin_->bottom.has_value()
170                 ? margin_->bottom.value().ToString().c_str() : "0.00vp");
171             marginJsonValue->Put("left", margin_->left.has_value()
172                 ? margin_->left.value().ToString().c_str() : "0.00vp");
173             json->PutExtAttr("margin", marginJsonValue->ToString().c_str(), filter);
174         } else {
175             json->PutExtAttr("margin", margin_->ToJsonString().c_str(), filter);
176         }
177     } else {
178         json->PutExtAttr("margin", "0.00vp", filter);
179     }
180 }
181 
FromJson(const std::unique_ptr<JsonValue> & json)182 void LayoutProperty::FromJson(const std::unique_ptr<JsonValue>& json)
183 {
184     UpdateCalcLayoutProperty(MeasureProperty::FromJson(json));
185     UpdateLayoutWeight(json->GetDouble("layoutWeight"));
186     UpdateAlignment(Alignment::GetAlignment(TextDirection::LTR, json->GetString("align")));
187     auto padding = json->GetString("padding");
188     if (padding != "0.0") {
189         UpdatePadding(PaddingProperty::FromJsonString(padding));
190     }
191     auto margin = json->GetString("margin");
192     if (margin != "0.0") {
193         UpdateMargin(MarginProperty::FromJsonString(margin));
194     }
195     UpdateVisibility(StringToVisibleType(json->GetString("visibility")));
196     UpdateLayoutDirection(StringToTextDirection(json->GetString("direction")));
197 }
198 
PixelRoundToJsonValue() const199 const std::string LayoutProperty::PixelRoundToJsonValue() const
200 {
201     auto res = JsonUtil::Create(true);
202     if (pixelRoundFlag_ & static_cast<uint8_t>(PixelRoundPolicy::FORCE_CEIL_START)) {
203         res->Put("start", "PixelRoundCalcPolicy.FORCE_CEIL");
204     } else if (pixelRoundFlag_ & static_cast<uint8_t>(PixelRoundPolicy::FORCE_FLOOR_START)) {
205         res->Put("start", "PixelRoundCalcPolicy.FORCE_FLOOR");
206     } else {
207         res->Put("start", "PixelRoundCalcPolicy.NO_FORCE_ROUND");
208     }
209     if (pixelRoundFlag_ & static_cast<uint8_t>(PixelRoundPolicy::FORCE_CEIL_TOP)) {
210         res->Put("top", "PixelRoundCalcPolicy.FORCE_CEIL");
211     } else if (pixelRoundFlag_ & static_cast<uint8_t>(PixelRoundPolicy::FORCE_FLOOR_TOP)) {
212         res->Put("top", "PixelRoundCalcPolicy.FORCE_FLOOR");
213     } else {
214         res->Put("top", "PixelRoundCalcPolicy.NO_FORCE_ROUND");
215     }
216     if (pixelRoundFlag_ & static_cast<uint8_t>(PixelRoundPolicy::FORCE_CEIL_END)) {
217         res->Put("end", "PixelRoundCalcPolicy.FORCE_CEIL");
218     } else if (pixelRoundFlag_ & static_cast<uint8_t>(PixelRoundPolicy::FORCE_FLOOR_END)) {
219         res->Put("end", "PixelRoundCalcPolicy.FORCE_FLOOR");
220     } else {
221         res->Put("end", "PixelRoundCalcPolicy.NO_FORCE_ROUND");
222     }
223     if (pixelRoundFlag_ & static_cast<uint8_t>(PixelRoundPolicy::FORCE_CEIL_BOTTOM)) {
224         res->Put("bottom", "PixelRoundCalcPolicy.FORCE_CEIL");
225     } else if (pixelRoundFlag_ & static_cast<uint8_t>(PixelRoundPolicy::FORCE_FLOOR_BOTTOM)) {
226         res->Put("bottom", "PixelRoundCalcPolicy.FORCE_FLOOR");
227     } else {
228         res->Put("bottom", "PixelRoundCalcPolicy.NO_FORCE_ROUND");
229     }
230     return res->ToString();
231 }
232 
Clone() const233 RefPtr<LayoutProperty> LayoutProperty::Clone() const
234 {
235     auto layoutProperty = MakeRefPtr<LayoutProperty>();
236     Clone(layoutProperty);
237     return layoutProperty;
238 }
239 
Clone(RefPtr<LayoutProperty> layoutProperty) const240 void LayoutProperty::Clone(RefPtr<LayoutProperty> layoutProperty) const
241 {
242     layoutProperty->UpdateLayoutProperty(this);
243 }
244 
UpdateLayoutProperty(const LayoutProperty * layoutProperty)245 void LayoutProperty::UpdateLayoutProperty(const LayoutProperty* layoutProperty)
246 {
247     CHECK_NULL_VOID(layoutProperty);
248     layoutConstraint_ = layoutProperty->layoutConstraint_;
249     if (layoutProperty->gridProperty_) {
250         gridProperty_ = std::make_unique<GridProperty>(*layoutProperty->gridProperty_);
251     }
252     if (layoutProperty->calcLayoutConstraint_) {
253         calcLayoutConstraint_ = std::make_unique<MeasureProperty>(*layoutProperty->calcLayoutConstraint_);
254     }
255     if (layoutProperty->padding_) {
256         padding_ = std::make_unique<PaddingProperty>(*layoutProperty->padding_);
257     }
258     if (layoutProperty->margin_) {
259         margin_ = std::make_unique<PaddingProperty>(*layoutProperty->margin_);
260     }
261     if (layoutProperty->borderWidth_) {
262         borderWidth_ = std::make_unique<BorderWidthProperty>(*layoutProperty->borderWidth_);
263     }
264     magicItemProperty_ = layoutProperty->magicItemProperty_;
265     if (layoutProperty->positionProperty_) {
266         positionProperty_ = std::make_unique<PositionProperty>(*layoutProperty->positionProperty_);
267     }
268     if (layoutProperty->flexItemProperty_) {
269         flexItemProperty_ = std::make_unique<FlexItemProperty>(*layoutProperty->flexItemProperty_);
270     }
271     if (layoutProperty->safeAreaInsets_) {
272         safeAreaInsets_ = std::make_unique<SafeAreaInsets>(*layoutProperty->safeAreaInsets_);
273     }
274     if (layoutProperty->safeAreaExpandOpts_) {
275         safeAreaExpandOpts_ = std::make_unique<SafeAreaExpandOpts>(*layoutProperty->safeAreaExpandOpts_);
276     }
277     geometryTransition_ = layoutProperty->geometryTransition_;
278     propVisibility_ = layoutProperty->GetVisibility();
279     measureType_ = layoutProperty->measureType_;
280     layoutDirection_ = layoutProperty->layoutDirection_;
281     propertyChangeFlag_ = layoutProperty->propertyChangeFlag_;
282     propIsBindOverlay_ = layoutProperty->propIsBindOverlay_;
283     isOverlayNode_ = layoutProperty->isOverlayNode_;
284     overlayOffsetX_ = layoutProperty->overlayOffsetX_;
285     overlayOffsetY_ = layoutProperty->overlayOffsetY_;
286 }
287 
UpdateCalcLayoutProperty(const MeasureProperty & constraint)288 void LayoutProperty::UpdateCalcLayoutProperty(const MeasureProperty& constraint)
289 {
290     if (!calcLayoutConstraint_) {
291         calcLayoutConstraint_ = std::make_unique<MeasureProperty>(constraint);
292         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
293         return;
294     }
295     if (*calcLayoutConstraint_ == constraint) {
296         return;
297     }
298     calcLayoutConstraint_->selfIdealSize = constraint.selfIdealSize;
299     calcLayoutConstraint_->maxSize = constraint.maxSize;
300     calcLayoutConstraint_->minSize = constraint.minSize;
301     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
302 }
303 
UpdateLayoutConstraint(const LayoutConstraintF & parentConstraint)304 void LayoutProperty::UpdateLayoutConstraint(const LayoutConstraintF& parentConstraint)
305 {
306     layoutConstraint_ = parentConstraint;
307     if (margin_) {
308         marginResult_.reset();
309         auto margin = CreateMargin();
310         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
311             MinusPaddingToNonNegativeSize(margin, layoutConstraint_->maxSize);
312             MinusPaddingToNonNegativeSize(margin, layoutConstraint_->minSize);
313             MinusPaddingToNonNegativeSize(margin, layoutConstraint_->percentReference);
314         } else {
315             MinusPaddingToSize(margin, layoutConstraint_->maxSize);
316             MinusPaddingToSize(margin, layoutConstraint_->minSize);
317             MinusPaddingToSize(margin, layoutConstraint_->percentReference);
318         }
319         // already has non negative protection
320         MinusPaddingToSize(margin, layoutConstraint_->selfIdealSize);
321         MinusPaddingToSize(margin, layoutConstraint_->parentIdealSize);
322     }
323     auto originMax = layoutConstraint_->maxSize;
324     if (calcLayoutConstraint_) {
325         if (calcLayoutConstraint_->maxSize.has_value()) {
326             layoutConstraint_->UpdateMaxSizeWithCheck(ConvertToSize(calcLayoutConstraint_->maxSize.value(),
327                 parentConstraint.scaleProperty, parentConstraint.percentReference));
328         }
329         if (calcLayoutConstraint_->minSize.has_value()) {
330             layoutConstraint_->UpdateMinSizeWithCheck(ConvertToSize(calcLayoutConstraint_->minSize.value(),
331                 parentConstraint.scaleProperty, parentConstraint.percentReference));
332         }
333         if (calcLayoutConstraint_->selfIdealSize.has_value()) {
334             layoutConstraint_->UpdateIllegalSelfIdealSizeWithCheck(
335                 ConvertToOptionalSize(calcLayoutConstraint_->selfIdealSize.value(), parentConstraint.scaleProperty,
336                     parentConstraint.percentReference));
337         }
338     }
339 
340     CheckSelfIdealSize(parentConstraint, originMax);
341     CheckBorderAndPadding();
342     CheckAspectRatio();
343 }
344 
UpdateLayoutConstraintWithLayoutRect()345 void LayoutProperty::UpdateLayoutConstraintWithLayoutRect()
346 {
347     CHECK_NULL_VOID(layoutRect_);
348     auto size = layoutRect_.value().GetSize();
349     layoutConstraint_ = {
350         .scaleProperty = ScaleProperty::CreateScaleProperty(),
351         .minSize = size,
352         .maxSize = size,
353         .percentReference = size,
354         .selfIdealSize = OptionalSizeF(size),
355     };
356 }
357 
CheckBorderAndPadding()358 void LayoutProperty::CheckBorderAndPadding()
359 {
360     auto selfWidth = layoutConstraint_->selfIdealSize.Width();
361     auto selfHeight = layoutConstraint_->selfIdealSize.Height();
362     if (!selfWidth && !selfHeight) {
363         return;
364     }
365     auto selfWidthFloat = selfWidth.value_or(Infinity<float>());
366     auto selfHeightFloat = selfHeight.value_or(Infinity<float>());
367     auto paddingWithBorder = CreatePaddingAndBorder();
368     auto deflateWidthF = paddingWithBorder.Width();
369     auto deflateHeightF = paddingWithBorder.Height();
370     if (LessOrEqual(deflateWidthF, selfWidthFloat) && LessOrEqual(deflateHeightF, selfHeightFloat)) {
371         return;
372     }
373     if (GreatNotEqual(deflateWidthF, selfWidthFloat)) {
374         layoutConstraint_->selfIdealSize.SetWidth(deflateWidthF);
375     }
376     if (GreatNotEqual(deflateHeightF, selfHeightFloat)) {
377         layoutConstraint_->selfIdealSize.SetHeight(deflateHeightF);
378     }
379 }
380 
CheckAspectRatio()381 void LayoutProperty::CheckAspectRatio()
382 {
383     if (!magicItemProperty_.HasAspectRatio()) {
384         return;
385     }
386     auto aspectRatio = magicItemProperty_.GetAspectRatioValue();
387     // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and aspectRatio are
388     // all set, the height is not used.
389     auto maxWidth = layoutConstraint_->maxSize.Width();
390     auto maxHeight = layoutConstraint_->maxSize.Height();
391     if (maxHeight > maxWidth / aspectRatio) {
392         maxHeight = maxWidth / aspectRatio;
393     }
394     layoutConstraint_->maxSize.SetWidth(maxWidth);
395     layoutConstraint_->maxSize.SetHeight(maxHeight);
396     std::optional<float> selfWidth;
397     std::optional<float> selfHeight;
398     if (layoutConstraint_->selfIdealSize.Width()) {
399         selfWidth = layoutConstraint_->selfIdealSize.Width().value();
400         selfHeight = selfWidth.value() / aspectRatio;
401         if (selfHeight > maxHeight) {
402             selfHeight = maxHeight;
403             selfWidth = selfHeight.value() * aspectRatio;
404         }
405     } else if (layoutConstraint_->selfIdealSize.Height()) {
406         selfHeight = layoutConstraint_->selfIdealSize.Height().value();
407         selfWidth = selfHeight.value() * aspectRatio;
408         if (selfWidth > maxWidth) {
409             selfWidth = maxWidth;
410             selfHeight = selfWidth.value() / aspectRatio;
411         }
412     }
413 
414     if (selfHeight) {
415         layoutConstraint_->selfIdealSize.SetHeight(selfHeight);
416     }
417     if (selfWidth) {
418         layoutConstraint_->selfIdealSize.SetWidth(selfWidth);
419     }
420 }
421 
BuildGridProperty(const RefPtr<FrameNode> & host)422 void LayoutProperty::BuildGridProperty(const RefPtr<FrameNode>& host)
423 {
424     CHECK_NULL_VOID(gridProperty_);
425     auto parent = host->GetAncestorNodeOfFrame();
426     while (parent) {
427         if (parent->GetTag() == V2::GRIDCONTAINER_ETS_TAG) {
428             auto containerLayout = parent->GetLayoutProperty();
429             gridProperty_->UpdateContainer(containerLayout, host);
430             UpdateUserDefinedIdealSize(CalcSize(CalcLength(gridProperty_->GetWidth()), std::nullopt));
431             break;
432         }
433         parent = parent->GetAncestorNodeOfFrame();
434     }
435 }
436 
UpdateGridProperty(std::optional<int32_t> span,std::optional<int32_t> offset,GridSizeType type)437 void LayoutProperty::UpdateGridProperty(std::optional<int32_t> span, std::optional<int32_t> offset, GridSizeType type)
438 {
439     if (!gridProperty_) {
440         gridProperty_ = std::make_unique<GridProperty>();
441     }
442 
443     bool isSpanUpdated = (span.has_value() && gridProperty_->UpdateSpan(span.value(), type));
444     bool isOffsetUpdated = (offset.has_value() && gridProperty_->UpdateOffset(offset.value(), type));
445     if (isSpanUpdated || isOffsetUpdated) {
446         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
447     }
448 }
449 
UpdateGridOffset(const RefPtr<FrameNode> & host)450 bool LayoutProperty::UpdateGridOffset(const RefPtr<FrameNode>& host)
451 {
452     CHECK_NULL_RETURN(gridProperty_, false);
453     auto optOffset = gridProperty_->GetOffset();
454     if (optOffset == UNDEFINED_DIMENSION) {
455         return false;
456     }
457 
458     RefPtr<FrameNode> parent = host->GetAncestorNodeOfFrame();
459     if (!parent) {
460         return false;
461     }
462     auto parentOffset = parent->GetOffsetRelativeToWindow();
463     auto globalOffset = gridProperty_->GetContainerPosition();
464 
465     OffsetF offset(optOffset.ConvertToPx(), 0);
466     offset = offset + globalOffset - parentOffset;
467     const auto& geometryNode = host->GetGeometryNode();
468     if (offset.GetX() == geometryNode->GetFrameOffset().GetX()) {
469         return false;
470     }
471     offset.SetY(geometryNode->GetFrameOffset().GetY());
472     geometryNode->SetFrameOffset(offset);
473     auto renderContext = host->GetRenderContext();
474     if (renderContext) {
475         renderContext->SavePaintRect();
476     }
477     return true;
478 }
479 
CheckSelfIdealSize(const LayoutConstraintF & parentConstraint,const SizeF & originMax)480 void LayoutProperty::CheckSelfIdealSize(const LayoutConstraintF& parentConstraint, const SizeF& originMax)
481 {
482     if (measureType_ == MeasureType::MATCH_PARENT) {
483         layoutConstraint_->UpdateIllegalSelfIdealSizeWithCheck(layoutConstraint_->parentIdealSize);
484     }
485     if (!calcLayoutConstraint_) {
486         return;
487     }
488     SizeF minSize(-1.0f, -1.0f);
489     SizeF maxSize(-1.0f, -1.0f);
490     if (calcLayoutConstraint_->maxSize.has_value()) {
491         maxSize = ConvertToSize(calcLayoutConstraint_->maxSize.value(), layoutConstraint_->scaleProperty,
492             layoutConstraint_->percentReference);
493     }
494     if (calcLayoutConstraint_->minSize.has_value()) {
495         minSize = ConvertToSize(calcLayoutConstraint_->minSize.value(), layoutConstraint_->scaleProperty,
496             layoutConstraint_->percentReference);
497     }
498     if (calcLayoutConstraint_->maxSize.has_value()) {
499         layoutConstraint_->selfIdealSize.UpdateWidthWhenSmaller(maxSize);
500         if (GreatNotEqual(maxSize.Width(), 0.0f) && GreatOrEqual(maxSize.Width(), minSize.Width())) {
501             layoutConstraint_->UpdateMaxWidthWithCheck(maxSize);
502         } else if (GreatNotEqual(maxSize.Width(), 0.0f) && LessNotEqual(maxSize.Width(), minSize.Width())) {
503             layoutConstraint_->maxSize.SetWidth(minSize.Width());
504         } else {
505             layoutConstraint_->maxSize.SetWidth(originMax.Width());
506         }
507         layoutConstraint_->selfIdealSize.UpdateHeightWhenSmaller(maxSize);
508         if (GreatNotEqual(maxSize.Height(), 0.0f) && GreatOrEqual(maxSize.Height(), minSize.Height())) {
509             layoutConstraint_->UpdateMaxHeightWithCheck(maxSize);
510         } else if (GreatNotEqual(maxSize.Height(), 0.0f) && LessNotEqual(maxSize.Height(), minSize.Height())) {
511             layoutConstraint_->maxSize.SetHeight(minSize.Height());
512         } else {
513             layoutConstraint_->maxSize.SetHeight(originMax.Height());
514         }
515     }
516     layoutConstraint_->UpdateMinSizeWithCheck(minSize);
517     layoutConstraint_->selfIdealSize.UpdateSizeWhenLarger(minSize);
518 }
519 
CreateChildConstraint() const520 LayoutConstraintF LayoutProperty::CreateChildConstraint() const
521 {
522     CHECK_NULL_RETURN(layoutConstraint_, {});
523     auto layoutConstraint = contentConstraint_.value();
524     layoutConstraint.parentIdealSize = layoutConstraint.selfIdealSize;
525     // update max size when ideal size has value.
526     if (layoutConstraint.parentIdealSize.Width()) {
527         layoutConstraint.maxSize.SetWidth(layoutConstraint.parentIdealSize.Width().value());
528         layoutConstraint.percentReference.SetWidth(layoutConstraint.parentIdealSize.Width().value());
529     }
530     if (layoutConstraint.parentIdealSize.Height()) {
531         layoutConstraint.maxSize.SetHeight(layoutConstraint.parentIdealSize.Height().value());
532         layoutConstraint.percentReference.SetHeight(layoutConstraint.parentIdealSize.Height().value());
533     }
534     // for child constraint, reset current selfIdealSize and minSize.
535     layoutConstraint.selfIdealSize.Reset();
536     layoutConstraint.minSize.Reset();
537     return layoutConstraint;
538 }
539 
UpdateContentConstraint()540 void LayoutProperty::UpdateContentConstraint()
541 {
542     CHECK_NULL_VOID(layoutConstraint_);
543     contentConstraint_ = layoutConstraint_.value();
544     // update percent reference when parent has size.
545     if (contentConstraint_->parentIdealSize.Width()) {
546         contentConstraint_->percentReference.SetWidth(contentConstraint_->parentIdealSize.Width().value());
547     }
548     if (contentConstraint_->parentIdealSize.Height()) {
549         contentConstraint_->percentReference.SetHeight(contentConstraint_->parentIdealSize.Height().value());
550     }
551     if (padding_) {
552         auto paddingF = ConvertToPaddingPropertyF(
553             *padding_, contentConstraint_->scaleProperty, contentConstraint_->percentReference.Width());
554         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
555             contentConstraint_->MinusPaddingToNonNegativeSize(
556                 paddingF.left, paddingF.right, paddingF.top, paddingF.bottom);
557         } else {
558             contentConstraint_->MinusPadding(paddingF.left, paddingF.right, paddingF.top, paddingF.bottom);
559         }
560     }
561     if (borderWidth_) {
562         auto borderWidthF = ConvertToBorderWidthPropertyF(
563             *borderWidth_, contentConstraint_->scaleProperty, layoutConstraint_->percentReference.Width());
564         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
565             contentConstraint_->MinusPaddingToNonNegativeSize(
566                 borderWidthF.leftDimen, borderWidthF.rightDimen, borderWidthF.topDimen, borderWidthF.bottomDimen);
567         } else {
568             contentConstraint_->MinusPadding(
569                 borderWidthF.leftDimen, borderWidthF.rightDimen, borderWidthF.topDimen, borderWidthF.bottomDimen);
570         }
571     }
572 }
573 
CreatePaddingAndBorder()574 PaddingPropertyF LayoutProperty::CreatePaddingAndBorder()
575 {
576     if (layoutConstraint_.has_value()) {
577         auto padding = ConvertToPaddingPropertyF(
578             padding_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
579         auto borderWidth = ConvertToBorderWidthPropertyF(
580             borderWidth_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
581 
582         return PaddingPropertyF { padding.left.value_or(0) + borderWidth.leftDimen.value_or(0),
583             padding.right.value_or(0) + borderWidth.rightDimen.value_or(0),
584             padding.top.value_or(0) + borderWidth.topDimen.value_or(0),
585             padding.bottom.value_or(0) + borderWidth.bottomDimen.value_or(0) };
586     }
587     auto padding = ConvertToPaddingPropertyF(
588         padding_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
589     auto borderWidth = ConvertToBorderWidthPropertyF(
590         borderWidth_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
591 
592     return PaddingPropertyF { padding.left.value_or(0) + borderWidth.leftDimen.value_or(0),
593         padding.right.value_or(0) + borderWidth.rightDimen.value_or(0),
594         padding.top.value_or(0) + borderWidth.topDimen.value_or(0),
595         padding.bottom.value_or(0) + borderWidth.bottomDimen.value_or(0) };
596 }
597 
CreatePaddingAndBorderWithDefault(float paddingHorizontalDefault,float paddingVerticalDefault,float borderHorizontalDefault,float borderVerticalDefault)598 PaddingPropertyF LayoutProperty::CreatePaddingAndBorderWithDefault(float paddingHorizontalDefault,
599     float paddingVerticalDefault, float borderHorizontalDefault, float borderVerticalDefault)
600 {
601     if (layoutConstraint_.has_value()) {
602         auto padding = ConvertToPaddingPropertyF(
603             padding_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
604         auto borderWidth = ConvertToBorderWidthPropertyF(
605             borderWidth_, ScaleProperty::CreateScaleProperty(), layoutConstraint_->percentReference.Width());
606         return PaddingPropertyF { padding.left.value_or(paddingHorizontalDefault) +
607                                       borderWidth.leftDimen.value_or(borderHorizontalDefault),
608             padding.right.value_or(paddingHorizontalDefault) + borderWidth.rightDimen.value_or(borderHorizontalDefault),
609             padding.top.value_or(paddingVerticalDefault) + borderWidth.topDimen.value_or(borderVerticalDefault),
610             padding.bottom.value_or(paddingVerticalDefault) + borderWidth.bottomDimen.value_or(borderVerticalDefault) };
611     }
612     auto padding = ConvertToPaddingPropertyF(
613         padding_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
614     auto borderWidth = ConvertToBorderWidthPropertyF(
615         borderWidth_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
616 
617     return PaddingPropertyF { padding.left.value_or(paddingHorizontalDefault) +
618                                   borderWidth.leftDimen.value_or(borderHorizontalDefault),
619         padding.right.value_or(paddingHorizontalDefault) + borderWidth.rightDimen.value_or(borderHorizontalDefault),
620         padding.top.value_or(paddingVerticalDefault) + borderWidth.topDimen.value_or(borderVerticalDefault),
621         padding.bottom.value_or(paddingVerticalDefault) + borderWidth.bottomDimen.value_or(borderVerticalDefault) };
622 }
623 
CreatePaddingWithoutBorder(bool useRootConstraint,bool roundPixel)624 PaddingPropertyF LayoutProperty::CreatePaddingWithoutBorder(bool useRootConstraint, bool roundPixel)
625 {
626     if (layoutConstraint_.has_value()) {
627         return ConvertToPaddingPropertyF(
628             padding_, layoutConstraint_->scaleProperty, layoutConstraint_->percentReference.Width(), roundPixel);
629     }
630 
631     return ConvertToPaddingPropertyF(padding_, ScaleProperty::CreateScaleProperty(),
632         useRootConstraint ? PipelineContext::GetCurrentRootWidth() : 0.0f, roundPixel);
633 }
634 
CreateBorder()635 BorderWidthPropertyF LayoutProperty::CreateBorder()
636 {
637     // no pixel rounding
638     if (layoutConstraint_.has_value()) {
639         return ConvertToBorderWidthPropertyF(
640             borderWidth_, layoutConstraint_->scaleProperty, layoutConstraint_->percentReference.Width(), false);
641     }
642 
643     return ConvertToBorderWidthPropertyF(
644         borderWidth_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth(), false);
645 }
646 
CreateMargin()647 MarginPropertyF LayoutProperty::CreateMargin()
648 {
649     CHECK_NULL_RETURN(margin_, MarginPropertyF());
650     if (!marginResult_.has_value() && margin_) {
651         if (layoutConstraint_.has_value()) {
652             marginResult_ = ConvertToMarginPropertyF(
653                 margin_, layoutConstraint_->scaleProperty, layoutConstraint_->percentReference.Width());
654         } else {
655             // root node
656             marginResult_ = ConvertToMarginPropertyF(
657                 margin_, ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth());
658         }
659     }
660     return marginResult_.value_or(MarginPropertyF());
661 }
662 
CreateMarginWithoutCache()663 MarginPropertyF LayoutProperty::CreateMarginWithoutCache()
664 {
665     CHECK_NULL_RETURN(margin_, MarginPropertyF());
666     auto host = GetHost();
667     CHECK_NULL_RETURN(host, MarginPropertyF());
668     const auto& parentConstraint = host->GetGeometryNode()->GetParentLayoutConstraint();
669     // no pixel rounding
670     if (parentConstraint) {
671         return ConvertToMarginPropertyF(
672             margin_, parentConstraint->scaleProperty, parentConstraint->percentReference.Width(), false);
673     }
674     // the root width is not considered at present.
675     return ConvertToMarginPropertyF(margin_, ScaleProperty::CreateScaleProperty(), 0.0f, false);
676 }
677 
SetHost(const WeakPtr<FrameNode> & host)678 void LayoutProperty::SetHost(const WeakPtr<FrameNode>& host)
679 {
680     host_ = host;
681 }
682 
GetHost() const683 RefPtr<FrameNode> LayoutProperty::GetHost() const
684 {
685     return host_.Upgrade();
686 }
687 
OnVisibilityUpdate(VisibleType visible,bool allowTransition)688 void LayoutProperty::OnVisibilityUpdate(VisibleType visible, bool allowTransition)
689 {
690     auto host = GetHost();
691     CHECK_NULL_VOID(host);
692     // store the previous visibility value.
693     auto preVisibility = propVisibility_;
694 
695     // update visibility value.
696     propVisibility_ = visible;
697     host->NotifyVisibleChange(preVisibility.value_or(VisibleType::VISIBLE), visible);
698     if (allowTransition && preVisibility) {
699         if (preVisibility.value() == VisibleType::VISIBLE && visible != VisibleType::VISIBLE) {
700             host->GetRenderContext()->OnNodeDisappear(false);
701         } else if (preVisibility.value() != VisibleType::VISIBLE && visible == VisibleType::VISIBLE) {
702             host->GetRenderContext()->OnNodeAppear(false);
703         }
704     }
705 
706     auto parent = host->GetAncestorNodeOfFrame();
707     CHECK_NULL_VOID(parent);
708     // if visible is not changed to/from VisibleType::Gone, only need to update render tree.
709     if (preVisibility.value_or(VisibleType::VISIBLE) != VisibleType::GONE && visible != VisibleType::GONE) {
710         parent->MarkNeedSyncRenderTree();
711         parent->RebuildRenderContextTree();
712         return;
713     }
714     UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
715     parent->MarkNeedSyncRenderTree();
716     parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
717 }
718 
UpdateSafeAreaExpandOpts(const SafeAreaExpandOpts & opts)719 void LayoutProperty::UpdateSafeAreaExpandOpts(const SafeAreaExpandOpts& opts)
720 {
721     if (!safeAreaExpandOpts_) {
722         safeAreaExpandOpts_ = std::make_unique<SafeAreaExpandOpts>();
723     }
724     if (*safeAreaExpandOpts_ != opts) {
725         *safeAreaExpandOpts_ = opts;
726         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
727         safeAreaExpandOpts_->switchToNone = !opts.Expansive();
728     }
729 }
730 
UpdateSafeAreaInsets(const SafeAreaInsets & safeArea)731 void LayoutProperty::UpdateSafeAreaInsets(const SafeAreaInsets& safeArea)
732 {
733     if (!safeAreaInsets_) {
734         safeAreaInsets_ = std::make_unique<SafeAreaInsets>();
735     }
736     if (*safeAreaInsets_ != safeArea) {
737         *safeAreaInsets_ = safeArea;
738     }
739 }
740 
HasFixedWidth() const741 bool LayoutProperty::HasFixedWidth() const
742 {
743     CHECK_NULL_RETURN(calcLayoutConstraint_, false);
744     auto&& idealSize = calcLayoutConstraint_->selfIdealSize;
745     return (idealSize && idealSize->WidthFixed());
746 }
747 
HasFixedHeight() const748 bool LayoutProperty::HasFixedHeight() const
749 {
750     CHECK_NULL_RETURN(calcLayoutConstraint_, false);
751     auto&& idealSize = calcLayoutConstraint_->selfIdealSize;
752     return (idealSize && idealSize->HeightFixed());
753 }
754 
HasAspectRatio() const755 bool LayoutProperty::HasAspectRatio() const
756 {
757     return magicItemProperty_.HasAspectRatio();
758 }
759 
GetAspectRatio() const760 float LayoutProperty::GetAspectRatio() const
761 {
762     if (magicItemProperty_.HasAspectRatio()) {
763         return magicItemProperty_.GetAspectRatioValue();
764     }
765     return 0.0f;
766 }
767 
UpdateAspectRatio(float ratio)768 void LayoutProperty::UpdateAspectRatio(float ratio)
769 {
770     if (magicItemProperty_.UpdateAspectRatio(ratio)) {
771         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
772     }
773 }
774 
ResetAspectRatio()775 void LayoutProperty::ResetAspectRatio()
776 {
777     if (magicItemProperty_.HasAspectRatio()) {
778         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
779         magicItemProperty_.ResetAspectRatio();
780     }
781 }
782 
UpdateGeometryTransition(const std::string & id,bool followWithoutTransition,bool doRegisterSharedTransition)783 void LayoutProperty::UpdateGeometryTransition(const std::string& id,
784     bool followWithoutTransition, bool doRegisterSharedTransition)
785 {
786     auto host = GetHost();
787     CHECK_NULL_VOID(host);
788 
789     auto geometryTransitionOld = GetGeometryTransition();
790     auto geometryTransitionNew =
791         ElementRegister::GetInstance()->GetOrCreateGeometryTransition(id,
792             followWithoutTransition, doRegisterSharedTransition);
793     CHECK_NULL_VOID(geometryTransitionOld != geometryTransitionNew);
794     if (geometryTransitionOld) {
795         if (geometryTransitionOld->Update(host_, host_)) {
796             geometryTransitionOld->OnFollowWithoutTransition();
797         }
798         // unregister node from old geometry transition
799         geometryTransitionOld->Update(host_, nullptr);
800         // register node into new geometry transition
801         if (geometryTransitionNew && !geometryTransitionNew->Update(nullptr, host_)) {
802             TAG_LOGE(AceLogTag::ACE_GEOMETRY_TRANSITION, "redundant node%{public}d has same geoid: %{public}s",
803                 host->GetId(), id.c_str());
804         }
805     } else if (geometryTransitionNew) {
806         if (geometryTransitionNew->IsInAndOutValid()) {
807             TAG_LOGE(AceLogTag::ACE_GEOMETRY_TRANSITION, "redundant node%{public}d has same geoid: %{public}s",
808                 host->GetId(), id.c_str());
809         }
810         geometryTransitionNew->Build(host_, true);
811     }
812     geometryTransition_ = geometryTransitionNew;
813 
814     TAG_LOGD(AceLogTag::ACE_GEOMETRY_TRANSITION, "node: %{public}d update id, old id: %{public}s, new id: %{public}s",
815         host->GetId(), geometryTransitionOld ? geometryTransitionOld->GetId().c_str() : "empty",
816         geometryTransitionNew ? id.c_str() : "empty");
817     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
818 }
819 
ResetGeometryTransition()820 void LayoutProperty::ResetGeometryTransition()
821 {
822     if (!GetGeometryTransition()) {
823         return;
824     }
825     UpdateGeometryTransition("");
826 }
827 
UpdateLayoutDirection(TextDirection value)828 void LayoutProperty::UpdateLayoutDirection(TextDirection value)
829 {
830     if (layoutDirection_ == value) {
831         return;
832     }
833     layoutDirection_ = value;
834     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
835 }
836 
GetNonAutoLayoutDirection() const837 TextDirection LayoutProperty::GetNonAutoLayoutDirection() const
838 {
839     auto direction = layoutDirection_.value_or(TextDirection::AUTO);
840     return direction != TextDirection::AUTO
841                ? direction
842                : (AceApplicationInfo::GetInstance().IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR);
843 }
844 
UpdateLayoutWeight(float value)845 void LayoutProperty::UpdateLayoutWeight(float value)
846 {
847     if (magicItemProperty_.UpdateLayoutWeight(value)) {
848         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
849     }
850 }
851 
UpdateBorderWidth(const BorderWidthProperty & value)852 void LayoutProperty::UpdateBorderWidth(const BorderWidthProperty& value)
853 {
854     if (!borderWidth_) {
855         borderWidth_ = std::make_unique<BorderWidthProperty>();
856     }
857     if (borderWidth_->UpdateWithCheck(value)) {
858         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
859     }
860 }
861 
UpdateOuterBorderWidth(const BorderWidthProperty & value)862 void LayoutProperty::UpdateOuterBorderWidth(const BorderWidthProperty& value)
863 {
864     if (!outerBorderWidth_) {
865         outerBorderWidth_ = std::make_unique<BorderWidthProperty>();
866     }
867     if (outerBorderWidth_->UpdateWithCheck(value)) {
868         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
869     }
870 }
871 
UpdateAlignment(Alignment value)872 void LayoutProperty::UpdateAlignment(Alignment value)
873 {
874     if (!positionProperty_) {
875         positionProperty_ = std::make_unique<PositionProperty>();
876     }
877     if (positionProperty_->UpdateAlignment(value)) {
878         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT;
879     }
880 }
881 
UpdateMargin(const MarginProperty & value)882 void LayoutProperty::UpdateMargin(const MarginProperty& value)
883 {
884     if (!margin_) {
885         margin_ = std::make_unique<MarginProperty>();
886     }
887     if (margin_->UpdateWithCheck(value)) {
888         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
889     }
890 }
891 
UpdatePadding(const PaddingProperty & value)892 void LayoutProperty::UpdatePadding(const PaddingProperty& value)
893 {
894     if (!padding_) {
895         padding_ = std::make_unique<PaddingProperty>();
896     }
897     if (padding_->UpdateWithCheck(value)) {
898         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
899     }
900 }
901 
UpdateUserDefinedIdealSize(const CalcSize & value)902 void LayoutProperty::UpdateUserDefinedIdealSize(const CalcSize& value)
903 {
904     if (!calcLayoutConstraint_) {
905         calcLayoutConstraint_ = std::make_unique<MeasureProperty>();
906     }
907     if (calcLayoutConstraint_->UpdateSelfIdealSizeWithCheck(value)) {
908         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
909     }
910 }
911 
ClearUserDefinedIdealSize(bool clearWidth,bool clearHeight)912 void LayoutProperty::ClearUserDefinedIdealSize(bool clearWidth, bool clearHeight)
913 {
914     if (!calcLayoutConstraint_) {
915         return;
916     }
917     if (calcLayoutConstraint_->ClearSelfIdealSize(clearWidth, clearHeight)) {
918         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
919     }
920 }
921 
UpdateCalcMinSize(const CalcSize & value)922 void LayoutProperty::UpdateCalcMinSize(const CalcSize& value)
923 {
924     if (!calcLayoutConstraint_) {
925         calcLayoutConstraint_ = std::make_unique<MeasureProperty>();
926     }
927     if (calcLayoutConstraint_->UpdateMinSizeWithCheck(value)) {
928         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
929     }
930 }
931 
UpdateCalcMaxSize(const CalcSize & value)932 void LayoutProperty::UpdateCalcMaxSize(const CalcSize& value)
933 {
934     if (!calcLayoutConstraint_) {
935         calcLayoutConstraint_ = std::make_unique<MeasureProperty>();
936     }
937     if (calcLayoutConstraint_->UpdateMaxSizeWithCheck(value)) {
938         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
939     }
940 }
941 
UpdateMarginSelfIdealSize(const SizeF & value)942 void LayoutProperty::UpdateMarginSelfIdealSize(const SizeF& value)
943 {
944     if (!layoutConstraint_.has_value()) {
945         layoutConstraint_ = LayoutConstraintF();
946     }
947     if (layoutConstraint_->UpdateSelfMarginSizeWithCheck(OptionalSizeF(value))) {
948         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
949     }
950 }
951 
ResetCalcMinSize()952 void LayoutProperty::ResetCalcMinSize()
953 {
954     if (!calcLayoutConstraint_) {
955         return;
956     }
957     if (calcLayoutConstraint_->minSize.has_value()) {
958         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
959     }
960     calcLayoutConstraint_->minSize.reset();
961 }
962 
ResetCalcMaxSize()963 void LayoutProperty::ResetCalcMaxSize()
964 {
965     if (!calcLayoutConstraint_) {
966         return;
967     }
968     if (calcLayoutConstraint_->maxSize.has_value()) {
969         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
970     }
971     calcLayoutConstraint_->maxSize.reset();
972 }
973 
ResetCalcMinSize(bool resetWidth)974 void LayoutProperty::ResetCalcMinSize(bool resetWidth)
975 {
976     if (!calcLayoutConstraint_) {
977         return;
978     }
979     CHECK_NULL_VOID(calcLayoutConstraint_->minSize.has_value());
980     bool resetSizeHasValue = resetWidth ? calcLayoutConstraint_->minSize.value().Width().has_value()
981                                         : calcLayoutConstraint_->minSize.value().Height().has_value();
982     CHECK_NULL_VOID(resetSizeHasValue);
983     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
984     if (resetWidth) {
985         calcLayoutConstraint_->minSize.value().SetWidth(std::nullopt);
986     } else {
987         calcLayoutConstraint_->minSize.value().SetHeight(std::nullopt);
988     }
989 }
990 
ResetCalcMaxSize(bool resetWidth)991 void LayoutProperty::ResetCalcMaxSize(bool resetWidth)
992 {
993     if (!calcLayoutConstraint_) {
994         return;
995     }
996     CHECK_NULL_VOID(calcLayoutConstraint_->maxSize.has_value());
997     bool resetSizeHasValue = resetWidth ? calcLayoutConstraint_->maxSize.value().Width().has_value()
998                                         : calcLayoutConstraint_->maxSize.value().Height().has_value();
999     CHECK_NULL_VOID(resetSizeHasValue);
1000     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1001     if (resetWidth) {
1002         calcLayoutConstraint_->maxSize.value().SetWidth(std::nullopt);
1003     } else {
1004         calcLayoutConstraint_->maxSize.value().SetHeight(std::nullopt);
1005     }
1006 }
1007 
UpdateFlexGrow(float flexGrow)1008 void LayoutProperty::UpdateFlexGrow(float flexGrow)
1009 {
1010     if (!flexItemProperty_) {
1011         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1012     }
1013     if (flexItemProperty_->UpdateFlexGrow(flexGrow)) {
1014         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1015     }
1016 }
1017 
ResetFlexGrow()1018 void LayoutProperty::ResetFlexGrow()
1019 {
1020     if (!flexItemProperty_) {
1021         return;
1022     }
1023     if (flexItemProperty_->HasFlexGrow()) {
1024         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1025     }
1026     flexItemProperty_->ResetFlexGrow();
1027 }
1028 
UpdateFlexShrink(float flexShrink)1029 void LayoutProperty::UpdateFlexShrink(float flexShrink)
1030 {
1031     if (!flexItemProperty_) {
1032         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1033     }
1034     if (flexItemProperty_->UpdateFlexShrink(flexShrink)) {
1035         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1036     }
1037 }
1038 
ResetFlexShrink()1039 void LayoutProperty::ResetFlexShrink()
1040 {
1041     if (!flexItemProperty_) {
1042         return;
1043     }
1044     if (flexItemProperty_->HasFlexShrink()) {
1045         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1046     }
1047     flexItemProperty_->ResetFlexShrink();
1048 }
1049 
UpdateFlexBasis(const Dimension & flexBasis)1050 void LayoutProperty::UpdateFlexBasis(const Dimension& flexBasis)
1051 {
1052     if (!flexItemProperty_) {
1053         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1054     }
1055     if (flexItemProperty_->UpdateFlexBasis(flexBasis)) {
1056         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1057     }
1058 }
1059 
UpdateAlignSelf(const FlexAlign & flexAlign)1060 void LayoutProperty::UpdateAlignSelf(const FlexAlign& flexAlign)
1061 {
1062     if (!flexItemProperty_) {
1063         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1064     }
1065     if (flexItemProperty_->UpdateAlignSelf(flexAlign)) {
1066         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1067     }
1068 }
1069 
ResetAlignSelf()1070 void LayoutProperty::ResetAlignSelf()
1071 {
1072     if (!flexItemProperty_) {
1073         return;
1074     }
1075     if (flexItemProperty_->HasAlignSelf()) {
1076         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1077     }
1078     flexItemProperty_->ResetAlignSelf();
1079 }
1080 
UpdateAlignRules(const std::map<AlignDirection,AlignRule> & alignRules)1081 void LayoutProperty::UpdateAlignRules(const std::map<AlignDirection, AlignRule>& alignRules)
1082 {
1083     if (!flexItemProperty_) {
1084         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1085     }
1086     if (flexItemProperty_->UpdateAlignRules(alignRules)) {
1087         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1088     }
1089 }
1090 
UpdateChainStyle(const ChainInfo & chainInfo)1091 void LayoutProperty::UpdateChainStyle(const ChainInfo& chainInfo)
1092 {
1093     if (!flexItemProperty_) {
1094         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1095     }
1096     if (!chainInfo.direction.has_value()) {
1097         ChainInfo nullChainInfo;
1098         if (flexItemProperty_->UpdateHorizontalChainStyle(nullChainInfo)) {
1099             propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1100         }
1101         if (flexItemProperty_->UpdateVerticalChainStyle(nullChainInfo)) {
1102             propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1103         }
1104     }
1105     if (chainInfo.direction == LineDirection::HORIZONTAL) {
1106         if (flexItemProperty_->UpdateHorizontalChainStyle(chainInfo)) {
1107             propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1108         }
1109     } else {
1110         if (flexItemProperty_->UpdateVerticalChainStyle(chainInfo)) {
1111             propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1112         }
1113     }
1114 }
1115 
UpdateBias(const BiasPair & biasPair)1116 void LayoutProperty::UpdateBias(const BiasPair& biasPair)
1117 {
1118     if (!flexItemProperty_) {
1119         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1120     }
1121     if (flexItemProperty_->UpdateBias(biasPair)) {
1122         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1123     }
1124 }
1125 
UpdateDisplayIndex(int32_t displayIndex)1126 void LayoutProperty::UpdateDisplayIndex(int32_t displayIndex)
1127 {
1128     if (!flexItemProperty_) {
1129         flexItemProperty_ = std::make_unique<FlexItemProperty>();
1130     }
1131     if (flexItemProperty_->UpdateDisplayIndex(displayIndex)) {
1132         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_MEASURE;
1133         auto host = GetHost();
1134         CHECK_NULL_VOID(host);
1135         auto parent = host->GetAncestorNodeOfFrame();
1136         CHECK_NULL_VOID(parent);
1137         const auto& children = parent->GetChildren();
1138         CHECK_EQUAL_VOID(children.empty(), true);
1139         for (const auto& child : children) {
1140             auto childFrameNode = AceType::DynamicCast<NG::FrameNode>(child);
1141             CHECK_NULL_CONTINUE(childFrameNode);
1142             auto layoutProperty = childFrameNode->GetLayoutProperty();
1143             CHECK_NULL_CONTINUE(layoutProperty);
1144             layoutProperty->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF);
1145         }
1146     }
1147 }
1148 
CreateContentConstraint() const1149 LayoutConstraintF LayoutProperty::CreateContentConstraint() const
1150 {
1151     auto layoutConstraint = contentConstraint_.value_or(LayoutConstraintF());
1152     layoutConstraint.maxSize.UpdateSizeWhenSmaller(layoutConstraint.selfIdealSize.ConvertToSizeT());
1153     return layoutConstraint;
1154 }
1155 
UpdateLayoutConstraint(const RefPtr<LayoutProperty> & layoutProperty)1156 void LayoutProperty::UpdateLayoutConstraint(const RefPtr<LayoutProperty>& layoutProperty)
1157 {
1158     layoutConstraint_ = layoutProperty->layoutConstraint_;
1159     contentConstraint_ = layoutProperty->contentConstraint_;
1160     gridProperty_ =
1161         (layoutProperty->gridProperty_) ? std::make_unique<GridProperty>(*layoutProperty->gridProperty_) : nullptr;
1162 }
1163 
UpdateVisibility(const VisibleType & value,bool allowTransition)1164 void LayoutProperty::UpdateVisibility(const VisibleType& value, bool allowTransition)
1165 {
1166     if (propVisibility_.has_value()) {
1167         if (NearEqual(propVisibility_.value(), value)) {
1168             return;
1169         }
1170     }
1171     OnVisibilityUpdate(value, allowTransition);
1172 }
1173 
SetOverlayOffset(const std::optional<Dimension> & overlayOffsetX,const std::optional<Dimension> & overlayOffsetY)1174 void LayoutProperty::SetOverlayOffset(
1175     const std::optional<Dimension>& overlayOffsetX, const std::optional<Dimension>& overlayOffsetY)
1176 {
1177     bool xChanged = true;
1178     bool yChanged = false;
1179     if ((!overlayOffsetX.has_value() && overlayOffsetX_.Value() == 0) ||
1180         (overlayOffsetX.has_value() && overlayOffsetX.value() == overlayOffsetX_)) {
1181         xChanged = false;
1182     }
1183 
1184     if ((!overlayOffsetY.has_value() && overlayOffsetY_.Value() == 0) ||
1185         (overlayOffsetY.has_value() && overlayOffsetY.value() == overlayOffsetY_)) {
1186         yChanged = false;
1187     }
1188 
1189     if (!xChanged && !yChanged) {
1190         return;
1191     }
1192 
1193     if (overlayOffsetX.has_value()) {
1194         overlayOffsetX_ = overlayOffsetX.value();
1195     } else {
1196         overlayOffsetX_.Reset();
1197     }
1198 
1199     if (overlayOffsetY.has_value()) {
1200         overlayOffsetY_ = overlayOffsetY.value();
1201     } else {
1202         overlayOffsetY_.Reset();
1203     }
1204 
1205     propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1206 }
1207 
GetOverlayOffset(Dimension & overlayOffsetX,Dimension & overlayOffsetY)1208 void LayoutProperty::GetOverlayOffset(Dimension& overlayOffsetX, Dimension& overlayOffsetY)
1209 {
1210     overlayOffsetX = overlayOffsetX_;
1211     overlayOffsetY = overlayOffsetY_;
1212 }
1213 
UpdateAllGeometryTransition(const RefPtr<UINode> & parent)1214 void LayoutProperty::UpdateAllGeometryTransition(const RefPtr<UINode>& parent)
1215 {
1216     std::queue<RefPtr<UINode>> q;
1217     q.push(parent);
1218     while (!q.empty()) {
1219         auto node = q.front();
1220         q.pop();
1221         auto frameNode = AceType::DynamicCast<FrameNode>(node);
1222         if (frameNode) {
1223             auto layoutProperty = frameNode->GetLayoutProperty();
1224             if (layoutProperty && layoutProperty->GetGeometryTransition()) {
1225                 auto geometryTransitionId = layoutProperty->GetGeometryTransition()->GetId();
1226                 layoutProperty->UpdateGeometryTransition("");
1227                 layoutProperty->UpdateGeometryTransition(geometryTransitionId);
1228             }
1229         }
1230         const auto& children = node->GetChildren();
1231         for (const auto& child : children) {
1232             q.push(child);
1233         }
1234     }
1235 }
1236 
GetPercentSensitive()1237 std::pair<bool, bool> LayoutProperty::GetPercentSensitive()
1238 {
1239     if (!contentConstraint_.has_value()) {
1240         return { false, false };
1241     }
1242     std::pair<bool, bool> res = { false, false };
1243     const auto& constraint = contentConstraint_.value();
1244     if (GreaterOrEqualToInfinity(constraint.maxSize.Height())) {
1245         if (calcLayoutConstraint_ && calcLayoutConstraint_->PercentHeight()) {
1246             res.second = true;
1247         }
1248     }
1249     if (GreaterOrEqualToInfinity(constraint.maxSize.Width())) {
1250         if (calcLayoutConstraint_ && calcLayoutConstraint_->PercentWidth()) {
1251             res.first = true;
1252         }
1253     }
1254     return res;
1255 }
1256 
UpdatePercentSensitive(bool width,bool height)1257 std::pair<bool, bool> LayoutProperty::UpdatePercentSensitive(bool width, bool height)
1258 {
1259     if (!contentConstraint_.has_value()) {
1260         return { false, false };
1261     }
1262     const auto& constraint = contentConstraint_.value();
1263     if (GreaterOrEqualToInfinity(constraint.maxSize.Height())) {
1264         heightPercentSensitive_ = heightPercentSensitive_ || height;
1265     }
1266     if (GreaterOrEqualToInfinity(constraint.maxSize.Width())) {
1267         widthPercentSensitive_ = heightPercentSensitive_ || width;
1268     }
1269     return { widthPercentSensitive_, heightPercentSensitive_ };
1270 }
1271 
ConstraintEqual(const std::optional<LayoutConstraintF> & preLayoutConstraint,const std::optional<LayoutConstraintF> & preContentConstraint)1272 bool LayoutProperty::ConstraintEqual(const std::optional<LayoutConstraintF>& preLayoutConstraint,
1273     const std::optional<LayoutConstraintF>& preContentConstraint)
1274 {
1275     if (!preLayoutConstraint || !layoutConstraint_) {
1276         return false;
1277     }
1278     if (!preContentConstraint || !contentConstraint_) {
1279         return false;
1280     }
1281     bool isNeedPercent = false;
1282     auto host = GetHost();
1283     if (host) {
1284         auto pattern = host->GetPattern();
1285         isNeedPercent = pattern ? pattern->IsNeedPercent() : false;
1286     }
1287     const auto& layout = layoutConstraint_.value();
1288     const auto& content = contentConstraint_.value();
1289     if (!isNeedPercent && GreaterOrEqualToInfinity(layout.maxSize.Width()) && !widthPercentSensitive_) {
1290         return (layout.EqualWithoutPercentWidth(preLayoutConstraint.value()) &&
1291             content.EqualWithoutPercentWidth(preContentConstraint.value()));
1292     }
1293     if (!isNeedPercent && GreaterOrEqualToInfinity(layout.maxSize.Height()) && !heightPercentSensitive_) {
1294         return (layout.EqualWithoutPercentHeight(preLayoutConstraint.value()) &&
1295             content.EqualWithoutPercentHeight(preContentConstraint.value()));
1296     }
1297     return (preLayoutConstraint == layoutConstraint_ && preContentConstraint == contentConstraint_);
1298 }
1299 
CheckPositionLocalizedEdges(TextDirection layoutDirection)1300 void LayoutProperty::CheckPositionLocalizedEdges(TextDirection layoutDirection)
1301 {
1302     auto host = GetHost();
1303     CHECK_NULL_VOID(host);
1304     const auto& target = host->GetRenderContext();
1305     CHECK_NULL_VOID(target);
1306     EdgesParam edges;
1307     auto positionEdges = target->GetPositionEdgesValue(EdgesParam {});
1308     if (positionEdges.top.has_value()) {
1309         edges.SetTop(positionEdges.top.value_or(Dimension(0.0)));
1310     }
1311     if (positionEdges.bottom.has_value()) {
1312         edges.SetBottom(positionEdges.bottom.value_or(Dimension(0.0)));
1313     }
1314     if (positionEdges.left.has_value()) {
1315         if (layoutDirection == TextDirection::RTL) {
1316             edges.SetRight(positionEdges.left.value_or(Dimension(0.0)));
1317         } else {
1318             edges.SetLeft(positionEdges.left.value_or(Dimension(0.0)));
1319         }
1320     }
1321     if (positionEdges.right.has_value()) {
1322         if (layoutDirection == TextDirection::RTL) {
1323             edges.SetLeft(positionEdges.right.value_or(Dimension(0.0)));
1324         } else {
1325             edges.SetRight(positionEdges.right.value_or(Dimension(0.0)));
1326         }
1327     }
1328     target->UpdatePositionEdges(edges);
1329 }
1330 
CheckMarkAnchorPosition(TextDirection layoutDirection)1331 void LayoutProperty::CheckMarkAnchorPosition(TextDirection layoutDirection)
1332 {
1333     auto host = GetHost();
1334     CHECK_NULL_VOID(host);
1335     const auto& target = host->GetRenderContext();
1336     CHECK_NULL_VOID(target);
1337     CalcDimension x;
1338     CalcDimension y;
1339     auto anchor = target->GetAnchorValue({});
1340     x = layoutDirection == TextDirection::RTL ? -anchor.GetX() : anchor.GetX();
1341     y = anchor.GetY();
1342     target->UpdateAnchor({ x, y });
1343 }
1344 
CheckOffsetLocalizedEdges(TextDirection layoutDirection)1345 void LayoutProperty::CheckOffsetLocalizedEdges(TextDirection layoutDirection)
1346 {
1347     auto host = GetHost();
1348     CHECK_NULL_VOID(host);
1349     const auto& target = host->GetRenderContext();
1350     CHECK_NULL_VOID(target);
1351     EdgesParam edges;
1352     auto offsetEdges = target->GetOffsetEdgesValue(EdgesParam {});
1353     if (offsetEdges.top.has_value()) {
1354         edges.SetTop(offsetEdges.top.value_or(Dimension(0.0)));
1355     }
1356     if (offsetEdges.bottom.has_value()) {
1357         edges.SetBottom(offsetEdges.bottom.value_or(Dimension(0.0)));
1358     }
1359     if (offsetEdges.left.has_value()) {
1360         if (layoutDirection == TextDirection::RTL) {
1361             edges.SetRight(offsetEdges.left.value_or(Dimension(0.0)));
1362         } else {
1363             edges.SetLeft(offsetEdges.left.value_or(Dimension(0.0)));
1364         }
1365     }
1366     if (offsetEdges.right.has_value()) {
1367         if (layoutDirection == TextDirection::RTL) {
1368             edges.SetLeft(offsetEdges.right.value_or(Dimension(0.0)));
1369         } else {
1370             edges.SetRight(offsetEdges.right.value_or(Dimension(0.0)));
1371         }
1372     }
1373     target->UpdateOffsetEdges(edges);
1374 }
1375 
CheckLocalizedBorderRadiuses(const TextDirection & direction)1376 void LayoutProperty::CheckLocalizedBorderRadiuses(const TextDirection& direction)
1377 {
1378     auto host = GetHost();
1379     CHECK_NULL_VOID(host);
1380     const auto& target = host->GetRenderContext();
1381     CHECK_NULL_VOID(target);
1382     BorderRadiusProperty borderRadius;
1383     BorderRadiusProperty borderRadiusProperty = target->GetBorderRadiusValue(BorderRadiusProperty {});
1384     if (!borderRadiusProperty.radiusTopStart.has_value() && !borderRadiusProperty.radiusTopEnd.has_value() &&
1385         !borderRadiusProperty.radiusBottomStart.has_value() && !borderRadiusProperty.radiusBottomEnd.has_value()) {
1386         return;
1387     }
1388     if (borderRadiusProperty.radiusTopStart.has_value()) {
1389         borderRadius.radiusTopStart = borderRadiusProperty.radiusTopStart;
1390         if (direction == TextDirection::RTL) {
1391             borderRadius.radiusTopRight = borderRadiusProperty.radiusTopStart;
1392         } else {
1393             borderRadius.radiusTopLeft = borderRadiusProperty.radiusTopStart;
1394         }
1395     }
1396     if (borderRadiusProperty.radiusTopEnd.has_value()) {
1397         borderRadius.radiusTopEnd = borderRadiusProperty.radiusTopEnd;
1398         if (direction == TextDirection::RTL) {
1399             borderRadius.radiusTopLeft = borderRadiusProperty.radiusTopEnd;
1400         } else {
1401             borderRadius.radiusTopRight = borderRadiusProperty.radiusTopEnd;
1402         }
1403     }
1404     if (borderRadiusProperty.radiusBottomStart.has_value()) {
1405         borderRadius.radiusBottomStart = borderRadiusProperty.radiusBottomStart;
1406         if (direction == TextDirection::RTL) {
1407             borderRadius.radiusBottomRight = borderRadiusProperty.radiusBottomStart;
1408         } else {
1409             borderRadius.radiusBottomLeft = borderRadiusProperty.radiusBottomStart;
1410         }
1411     }
1412     if (borderRadiusProperty.radiusBottomEnd.has_value()) {
1413         borderRadius.radiusBottomEnd = borderRadiusProperty.radiusBottomEnd;
1414         if (direction == TextDirection::RTL) {
1415             borderRadius.radiusBottomLeft = borderRadiusProperty.radiusBottomEnd;
1416         } else {
1417             borderRadius.radiusBottomRight = borderRadiusProperty.radiusBottomEnd;
1418         }
1419     }
1420     target->UpdateBorderRadius(borderRadius);
1421 }
1422 
CheckLocalizedOuterBorderColor(const TextDirection & direction)1423 void LayoutProperty::CheckLocalizedOuterBorderColor(const TextDirection& direction)
1424 {
1425     auto host = GetHost();
1426     CHECK_NULL_VOID(host);
1427     const auto& target = host->GetRenderContext();
1428     CHECK_NULL_VOID(target);
1429     NG::BorderColorProperty borderColors;
1430     borderColors.multiValued = true;
1431     auto outerBorderColorProperty = target->GetOuterBorderColorValue(BorderColorProperty {});
1432     if (!outerBorderColorProperty.startColor.has_value() && !outerBorderColorProperty.endColor.has_value()) {
1433         return;
1434     }
1435     if (outerBorderColorProperty.startColor.has_value()) {
1436         borderColors.startColor = outerBorderColorProperty.startColor;
1437         if (direction == TextDirection::RTL) {
1438             borderColors.rightColor = outerBorderColorProperty.startColor;
1439         } else {
1440             borderColors.leftColor = outerBorderColorProperty.startColor;
1441         }
1442     }
1443     if (outerBorderColorProperty.endColor.has_value()) {
1444         borderColors.endColor = outerBorderColorProperty.endColor;
1445         if (direction == TextDirection::RTL) {
1446             borderColors.leftColor = outerBorderColorProperty.endColor;
1447         } else {
1448             borderColors.rightColor = outerBorderColorProperty.endColor;
1449         }
1450     }
1451     if (outerBorderColorProperty.topColor.has_value()) {
1452         borderColors.topColor = outerBorderColorProperty.topColor;
1453     }
1454     if (outerBorderColorProperty.bottomColor.has_value()) {
1455         borderColors.bottomColor = outerBorderColorProperty.bottomColor;
1456     }
1457     target->UpdateOuterBorderColor(borderColors);
1458 }
1459 
CheckLocalizedPadding(const RefPtr<LayoutProperty> & layoutProperty,const TextDirection & direction)1460 void LayoutProperty::CheckLocalizedPadding(const RefPtr<LayoutProperty>& layoutProperty, const TextDirection& direction)
1461 {
1462     CHECK_NULL_VOID(layoutProperty);
1463     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
1464     CHECK_NULL_VOID(paddingProperty);
1465     if (!paddingProperty->start.has_value() && !paddingProperty->end.has_value()) {
1466         return;
1467     }
1468     PaddingProperty padding;
1469     if (paddingProperty->start.has_value()) {
1470         padding.start = paddingProperty->start;
1471         if (direction == TextDirection::RTL) {
1472             padding.right = paddingProperty->start;
1473         } else {
1474             padding.left = paddingProperty->start;
1475         }
1476     }
1477     if (paddingProperty->end.has_value()) {
1478         padding.end = paddingProperty->end;
1479         if (direction == TextDirection::RTL) {
1480             padding.left = paddingProperty->end;
1481         } else {
1482             padding.right = paddingProperty->end;
1483         }
1484     }
1485     if (paddingProperty->top.has_value()) {
1486         padding.top = paddingProperty->top;
1487     }
1488     if (paddingProperty->bottom.has_value()) {
1489         padding.bottom = paddingProperty->bottom;
1490     }
1491     if (padding.left.has_value() && !padding.right.has_value()) {
1492         padding.right = std::optional<CalcLength>(CalcLength(0));
1493     }
1494     if (!padding.left.has_value() && padding.right.has_value()) {
1495         padding.left = std::optional<CalcLength>(CalcLength(0));
1496     }
1497     LocalizedPaddingOrMarginChange(padding, padding_);
1498 }
1499 
CheckLocalizedMargin(const RefPtr<LayoutProperty> & layoutProperty,const TextDirection & direction)1500 void LayoutProperty::CheckLocalizedMargin(const RefPtr<LayoutProperty>& layoutProperty, const TextDirection& direction)
1501 {
1502     CHECK_NULL_VOID(layoutProperty);
1503     const auto& marginProperty = layoutProperty->GetMarginProperty();
1504     CHECK_NULL_VOID(marginProperty);
1505     if (!marginProperty->start.has_value() && !marginProperty->end.has_value()) {
1506         return;
1507     }
1508     MarginProperty margin;
1509     if (marginProperty->start.has_value()) {
1510         margin.start = marginProperty->start;
1511         if (direction == TextDirection::RTL) {
1512             margin.right = marginProperty->start;
1513         } else {
1514             margin.left = marginProperty->start;
1515         }
1516     }
1517     if (marginProperty->end.has_value()) {
1518         margin.end = marginProperty->end;
1519         if (direction == TextDirection::RTL) {
1520             margin.left = marginProperty->end;
1521         } else {
1522             margin.right = marginProperty->end;
1523         }
1524     }
1525     if (marginProperty->top.has_value()) {
1526         margin.top = marginProperty->top;
1527     }
1528     if (marginProperty->bottom.has_value()) {
1529         margin.bottom = marginProperty->bottom;
1530     }
1531     if (margin.left.has_value() && !margin.right.has_value()) {
1532         margin.right = std::optional<CalcLength>(CalcLength(0));
1533     }
1534     if (!margin.left.has_value() && margin.right.has_value()) {
1535         margin.left = std::optional<CalcLength>(CalcLength(0));
1536     }
1537     LocalizedPaddingOrMarginChange(margin, margin_);
1538 }
1539 
LocalizedPaddingOrMarginChange(const PaddingProperty & value,std::unique_ptr<PaddingProperty> & padding)1540 void LayoutProperty::LocalizedPaddingOrMarginChange(
1541     const PaddingProperty& value, std::unique_ptr<PaddingProperty>& padding)
1542 {
1543     if (value != *padding || padding->start != value.start || padding->end != value.end) {
1544         padding->start = value.start;
1545         padding->end = value.end;
1546         padding->left = value.left;
1547         padding->right = value.right;
1548         padding->top = value.top;
1549         padding->bottom = value.bottom;
1550         propertyChangeFlag_ = propertyChangeFlag_ | PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE;
1551     }
1552 }
1553 
CheckLocalizedEdgeWidths(const RefPtr<LayoutProperty> & layoutProperty,const TextDirection & direction)1554 void LayoutProperty::CheckLocalizedEdgeWidths(
1555     const RefPtr<LayoutProperty>& layoutProperty, const TextDirection& direction)
1556 {
1557     CHECK_NULL_VOID(layoutProperty);
1558     auto host = GetHost();
1559     CHECK_NULL_VOID(host);
1560     const auto& target = host->GetRenderContext();
1561     CHECK_NULL_VOID(target);
1562     auto borderWidthProperty = target->GetBorderWidth();
1563     CHECK_NULL_VOID(borderWidthProperty);
1564     if (!borderWidthProperty->startDimen.has_value() && !borderWidthProperty->endDimen.has_value()) {
1565         return;
1566     }
1567     BorderWidthProperty borderWidth;
1568     if (borderWidthProperty->startDimen.has_value()) {
1569         borderWidth.startDimen = borderWidthProperty->startDimen;
1570         if (direction == TextDirection::RTL) {
1571             borderWidth.rightDimen = borderWidthProperty->startDimen;
1572         } else {
1573             borderWidth.leftDimen = borderWidthProperty->startDimen;
1574         }
1575     }
1576     if (borderWidthProperty->endDimen.has_value()) {
1577         borderWidth.endDimen = borderWidthProperty->endDimen;
1578         if (direction == TextDirection::RTL) {
1579             borderWidth.leftDimen = borderWidthProperty->endDimen;
1580         } else {
1581             borderWidth.rightDimen = borderWidthProperty->endDimen;
1582         }
1583     }
1584     if (borderWidthProperty->topDimen.has_value()) {
1585         borderWidth.topDimen = borderWidthProperty->topDimen;
1586     }
1587     if (borderWidthProperty->bottomDimen.has_value()) {
1588         borderWidth.bottomDimen = borderWidthProperty->bottomDimen;
1589     }
1590     if (borderWidth.leftDimen.has_value() && !borderWidth.rightDimen.has_value()) {
1591         borderWidth.rightDimen = std::optional<Dimension>(Dimension(0));
1592     }
1593     if (!borderWidth.leftDimen.has_value() && borderWidth.rightDimen.has_value()) {
1594         borderWidth.leftDimen = std::optional<Dimension>(Dimension(0));
1595     }
1596     borderWidth.multiValued = true;
1597     layoutProperty->UpdateBorderWidth(borderWidth);
1598     target->UpdateBorderWidth(borderWidth);
1599 }
1600 
CheckLocalizedEdgeColors(const TextDirection & direction)1601 void LayoutProperty::CheckLocalizedEdgeColors(const TextDirection& direction)
1602 {
1603     auto host = GetHost();
1604     CHECK_NULL_VOID(host);
1605     const auto& target = host->GetRenderContext();
1606     CHECK_NULL_VOID(target);
1607     BorderColorProperty borderColors;
1608     BorderColorProperty colorProperty = target->GetBorderColorValue(BorderColorProperty {});
1609     if (!colorProperty.startColor.has_value() && !colorProperty.endColor.has_value()) {
1610         return;
1611     }
1612     if (colorProperty.startColor.has_value()) {
1613         borderColors.startColor = colorProperty.startColor;
1614         if (direction == TextDirection::RTL) {
1615             borderColors.rightColor = colorProperty.startColor;
1616         } else {
1617             borderColors.leftColor = colorProperty.startColor;
1618         }
1619     }
1620     if (colorProperty.endColor.has_value()) {
1621         borderColors.endColor = colorProperty.endColor;
1622         if (direction == TextDirection::RTL) {
1623             borderColors.leftColor = colorProperty.endColor;
1624         } else {
1625             borderColors.rightColor = colorProperty.endColor;
1626         }
1627     }
1628     if (colorProperty.topColor.has_value()) {
1629         borderColors.topColor = colorProperty.topColor;
1630     }
1631     if (colorProperty.bottomColor.has_value()) {
1632         borderColors.topColor = colorProperty.bottomColor;
1633     }
1634     borderColors.multiValued = true;
1635     target->UpdateBorderColor(borderColors);
1636 }
1637 
CheckLocalizedBorderImageSlice(const TextDirection & direction)1638 void LayoutProperty::CheckLocalizedBorderImageSlice(const TextDirection& direction)
1639 {
1640     auto host = GetHost();
1641     CHECK_NULL_VOID(host);
1642     const auto& target = host->GetRenderContext();
1643     CHECK_NULL_VOID(target);
1644     auto borderImage = target->GetBorderImage();
1645     CHECK_NULL_VOID(borderImage);
1646     auto borderImageProperty = borderImage.value();
1647     CHECK_NULL_VOID(borderImageProperty);
1648     if (!borderImageProperty->borderImageStart_.has_value() && !borderImageProperty->borderImageEnd_.has_value()) {
1649         return;
1650     }
1651     Dimension leftSlice;
1652     Dimension rightSlice;
1653     Dimension startSlice;
1654     Dimension endSlice;
1655     if (borderImageProperty->borderImageStart_.has_value()) {
1656         startSlice = borderImageProperty->borderImageStart_->GetBorderImageSlice();
1657         borderImageProperty->SetEdgeSlice(BorderImageDirection::START, startSlice);
1658         if (direction == TextDirection::RTL) {
1659             rightSlice = borderImageProperty->borderImageStart_->GetBorderImageSlice();
1660         } else {
1661             leftSlice = borderImageProperty->borderImageStart_->GetBorderImageSlice();
1662         }
1663     }
1664     if (borderImageProperty->borderImageEnd_.has_value()) {
1665         endSlice = borderImageProperty->borderImageEnd_->GetBorderImageSlice();
1666         borderImageProperty->SetEdgeSlice(BorderImageDirection::END, endSlice);
1667         if (direction == TextDirection::RTL) {
1668             leftSlice = borderImageProperty->borderImageEnd_->GetBorderImageSlice();
1669         } else {
1670             rightSlice = borderImageProperty->borderImageEnd_->GetBorderImageSlice();
1671         }
1672     }
1673     borderImageProperty->SetEdgeSlice(BorderImageDirection::LEFT, leftSlice);
1674     borderImageProperty->SetEdgeSlice(BorderImageDirection::RIGHT, rightSlice);
1675     target->UpdateBorderImage(borderImageProperty);
1676 }
1677 
CheckLocalizedBorderImageWidth(const TextDirection & direction)1678 void LayoutProperty::CheckLocalizedBorderImageWidth(const TextDirection& direction)
1679 {
1680     auto host = GetHost();
1681     CHECK_NULL_VOID(host);
1682     const auto& target = host->GetRenderContext();
1683     CHECK_NULL_VOID(target);
1684     auto borderImage = target->GetBorderImage();
1685     CHECK_NULL_VOID(borderImage);
1686     auto borderImageProperty = borderImage.value();
1687     CHECK_NULL_VOID(borderImageProperty);
1688     if (!borderImageProperty->borderImageStart_.has_value() && !borderImageProperty->borderImageEnd_.has_value()) {
1689         return;
1690     }
1691     Dimension leftWidth;
1692     Dimension rightWidth;
1693     Dimension startWidth;
1694     Dimension endWidth;
1695     if (borderImageProperty->borderImageStart_.has_value()) {
1696         startWidth = borderImageProperty->borderImageStart_->GetBorderImageWidth();
1697         borderImageProperty->SetEdgeWidth(BorderImageDirection::START, startWidth);
1698         if (direction == TextDirection::RTL) {
1699             rightWidth = borderImageProperty->borderImageStart_->GetBorderImageWidth();
1700         } else {
1701             leftWidth = borderImageProperty->borderImageStart_->GetBorderImageWidth();
1702         }
1703     }
1704     if (borderImageProperty->borderImageEnd_.has_value()) {
1705         endWidth = borderImageProperty->borderImageEnd_->GetBorderImageWidth();
1706         borderImageProperty->SetEdgeWidth(BorderImageDirection::END, endWidth);
1707         if (direction == TextDirection::RTL) {
1708             leftWidth = borderImageProperty->borderImageEnd_->GetBorderImageWidth();
1709         } else {
1710             rightWidth = borderImageProperty->borderImageEnd_->GetBorderImageWidth();
1711         }
1712     }
1713     borderImageProperty->SetEdgeWidth(BorderImageDirection::LEFT, leftWidth);
1714     borderImageProperty->SetEdgeWidth(BorderImageDirection::RIGHT, rightWidth);
1715     target->UpdateBorderImage(borderImageProperty);
1716 }
1717 
CheckLocalizedBorderImageOutset(const TextDirection & direction)1718 void LayoutProperty::CheckLocalizedBorderImageOutset(const TextDirection& direction)
1719 {
1720     auto host = GetHost();
1721     CHECK_NULL_VOID(host);
1722     const auto& target = host->GetRenderContext();
1723     CHECK_NULL_VOID(target);
1724     auto borderImage = target->GetBorderImage();
1725     CHECK_NULL_VOID(borderImage);
1726     auto borderImageProperty = borderImage.value();
1727     CHECK_NULL_VOID(borderImageProperty);
1728     if (!borderImageProperty->borderImageStart_.has_value() && !borderImageProperty->borderImageEnd_.has_value()) {
1729         return;
1730     }
1731     Dimension leftOutset;
1732     Dimension rightOutset;
1733     Dimension startOutset;
1734     Dimension endOutset;
1735     if (borderImageProperty->borderImageStart_.has_value()) {
1736         startOutset = borderImageProperty->borderImageStart_->GetBorderImageOutset();
1737         borderImageProperty->SetEdgeOutset(BorderImageDirection::START, startOutset);
1738         if (direction == TextDirection::RTL) {
1739             rightOutset = borderImageProperty->borderImageStart_->GetBorderImageOutset();
1740         } else {
1741             leftOutset = borderImageProperty->borderImageStart_->GetBorderImageOutset();
1742         }
1743     }
1744     if (borderImageProperty->borderImageEnd_.has_value()) {
1745         endOutset = borderImageProperty->borderImageEnd_->GetBorderImageOutset();
1746         borderImageProperty->SetEdgeOutset(BorderImageDirection::END, endOutset);
1747         if (direction == TextDirection::RTL) {
1748             leftOutset = borderImageProperty->borderImageEnd_->GetBorderImageOutset();
1749         } else {
1750             rightOutset = borderImageProperty->borderImageEnd_->GetBorderImageOutset();
1751         }
1752     }
1753     borderImageProperty->SetEdgeOutset(BorderImageDirection::LEFT, leftOutset);
1754     borderImageProperty->SetEdgeOutset(BorderImageDirection::RIGHT, rightOutset);
1755     target->UpdateBorderImage(borderImageProperty);
1756 }
1757 } // namespace OHOS::Ace::NG
1758