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/layout_policy_property.h" 26 #include "core/components_ng/property/measure_property.h" 27 28 namespace OHOS::Ace::NG { 29 enum class ReferenceEdge { 30 START, 31 END, 32 }; 33 struct ViewPosReference { 34 float viewPosStart; 35 float viewPosEnd; 36 float referencePos; 37 ReferenceEdge referenceEdge; 38 Axis axis; 39 40 bool operator==(const ViewPosReference &other) const 41 { 42 return NearEqual(viewPosStart, other.viewPosStart) && 43 NearEqual(viewPosEnd, other.viewPosEnd) && 44 NearEqual(referencePos, other.referencePos) && 45 referenceEdge == other.referenceEdge && 46 axis == other.axis; 47 } 48 }; 49 template<typename T> 50 struct LayoutConstraintT { 51 ScaleProperty scaleProperty = ScaleProperty::CreateScaleProperty(); 52 SizeT<T> minSize { 0, 0 }; 53 SizeT<T> maxSize { Infinity<T>(), Infinity<T>() }; 54 SizeT<T> percentReference { 0, 0 }; 55 OptionalSize<T> parentIdealSize; 56 OptionalSize<T> selfIdealSize; 57 std::optional<ViewPosReference> viewPosRef; 58 CompareWithInfinityCheckLayoutConstraintT59 static bool CompareWithInfinityCheck(const OptionalSize<float>& first, const OptionalSize<float>& second) 60 { 61 if (first.Width().has_value() ^ second.Width().has_value()) { 62 return false; 63 } 64 auto widthBothInf = GreaterOrEqualToInfinity(first.Width().value_or(0.0f)) && 65 GreaterOrEqualToInfinity(second.Width().value_or(0.0f)); 66 if (!widthBothInf && !NearEqual(first.Width().value_or(0), second.Width().value_or(0))) { 67 return false; 68 } 69 if (first.Height().has_value() ^ second.Height().has_value()) { 70 return false; 71 } 72 auto heightBothInf = GreaterOrEqualToInfinity(first.Height().value_or(0.0f)) && 73 GreaterOrEqualToInfinity(second.Height().value_or(0.0f)); 74 if (!heightBothInf && !NearEqual(first.Height().value_or(0), second.Height().value_or(0))) { 75 return false; 76 } 77 return true; 78 } 79 CompareWithInfinityCheckLayoutConstraintT80 static bool CompareWithInfinityCheck(const SizeT<float>& first, const SizeT<float>& second) 81 { 82 auto widthBothInf = GreaterOrEqualToInfinity(first.Width()) && GreaterOrEqualToInfinity(second.Width()); 83 auto heightBothInf = GreaterOrEqualToInfinity(first.Height()) && GreaterOrEqualToInfinity(second.Height()); 84 if (widthBothInf && heightBothInf) { 85 return true; 86 } 87 return NearEqual(first.Width(), second.Width()) && NearEqual(first.Height(), second.Height()); 88 } 89 CompareWithInfinityCheckLayoutConstraintT90 static bool CompareWithInfinityCheck(float first, float second) 91 { 92 auto bothInf = GreaterOrEqualToInfinity(first) && GreaterOrEqualToInfinity(second); 93 if (bothInf) { 94 return true; 95 } 96 return NearEqual(first, second); 97 } 98 99 void ApplyAspectRatio(float ratio, const std::optional<CalcSize>& calcSize, 100 const std::optional<NG::LayoutPolicyProperty>& layoutPolicy = std::nullopt, bool greaterThanApiTen = false); 101 102 void ApplyAspectRatioToParentIdealSize(bool useWidth, float ratio); 103 104 void ApplyAspectRatioByMaxSize(float ratio, std::optional<bool> useDefinedWidth, bool greaterThanApiTen = false); 105 106 void ApplyAspectRatioWithCalcSize(float ratio, bool useDefinedWidth); 107 108 void ApplyAspectRatioWithoutCalcSize(float ratio, bool greaterThanApiTen = false); 109 110 void Reset(); 111 112 void MinusPadding(const std::optional<T>& left, const std::optional<T>& right, const std::optional<T>& top, 113 const std::optional<T>& bottom); 114 115 void MinusPaddingToNonNegativeSize(const std::optional<T>& left, const std::optional<T>& right, 116 const std::optional<T>& top, const std::optional<T>& bottom); 117 118 bool operator==(const LayoutConstraintT& layoutConstraint) const 119 { 120 return (scaleProperty == layoutConstraint.scaleProperty) && (minSize == layoutConstraint.minSize) && 121 (maxSize == layoutConstraint.maxSize) && (percentReference == layoutConstraint.percentReference) && 122 (parentIdealSize == layoutConstraint.parentIdealSize) && 123 (selfIdealSize == layoutConstraint.selfIdealSize) && (viewPosRef == layoutConstraint.viewPosRef); 124 } 125 126 bool operator!=(const LayoutConstraintT& layoutConstraint) const 127 { 128 return !(*this == layoutConstraint); 129 } 130 EqualWithoutPercentWidthLayoutConstraintT131 bool EqualWithoutPercentWidth(const LayoutConstraintT& layoutConstraint) const 132 { 133 return (scaleProperty == layoutConstraint.scaleProperty) && 134 CompareWithInfinityCheck(minSize, layoutConstraint.minSize) && 135 CompareWithInfinityCheck(maxSize, layoutConstraint.maxSize) && 136 CompareWithInfinityCheck(parentIdealSize, layoutConstraint.parentIdealSize) && 137 CompareWithInfinityCheck(percentReference.Height(), layoutConstraint.percentReference.Height()) && 138 CompareWithInfinityCheck(selfIdealSize, layoutConstraint.selfIdealSize) && 139 (viewPosRef == layoutConstraint.viewPosRef); 140 } 141 EqualWithoutPercentHeightLayoutConstraintT142 bool EqualWithoutPercentHeight(const LayoutConstraintT& layoutConstraint) const 143 { 144 return (scaleProperty == layoutConstraint.scaleProperty) && 145 CompareWithInfinityCheck(minSize, layoutConstraint.minSize) && 146 CompareWithInfinityCheck(maxSize, layoutConstraint.maxSize) && 147 CompareWithInfinityCheck(parentIdealSize, layoutConstraint.parentIdealSize) && 148 CompareWithInfinityCheck(percentReference.Width(), layoutConstraint.percentReference.Width()) && 149 CompareWithInfinityCheck(selfIdealSize, layoutConstraint.selfIdealSize) && 150 (viewPosRef == layoutConstraint.viewPosRef); 151 } 152 UpdateSelfMarginSizeWithCheckLayoutConstraintT153 bool UpdateSelfMarginSizeWithCheck(const OptionalSize<T>& size) 154 { 155 if (selfIdealSize == size) { 156 return false; 157 } 158 return selfIdealSize.UpdateSizeWithCheck(size); 159 } 160 UpdateIllegalSelfMarginSizeWithCheckLayoutConstraintT161 bool UpdateIllegalSelfMarginSizeWithCheck(const OptionalSize<T>& size) 162 { 163 if (selfIdealSize == size) { 164 return false; 165 } 166 return selfIdealSize.UpdateIllegalSizeWithCheck(size); 167 } 168 UpdateIllegalSelfIdealSizeWithCheckLayoutConstraintT169 bool UpdateIllegalSelfIdealSizeWithCheck(const OptionalSize<T>& size) 170 { 171 if (selfIdealSize == size) { 172 return false; 173 } 174 return selfIdealSize.UpdateIllegalSizeWithCheck(size); 175 } 176 UpdateParentIdealSizeWithCheckLayoutConstraintT177 bool UpdateParentIdealSizeWithCheck(const OptionalSize<T>&& size) 178 { 179 if (parentIdealSize == size) { 180 return false; 181 } 182 return parentIdealSize.UpdateSizeWithCheck(size); 183 } 184 UpdateIllegalParentIdealSizeWithCheckLayoutConstraintT185 bool UpdateIllegalParentIdealSizeWithCheck(const OptionalSize<T>&& size) 186 { 187 if (parentIdealSize == size) { 188 return false; 189 } 190 return parentIdealSize.UpdateIllegalSizeWithCheck(size); 191 } 192 UpdateParentIdealSizeByLayoutPolicyLayoutConstraintT193 bool UpdateParentIdealSizeByLayoutPolicy(const SizeT<T>& size, bool isMax, NG::LayoutPolicyProperty layoutPolicy) 194 { 195 bool widthUpdated = false; 196 bool heightUpdated = false; 197 if (layoutPolicy.IsWidthMatch()) { 198 if (isMax) { 199 widthUpdated = parentIdealSize.UpdateWidthWhenSmaller(size); 200 } else { 201 widthUpdated = parentIdealSize.UpdateWidthWhenLarger(size); 202 } 203 } 204 if (layoutPolicy.IsHeightMatch()) { 205 if (isMax) { 206 heightUpdated = parentIdealSize.UpdateHeightWhenSmaller(size); 207 } else { 208 heightUpdated = parentIdealSize.UpdateHeightWhenLarger(size); 209 } 210 } 211 return widthUpdated || heightUpdated; 212 } 213 UpdateMaxSizeWithCheckLayoutConstraintT214 bool UpdateMaxSizeWithCheck(const SizeT<T>& size) 215 { 216 if (maxSize == size) { 217 return false; 218 } 219 return maxSize.UpdateSizeWhenSmaller(size); 220 } 221 UpdateMaxWidthWithCheckLayoutConstraintT222 bool UpdateMaxWidthWithCheck(const SizeT<T>& size) 223 { 224 if (maxSize == size) { 225 return false; 226 } 227 return maxSize.UpdateWidthWhenSmaller(size); 228 } 229 UpdateMaxHeightWithCheckLayoutConstraintT230 bool UpdateMaxHeightWithCheck(const SizeT<T>& size) 231 { 232 if (maxSize == size) { 233 return false; 234 } 235 return maxSize.UpdateHeightWhenSmaller(size); 236 } 237 UpdateMinSizeWithCheckLayoutConstraintT238 bool UpdateMinSizeWithCheck(const SizeT<T>& size) 239 { 240 if (minSize == size) { 241 return false; 242 } 243 return minSize.UpdateSizeWhenLarger(size); 244 } 245 UpdatePercentReferenceLayoutConstraintT246 bool UpdatePercentReference(const SizeT<T>& size) 247 { 248 if (percentReference == size) { 249 return false; 250 } 251 percentReference.SetSizeT(size); 252 return true; 253 } 254 255 std::string ToString() const; 256 257 SizeF Constrain(const SizeF& size) const; 258 }; 259 260 using LayoutConstraintF = LayoutConstraintT<float>; 261 } // namespace OHOS::Ace::NG 262 263 #include "layout_constraint.inl" 264 265 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_LAYOUT_CONSTRAINT_H 266