1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QSIZE_H
41#define QSIZE_H
42
43#include <QtCore/qnamespace.h>
44#include <QtCore/qhashfunctions.h>
45#include <QtCore/qmargins.h>
46
47#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
48struct CGSize;
49#endif
50
51QT_BEGIN_NAMESPACE
52
53
54class Q_CORE_EXPORT QSize
55{
56public:
57 constexpr QSize() noexcept;
58 constexpr QSize(int w, int h) noexcept;
59
60 constexpr inline bool isNull() const noexcept;
61 constexpr inline bool isEmpty() const noexcept;
62 constexpr inline bool isValid() const noexcept;
63
64 constexpr inline int width() const noexcept;
65 constexpr inline int height() const noexcept;
66 constexpr inline void setWidth(int w) noexcept;
67 constexpr inline void setHeight(int h) noexcept;
68 void transpose() noexcept;
69 [[nodiscard]] constexpr inline QSize transposed() const noexcept;
70
71 inline void scale(int w, int h, Qt::AspectRatioMode mode) noexcept;
72 inline void scale(const QSize &s, Qt::AspectRatioMode mode) noexcept;
73 [[nodiscard]] QSize scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept;
74 [[nodiscard]] QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept;
75
76 [[nodiscard]] constexpr inline QSize expandedTo(const QSize &) const noexcept;
77 [[nodiscard]] constexpr inline QSize boundedTo(const QSize &) const noexcept;
78
79 [[nodiscard]] constexpr QSize grownBy(QMargins m) const noexcept
80 { return {width() + m.left() + m.right(), height() + m.top() + m.bottom()}; }
81 [[nodiscard]] constexpr QSize shrunkBy(QMargins m) const noexcept
82 { return {width() - m.left() - m.right(), height() - m.top() - m.bottom()}; }
83
84 constexpr inline int &rwidth() noexcept;
85 constexpr inline int &rheight() noexcept;
86
87 constexpr inline QSize &operator+=(const QSize &) noexcept;
88 constexpr inline QSize &operator-=(const QSize &) noexcept;
89 constexpr inline QSize &operator*=(qreal c) noexcept;
90 inline QSize &operator/=(qreal c);
91
92 friend inline constexpr bool operator==(const QSize &s1, const QSize &s2) noexcept
93 { return s1.wd == s2.wd && s1.ht == s2.ht; }
94 friend inline constexpr bool operator!=(const QSize &s1, const QSize &s2) noexcept
95 { return s1.wd != s2.wd || s1.ht != s2.ht; }
96 friend inline constexpr QSize operator+(const QSize &s1, const QSize &s2) noexcept
97 { return QSize(s1.wd + s2.wd, s1.ht + s2.ht); }
98 friend inline constexpr QSize operator-(const QSize &s1, const QSize &s2) noexcept
99 { return QSize(s1.wd - s2.wd, s1.ht - s2.ht); }
100 friend inline constexpr QSize operator*(const QSize &s, qreal c) noexcept
101 { return QSize(qRound(s.wd * c), qRound(s.ht * c)); }
102 friend inline constexpr QSize operator*(qreal c, const QSize &s) noexcept
103 { return s * c; }
104 friend inline QSize operator/(const QSize &s, qreal c)
105 { Q_ASSERT(!qFuzzyIsNull(c)); return QSize(qRound(s.wd / c), qRound(s.ht / c)); }
106 friend inline constexpr size_t qHash(const QSize &, size_t) noexcept;
107
108#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
109 [[nodiscard]] CGSize toCGSize() const noexcept;
110#endif
111
112private:
113 int wd;
114 int ht;
115
116 template <std::size_t I,
117 typename S,
118 std::enable_if_t<(I < 2), bool> = true,
119 std::enable_if_t<std::is_same_v<std::decay_t<S>, QSize>, bool> = true>
120 friend constexpr decltype(auto) get(S &&s) noexcept
121 {
122 if constexpr (I == 0)
123 return (std::forward<S>(s).wd);
124 else if constexpr (I == 1)
125 return (std::forward<S>(s).ht);
126 }
127};
128Q_DECLARE_TYPEINFO(QSize, Q_RELOCATABLE_TYPE);
129
130/*****************************************************************************
131 QSize stream functions
132 *****************************************************************************/
133
134#ifndef QT_NO_DATASTREAM
135Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSize &);
136Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSize &);
137#endif
138
139
140/*****************************************************************************
141 QSize inline functions
142 *****************************************************************************/
143
144constexpr inline QSize::QSize() noexcept : wd(-1), ht(-1) {}
145
146constexpr inline QSize::QSize(int w, int h) noexcept : wd(w), ht(h) {}
147
148constexpr inline bool QSize::isNull() const noexcept
149{ return wd == 0 && ht == 0; }
150
151constexpr inline bool QSize::isEmpty() const noexcept
152{ return wd < 1 || ht < 1; }
153
154constexpr inline bool QSize::isValid() const noexcept
155{ return wd >= 0 && ht >= 0; }
156
157constexpr inline int QSize::width() const noexcept
158{ return wd; }
159
160constexpr inline int QSize::height() const noexcept
161{ return ht; }
162
163constexpr inline void QSize::setWidth(int w) noexcept
164{ wd = w; }
165
166constexpr inline void QSize::setHeight(int h) noexcept
167{ ht = h; }
168
169constexpr inline QSize QSize::transposed() const noexcept
170{ return QSize(ht, wd); }
171
172inline void QSize::scale(int w, int h, Qt::AspectRatioMode mode) noexcept
173{ scale(QSize(w, h), mode); }
174
175inline void QSize::scale(const QSize &s, Qt::AspectRatioMode mode) noexcept
176{ *this = scaled(s, mode); }
177
178inline QSize QSize::scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept
179{ return scaled(QSize(w, h), mode); }
180
181constexpr inline int &QSize::rwidth() noexcept
182{ return wd; }
183
184constexpr inline int &QSize::rheight() noexcept
185{ return ht; }
186
187constexpr inline QSize &QSize::operator+=(const QSize &s) noexcept
188{
189 wd += s.wd;
190 ht += s.ht;
191 return *this;
192}
193
194constexpr inline QSize &QSize::operator-=(const QSize &s) noexcept
195{
196 wd -= s.wd;
197 ht -= s.ht;
198 return *this;
199}
200
201constexpr inline QSize &QSize::operator*=(qreal c) noexcept
202{
203 wd = qRound(wd * c);
204 ht = qRound(ht * c);
205 return *this;
206}
207
208constexpr inline size_t qHash(const QSize &s, size_t seed = 0) noexcept
209{ return qHashMulti(seed, s.wd, s.ht); }
210
211inline QSize &QSize::operator/=(qreal c)
212{
213 Q_ASSERT(!qFuzzyIsNull(c));
214 wd = qRound(wd / c);
215 ht = qRound(ht / c);
216 return *this;
217}
218
219constexpr inline QSize QSize::expandedTo(const QSize & otherSize) const noexcept
220{
221 return QSize(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht));
222}
223
224constexpr inline QSize QSize::boundedTo(const QSize & otherSize) const noexcept
225{
226 return QSize(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht));
227}
228
229#ifndef QT_NO_DEBUG_STREAM
230Q_CORE_EXPORT QDebug operator<<(QDebug, const QSize &);
231#endif
232
233
234class Q_CORE_EXPORT QSizeF
235{
236public:
237 constexpr QSizeF() noexcept;
238 constexpr QSizeF(const QSize &sz) noexcept;
239 constexpr QSizeF(qreal w, qreal h) noexcept;
240
241 inline bool isNull() const noexcept;
242 constexpr inline bool isEmpty() const noexcept;
243 constexpr inline bool isValid() const noexcept;
244
245 constexpr inline qreal width() const noexcept;
246 constexpr inline qreal height() const noexcept;
247 constexpr inline void setWidth(qreal w) noexcept;
248 constexpr inline void setHeight(qreal h) noexcept;
249 void transpose() noexcept;
250 [[nodiscard]] constexpr inline QSizeF transposed() const noexcept;
251
252 inline void scale(qreal w, qreal h, Qt::AspectRatioMode mode) noexcept;
253 inline void scale(const QSizeF &s, Qt::AspectRatioMode mode) noexcept;
254 [[nodiscard]] QSizeF scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const noexcept;
255 [[nodiscard]] QSizeF scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept;
256
257 [[nodiscard]] constexpr inline QSizeF expandedTo(const QSizeF &) const noexcept;
258 [[nodiscard]] constexpr inline QSizeF boundedTo(const QSizeF &) const noexcept;
259
260 [[nodiscard]] constexpr QSizeF grownBy(QMarginsF m) const noexcept
261 { return {width() + m.left() + m.right(), height() + m.top() + m.bottom()}; }
262 [[nodiscard]] constexpr QSizeF shrunkBy(QMarginsF m) const noexcept
263 { return {width() - m.left() - m.right(), height() - m.top() - m.bottom()}; }
264
265 constexpr inline qreal &rwidth() noexcept;
266 constexpr inline qreal &rheight() noexcept;
267
268 constexpr inline QSizeF &operator+=(const QSizeF &) noexcept;
269 constexpr inline QSizeF &operator-=(const QSizeF &) noexcept;
270 constexpr inline QSizeF &operator*=(qreal c) noexcept;
271 inline QSizeF &operator/=(qreal c);
272
273 QT_WARNING_PUSH
274 QT_WARNING_DISABLE_FLOAT_COMPARE
275 friend constexpr inline bool operator==(const QSizeF &s1, const QSizeF &s2)
276 {
277 return ((!s1.wd || !s2.wd) ? qFuzzyIsNull(s1.wd - s2.wd) : qFuzzyCompare(s1.wd, s2.wd))
278 && ((!s1.ht || !s2.ht) ? qFuzzyIsNull(s1.ht - s2.ht) : qFuzzyCompare(s1.ht, s2.ht));
279 }
280 QT_WARNING_POP
281 friend constexpr inline bool operator!=(const QSizeF &s1, const QSizeF &s2)
282 { return !(s1 == s2); }
283 friend constexpr inline QSizeF operator+(const QSizeF &s1, const QSizeF &s2) noexcept
284 { return QSizeF(s1.wd + s2.wd, s1.ht + s2.ht); }
285 friend constexpr inline QSizeF operator-(const QSizeF &s1, const QSizeF &s2) noexcept
286 { return QSizeF(s1.wd - s2.wd, s1.ht - s2.ht); }
287 friend constexpr inline QSizeF operator*(const QSizeF &s, qreal c) noexcept
288 { return QSizeF(s.wd * c, s.ht * c); }
289 friend constexpr inline QSizeF operator*(qreal c, const QSizeF &s) noexcept
290 { return s * c; }
291 friend inline QSizeF operator/(const QSizeF &s, qreal c)
292 { Q_ASSERT(!qFuzzyIsNull(c)); return QSizeF(s.wd / c, s.ht / c); }
293
294 constexpr inline QSize toSize() const noexcept;
295
296#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
297 [[nodiscard]] static QSizeF fromCGSize(CGSize size) noexcept;
298 [[nodiscard]] CGSize toCGSize() const noexcept;
299#endif
300
301private:
302 qreal wd;
303 qreal ht;
304
305 template <std::size_t I,
306 typename S,
307 std::enable_if_t<(I < 2), bool> = true,
308 std::enable_if_t<std::is_same_v<std::decay_t<S>, QSizeF>, bool> = true>
309 friend constexpr decltype(auto) get(S &&s) noexcept
310 {
311 if constexpr (I == 0)
312 return (std::forward<S>(s).wd);
313 else if constexpr (I == 1)
314 return (std::forward<S>(s).ht);
315 }
316};
317Q_DECLARE_TYPEINFO(QSizeF, Q_RELOCATABLE_TYPE);
318
319
320/*****************************************************************************
321 QSizeF stream functions
322 *****************************************************************************/
323
324#ifndef QT_NO_DATASTREAM
325Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSizeF &);
326Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSizeF &);
327#endif
328
329
330/*****************************************************************************
331 QSizeF inline functions
332 *****************************************************************************/
333
334constexpr inline QSizeF::QSizeF() noexcept : wd(-1.), ht(-1.) {}
335
336constexpr inline QSizeF::QSizeF(const QSize &sz) noexcept : wd(sz.width()), ht(sz.height()) {}
337
338constexpr inline QSizeF::QSizeF(qreal w, qreal h) noexcept : wd(w), ht(h) {}
339
340inline bool QSizeF::isNull() const noexcept
341{ return qIsNull(wd) && qIsNull(ht); }
342
343constexpr inline bool QSizeF::isEmpty() const noexcept
344{ return wd <= 0. || ht <= 0.; }
345
346constexpr inline bool QSizeF::isValid() const noexcept
347{ return wd >= 0. && ht >= 0.; }
348
349constexpr inline qreal QSizeF::width() const noexcept
350{ return wd; }
351
352constexpr inline qreal QSizeF::height() const noexcept
353{ return ht; }
354
355constexpr inline void QSizeF::setWidth(qreal w) noexcept
356{ wd = w; }
357
358constexpr inline void QSizeF::setHeight(qreal h) noexcept
359{ ht = h; }
360
361constexpr inline QSizeF QSizeF::transposed() const noexcept
362{ return QSizeF(ht, wd); }
363
364inline void QSizeF::scale(qreal w, qreal h, Qt::AspectRatioMode mode) noexcept
365{ scale(QSizeF(w, h), mode); }
366
367inline void QSizeF::scale(const QSizeF &s, Qt::AspectRatioMode mode) noexcept
368{ *this = scaled(s, mode); }
369
370inline QSizeF QSizeF::scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const noexcept
371{ return scaled(QSizeF(w, h), mode); }
372
373constexpr inline qreal &QSizeF::rwidth() noexcept
374{ return wd; }
375
376constexpr inline qreal &QSizeF::rheight() noexcept
377{ return ht; }
378
379constexpr inline QSizeF &QSizeF::operator+=(const QSizeF &s) noexcept
380{
381 wd += s.wd;
382 ht += s.ht;
383 return *this;
384}
385
386constexpr inline QSizeF &QSizeF::operator-=(const QSizeF &s) noexcept
387{
388 wd -= s.wd;
389 ht -= s.ht;
390 return *this;
391}
392
393constexpr inline QSizeF &QSizeF::operator*=(qreal c) noexcept
394{
395 wd *= c;
396 ht *= c;
397 return *this;
398}
399
400inline QSizeF &QSizeF::operator/=(qreal c)
401{
402 Q_ASSERT(!qFuzzyIsNull(c) && qIsFinite(c));
403 wd = wd / c;
404 ht = ht / c;
405 return *this;
406}
407
408constexpr inline QSizeF QSizeF::expandedTo(const QSizeF &otherSize) const noexcept
409{
410 return QSizeF(qMax(wd, otherSize.wd), qMax(ht, otherSize.ht));
411}
412
413constexpr inline QSizeF QSizeF::boundedTo(const QSizeF &otherSize) const noexcept
414{
415 return QSizeF(qMin(wd, otherSize.wd), qMin(ht, otherSize.ht));
416}
417
418constexpr inline QSize QSizeF::toSize() const noexcept
419{
420 return QSize(qRound(wd), qRound(ht));
421}
422
423#ifndef QT_NO_DEBUG_STREAM
424Q_CORE_EXPORT QDebug operator<<(QDebug, const QSizeF &);
425#endif
426
427QT_END_NAMESPACE
428
429/*****************************************************************************
430 QSize/QSizeF tuple protocol
431 *****************************************************************************/
432
433namespace std {
434 template <>
435 class tuple_size<QT_PREPEND_NAMESPACE(QSize)> : public integral_constant<size_t, 2> {};
436 template <>
437 class tuple_element<0, QT_PREPEND_NAMESPACE(QSize)> { public: using type = int; };
438 template <>
439 class tuple_element<1, QT_PREPEND_NAMESPACE(QSize)> { public: using type = int; };
440
441 template <>
442 class tuple_size<QT_PREPEND_NAMESPACE(QSizeF)> : public integral_constant<size_t, 2> {};
443 template <>
444 class tuple_element<0, QT_PREPEND_NAMESPACE(QSizeF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
445 template <>
446 class tuple_element<1, QT_PREPEND_NAMESPACE(QSizeF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); };
447}
448
449#endif // QSIZE_H
450