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

source code of qtbase/src/corelib/tools/qsize.h