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