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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_LAYOUT_CONSTRAINT_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_LAYOUT_CONSTRAINT_H
18 
19 #include <algorithm>
20 #include <optional>
21 #include <string>
22 
23 #include "base/geometry/ng/size_t.h"
24 #include "core/components_ng/property/calc_length.h"
25 #include "core/components_ng/property/measure_property.h"
26 
27 namespace OHOS::Ace::NG {
28 template<typename T>
29 struct LayoutConstraintT {
30     ScaleProperty scaleProperty = ScaleProperty::CreateScaleProperty();
31     SizeT<T> minSize { 0, 0 };
32     SizeT<T> maxSize { Infinity<T>(), Infinity<T>() };
33     SizeT<T> percentReference { 0, 0 };
34     OptionalSize<T> parentIdealSize;
35     OptionalSize<T> selfIdealSize;
36 
CompareWithInfinityCheckLayoutConstraintT37     static bool CompareWithInfinityCheck(const OptionalSize<float>& first, const OptionalSize<float>& second)
38     {
39         if (first.Width().has_value() ^ second.Width().has_value()) {
40             return false;
41         }
42         auto widthBothInf = GreaterOrEqualToInfinity(first.Width().value_or(0.0f)) &&
43                             GreaterOrEqualToInfinity(second.Width().value_or(0.0f));
44         if (!widthBothInf && !NearEqual(first.Width().value_or(0), second.Width().value_or(0))) {
45             return false;
46         }
47         if (first.Height().has_value() ^ second.Height().has_value()) {
48             return false;
49         }
50         auto heightBothInf = GreaterOrEqualToInfinity(first.Height().value_or(0.0f)) &&
51                             GreaterOrEqualToInfinity(second.Height().value_or(0.0f));
52         if (!heightBothInf && !NearEqual(first.Height().value_or(0), second.Height().value_or(0))) {
53             return false;
54         }
55         return true;
56     }
57 
CompareWithInfinityCheckLayoutConstraintT58     static bool CompareWithInfinityCheck(const SizeT<float>& first, const SizeT<float>& second)
59     {
60         auto widthBothInf = GreaterOrEqualToInfinity(first.Width()) && GreaterOrEqualToInfinity(second.Width());
61         auto heightBothInf = GreaterOrEqualToInfinity(first.Height()) && GreaterOrEqualToInfinity(second.Height());
62         if (widthBothInf && heightBothInf) {
63             return true;
64         }
65         return NearEqual(first.Width(), second.Width()) && NearEqual(first.Height(), second.Height());
66     }
67 
CompareWithInfinityCheckLayoutConstraintT68     static bool CompareWithInfinityCheck(float first, float second)
69     {
70         auto bothInf = GreaterOrEqualToInfinity(first) && GreaterOrEqualToInfinity(second);
71         if (bothInf) {
72             return true;
73         }
74         return NearEqual(first, second);
75     }
76 
77     void ApplyAspectRatio(float ratio, const std::optional<CalcSize>& calcSize, bool greaterThanApiTen = false);
78 
79     void ApplyAspectRatioToParentIdealSize(bool useWidth, float ratio);
80 
81     void ApplyAspectRatioByMaxSize(float ratio, std::optional<bool> useDefinedWidth, bool greaterThanApiTen = false);
82 
83     void ApplyAspectRatioWithCalcSize(float ratio, bool useDefinedWidth);
84 
85     void ApplyAspectRatioWithoutCalcSize(float ratio, bool greaterThanApiTen = false);
86 
87     void Reset();
88 
89     void MinusPadding(const std::optional<T>& left, const std::optional<T>& right, const std::optional<T>& top,
90         const std::optional<T>& bottom);
91 
92     void MinusPaddingToNonNegativeSize(const std::optional<T>& left, const std::optional<T>& right,
93         const std::optional<T>& top, const std::optional<T>& bottom);
94 
95     bool operator==(const LayoutConstraintT& layoutConstraint) const
96     {
97         return (scaleProperty == layoutConstraint.scaleProperty) && (minSize == layoutConstraint.minSize) &&
98                (maxSize == layoutConstraint.maxSize) && (percentReference == layoutConstraint.percentReference) &&
99                (parentIdealSize == layoutConstraint.parentIdealSize) &&
100                (selfIdealSize == layoutConstraint.selfIdealSize);
101     }
102 
103     bool operator!=(const LayoutConstraintT& layoutConstraint) const
104     {
105         return !(*this == layoutConstraint);
106     }
107 
EqualWithoutPercentWidthLayoutConstraintT108     bool EqualWithoutPercentWidth(const LayoutConstraintT& layoutConstraint) const
109     {
110         return (scaleProperty == layoutConstraint.scaleProperty) &&
111                CompareWithInfinityCheck(minSize, layoutConstraint.minSize) &&
112                CompareWithInfinityCheck(maxSize, layoutConstraint.maxSize) &&
113                CompareWithInfinityCheck(parentIdealSize, layoutConstraint.parentIdealSize) &&
114                CompareWithInfinityCheck(percentReference.Height(), layoutConstraint.percentReference.Height()) &&
115                CompareWithInfinityCheck(selfIdealSize, layoutConstraint.selfIdealSize);
116     }
117 
EqualWithoutPercentHeightLayoutConstraintT118     bool EqualWithoutPercentHeight(const LayoutConstraintT& layoutConstraint) const
119     {
120         return (scaleProperty == layoutConstraint.scaleProperty) &&
121                CompareWithInfinityCheck(minSize, layoutConstraint.minSize) &&
122                CompareWithInfinityCheck(maxSize, layoutConstraint.maxSize) &&
123                CompareWithInfinityCheck(parentIdealSize, layoutConstraint.parentIdealSize) &&
124                CompareWithInfinityCheck(percentReference.Width(), layoutConstraint.percentReference.Width()) &&
125                CompareWithInfinityCheck(selfIdealSize, layoutConstraint.selfIdealSize);
126     }
127 
UpdateSelfMarginSizeWithCheckLayoutConstraintT128     bool UpdateSelfMarginSizeWithCheck(const OptionalSize<T>& size)
129     {
130         if (selfIdealSize == size) {
131             return false;
132         }
133         return selfIdealSize.UpdateSizeWithCheck(size);
134     }
135 
UpdateIllegalSelfMarginSizeWithCheckLayoutConstraintT136     bool UpdateIllegalSelfMarginSizeWithCheck(const OptionalSize<T>& size)
137     {
138         if (selfIdealSize == size) {
139             return false;
140         }
141         return selfIdealSize.UpdateIllegalSizeWithCheck(size);
142     }
143 
UpdateIllegalSelfIdealSizeWithCheckLayoutConstraintT144     bool UpdateIllegalSelfIdealSizeWithCheck(const OptionalSize<T>& size)
145     {
146         if (selfIdealSize == size) {
147             return false;
148         }
149         return selfIdealSize.UpdateIllegalSizeWithCheck(size);
150     }
151 
UpdateParentIdealSizeWithCheckLayoutConstraintT152     bool UpdateParentIdealSizeWithCheck(const OptionalSize<T>&& size)
153     {
154         if (parentIdealSize == size) {
155             return false;
156         }
157         return parentIdealSize.UpdateSizeWithCheck(size);
158     }
159 
UpdateIllegalParentIdealSizeWithCheckLayoutConstraintT160     bool UpdateIllegalParentIdealSizeWithCheck(const OptionalSize<T>&& size)
161     {
162         if (parentIdealSize == size) {
163             return false;
164         }
165         return parentIdealSize.UpdateIllegalSizeWithCheck(size);
166     }
167 
UpdateMaxSizeWithCheckLayoutConstraintT168     bool UpdateMaxSizeWithCheck(const SizeT<T>& size)
169     {
170         if (maxSize == size) {
171             return false;
172         }
173         return maxSize.UpdateSizeWhenSmaller(size);
174     }
175 
UpdateMaxWidthWithCheckLayoutConstraintT176     bool UpdateMaxWidthWithCheck(const SizeT<T>& size)
177     {
178         if (maxSize == size) {
179             return false;
180         }
181         return maxSize.UpdateWidthWhenSmaller(size);
182     }
183 
UpdateMaxHeightWithCheckLayoutConstraintT184     bool UpdateMaxHeightWithCheck(const SizeT<T>& size)
185     {
186         if (maxSize == size) {
187             return false;
188         }
189         return maxSize.UpdateHeightWhenSmaller(size);
190     }
191 
UpdateMinSizeWithCheckLayoutConstraintT192     bool UpdateMinSizeWithCheck(const SizeT<T>& size)
193     {
194         if (minSize == size) {
195             return false;
196         }
197         return minSize.UpdateSizeWhenLarger(size);
198     }
199 
UpdatePercentReferenceLayoutConstraintT200     bool UpdatePercentReference(const SizeT<T>& size)
201     {
202         if (percentReference == size) {
203             return false;
204         }
205         percentReference.SetSizeT(size);
206         return true;
207     }
208 
209     std::string ToString() const;
210 
211     SizeF Constrain(const SizeF& size) const;
212 };
213 
214 using LayoutConstraintF = LayoutConstraintT<float>;
215 } // namespace OHOS::Ace::NG
216 
217 #include "layout_constraint.inl"
218 
219 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_LAYOUT_CONSTRAINT_H
220