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