1/* 2 * Copyright (c) 2023 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 16namespace OHOS::Ace::NG { 17template<typename T> 18void LayoutConstraintT<T>::ApplyAspectRatio(float ratio, const std::optional<CalcSize>& calcSize) 19{ 20 if (!Positive(ratio)) { 21 // just in case ratio is illegal value 22 LOGD("Aspect ratio value is not positive"); 23 return; 24 } 25 std::optional<bool> useDefinedWidth; 26 if (calcSize) { 27 if (calcSize.value().Width()) { 28 useDefinedWidth = true; 29 } else if (calcSize.value().Height()) { 30 useDefinedWidth = false; 31 } 32 } 33 if (useDefinedWidth) { 34 if (useDefinedWidth.value_or(false)) { 35 if (selfIdealSize.Width()) { 36 selfIdealSize.SetHeight(selfIdealSize.Width().value() / ratio); 37 } 38 minSize.SetHeight(minSize.Width() / ratio); 39 maxSize.SetHeight(maxSize.Width() / ratio); 40 ApplyAspectRatioToParentIdealSize(true, ratio); 41 return; 42 } 43 if (selfIdealSize.Height()) { 44 selfIdealSize.SetWidth(selfIdealSize.Height().value() * ratio); 45 } 46 minSize.SetWidth(minSize.Height() * ratio); 47 maxSize.SetWidth(maxSize.Height() * ratio); 48 ApplyAspectRatioToParentIdealSize(false, ratio); 49 return; 50 } else { 51 if (selfIdealSize.Width()) { 52 selfIdealSize.SetHeight(selfIdealSize.Width().value() / ratio); 53 minSize.SetHeight(minSize.Width() / ratio); 54 maxSize.SetHeight(maxSize.Width() / ratio); 55 ApplyAspectRatioToParentIdealSize(true, ratio); 56 return; 57 } 58 if (selfIdealSize.Height()) { 59 selfIdealSize.SetWidth(selfIdealSize.Height().value() * ratio); 60 minSize.SetWidth(minSize.Height() * ratio); 61 maxSize.SetWidth(maxSize.Height() * ratio); 62 ApplyAspectRatioToParentIdealSize(false, ratio); 63 return; 64 } 65 } 66 // after previous conditions, ideal size does not exist, we use max size to rule aspect ratio 67 // but nothing can be done if both width and height are inf 68 if (NearEqual(maxSize.Width(), Infinity<T>()) && NearEqual(maxSize.Height(), Infinity<T>())) { 69 return; 70 } 71 ApplyAspectRatioByMaxSize(ratio, useDefinedWidth); 72} 73 74template<typename T> 75void LayoutConstraintT<T>::ApplyAspectRatioToParentIdealSize(bool useWidth, float ratio) 76{ 77 if (!Positive(ratio)) { 78 return; 79 } 80 if (useWidth && parentIdealSize.Width()) { 81 parentIdealSize.SetHeight(parentIdealSize.Width().value() / ratio); 82 return; 83 } 84 if (!parentIdealSize.Height()) { 85 return; 86 } 87 parentIdealSize.SetWidth(parentIdealSize.Height().value() * ratio); 88} 89 90template<typename T> 91void LayoutConstraintT<T>::ApplyAspectRatioByMaxSize(float ratio, std::optional<bool> useDefinedWidth) 92{ 93 if (!Positive(ratio)) { 94 return; 95 } 96 if (useDefinedWidth) { 97 ApplyAspectRatioWithCalcSize(ratio, useDefinedWidth.value()); 98 return; 99 } 100 ApplyAspectRatioWithoutCalcSize(ratio); 101} 102 103template<typename T> 104void LayoutConstraintT<T>::ApplyAspectRatioWithCalcSize(float ratio, bool useDefinedWidth) 105{ 106 if (!Positive(ratio)) { 107 return; 108 } 109 if (useDefinedWidth) { 110 minSize.SetHeight(minSize.Width() / ratio); 111 maxSize.SetHeight(maxSize.Width() / ratio); 112 percentReference.SetHeight(percentReference.Width() / ratio); 113 ApplyAspectRatioToParentIdealSize(true, ratio); 114 return; 115 } 116 minSize.SetWidth(minSize.Height() * ratio); 117 maxSize.SetWidth(maxSize.Height() * ratio); 118 percentReference.SetWidth(percentReference.Height() / ratio); 119 ApplyAspectRatioToParentIdealSize(false, ratio); 120} 121 122template<typename T> 123void LayoutConstraintT<T>::ApplyAspectRatioWithoutCalcSize(float ratio) 124{ 125 if (!Positive(ratio)) { 126 return; 127 } 128 if (maxSize.Width() < maxSize.Height()) { 129 minSize.SetHeight(minSize.Width() / ratio); 130 maxSize.SetHeight(maxSize.Width() / ratio); 131 percentReference.SetHeight(percentReference.Width() / ratio); 132 ApplyAspectRatioToParentIdealSize(true, ratio); 133 return; 134 } 135 minSize.SetWidth(minSize.Height() * ratio); 136 maxSize.SetWidth(maxSize.Height() * ratio); 137 percentReference.SetWidth(percentReference.Height() / ratio); 138 ApplyAspectRatioToParentIdealSize(false, ratio); 139} 140 141template<typename T> 142void LayoutConstraintT<T>::Reset() 143{ 144 scaleProperty.Reset(); 145 minSize = { 0, 0 }; 146 maxSize = { Infinity<T>(), Infinity<T>() }; 147 percentReference = { 0, 0 }; 148 parentIdealSize.Reset(); 149 selfIdealSize.Reset(); 150} 151 152template<typename T> 153void LayoutConstraintT<T>::MinusPadding(const std::optional<T>& left, const std::optional<T>& right, 154 const std::optional<T>& top, const std::optional<T>& bottom) 155{ 156 minSize.MinusPadding(left, right, top, bottom); 157 maxSize.MinusPadding(left, right, top, bottom); 158 parentIdealSize.MinusPadding(left, right, top, bottom); 159 selfIdealSize.MinusPadding(left, right, top, bottom); 160 percentReference.MinusPadding(left, right, top, bottom); 161} 162 163template<typename T> 164std::string LayoutConstraintT<T>::ToString() const 165{ 166 std::string str; 167 str.append("minSize: [").append(minSize.ToString()).append("]"); 168 str.append("maxSize: [").append(maxSize.ToString()).append("]"); 169 str.append("percentReference: [").append(percentReference.ToString()).append("]"); 170 str.append("parentIdealSize: [").append(parentIdealSize.ToString()).append("]"); 171 str.append("selfIdealSize: [").append(selfIdealSize.ToString()).append("]"); 172 return str; 173} 174 175template<typename T> 176SizeF LayoutConstraintT<T>::Constrain(const SizeF& size) const 177{ 178 SizeF constrainSize; 179 constrainSize.SetWidth(std::clamp(size.Width(), minSize.Width(), maxSize.Width())); 180 constrainSize.SetHeight(std::clamp(size.Height(), minSize.Height(), maxSize.Height())); 181 return constrainSize; 182} 183} // namespace OHOS::Ace::NG