• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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