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