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