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 QPOINT_H |
5 | #define QPOINT_H |
6 | |
7 | #include <QtCore/qnamespace.h> |
8 | |
9 | #include <QtCore/q20type_traits.h> |
10 | #include <QtCore/q23utility.h> |
11 | |
12 | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
13 | struct CGPoint; |
14 | #endif |
15 | |
16 | QT_BEGIN_NAMESPACE |
17 | |
18 | QT_ENABLE_P0846_SEMANTICS_FOR(get) |
19 | |
20 | class QPointF; |
21 | |
22 | class QPoint |
23 | { |
24 | public: |
25 | constexpr QPoint() noexcept; |
26 | constexpr QPoint(int xpos, int ypos) noexcept; |
27 | |
28 | constexpr inline bool isNull() const noexcept; |
29 | |
30 | constexpr inline int x() const noexcept; |
31 | constexpr inline int y() const noexcept; |
32 | constexpr inline void setX(int x) noexcept; |
33 | constexpr inline void setY(int y) noexcept; |
34 | |
35 | constexpr inline int manhattanLength() const; |
36 | |
37 | constexpr QPoint transposed() const noexcept { return {yp, xp}; } |
38 | |
39 | constexpr inline int &rx() noexcept; |
40 | constexpr inline int &ry() noexcept; |
41 | |
42 | constexpr inline QPoint &operator+=(const QPoint &p); |
43 | constexpr inline QPoint &operator-=(const QPoint &p); |
44 | |
45 | constexpr inline QPoint &operator*=(float factor); |
46 | constexpr inline QPoint &operator*=(double factor); |
47 | constexpr inline QPoint &operator*=(int factor); |
48 | |
49 | constexpr inline QPoint &operator/=(qreal divisor); |
50 | |
51 | constexpr static inline int dotProduct(const QPoint &p1, const QPoint &p2) |
52 | { return p1.xp * p2.xp + p1.yp * p2.yp; } |
53 | |
54 | friend constexpr inline bool operator==(const QPoint &p1, const QPoint &p2) noexcept |
55 | { return p1.xp == p2.xp && p1.yp == p2.yp; } |
56 | friend constexpr inline bool operator!=(const QPoint &p1, const QPoint &p2) noexcept |
57 | { return p1.xp != p2.xp || p1.yp != p2.yp; } |
58 | friend constexpr inline QPoint operator+(const QPoint &p1, const QPoint &p2) noexcept |
59 | { return QPoint(p1.xp + p2.xp, p1.yp + p2.yp); } |
60 | friend constexpr inline QPoint operator-(const QPoint &p1, const QPoint &p2) noexcept |
61 | { return QPoint(p1.xp - p2.xp, p1.yp - p2.yp); } |
62 | friend constexpr inline QPoint operator*(const QPoint &p, float factor) |
63 | { return QPoint(qRound(f: p.xp * factor), qRound(f: p.yp * factor)); } |
64 | friend constexpr inline QPoint operator*(const QPoint &p, double factor) |
65 | { return QPoint(qRound(d: p.xp * factor), qRound(d: p.yp * factor)); } |
66 | friend constexpr inline QPoint operator*(const QPoint &p, int factor) noexcept |
67 | { return QPoint(p.xp * factor, p.yp * factor); } |
68 | friend constexpr inline QPoint operator*(float factor, const QPoint &p) |
69 | { return QPoint(qRound(f: p.xp * factor), qRound(f: p.yp * factor)); } |
70 | friend constexpr inline QPoint operator*(double factor, const QPoint &p) |
71 | { return QPoint(qRound(d: p.xp * factor), qRound(d: p.yp * factor)); } |
72 | friend constexpr inline QPoint operator*(int factor, const QPoint &p) noexcept |
73 | { return QPoint(p.xp * factor, p.yp * factor); } |
74 | friend constexpr inline QPoint operator+(const QPoint &p) noexcept |
75 | { return p; } |
76 | friend constexpr inline QPoint operator-(const QPoint &p) noexcept |
77 | { return QPoint(-p.xp, -p.yp); } |
78 | friend constexpr inline QPoint operator/(const QPoint &p, qreal c) |
79 | { return QPoint(qRound(d: p.xp / c), qRound(d: p.yp / c)); } |
80 | |
81 | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
82 | [[nodiscard]] Q_CORE_EXPORT CGPoint toCGPoint() const noexcept; |
83 | #endif |
84 | [[nodiscard]] constexpr inline QPointF toPointF() const noexcept; |
85 | |
86 | private: |
87 | friend class QTransform; |
88 | int xp; |
89 | int yp; |
90 | |
91 | template <std::size_t I, |
92 | typename P, |
93 | std::enable_if_t<(I < 2), bool> = true, |
94 | std::enable_if_t<std::is_same_v<q20::remove_cvref_t<P>, QPoint>, bool> = true> |
95 | friend constexpr decltype(auto) get(P &&p) noexcept |
96 | { |
97 | if constexpr (I == 0) |
98 | return q23::forward_like<P>(p.xp); |
99 | else if constexpr (I == 1) |
100 | return q23::forward_like<P>(p.yp); |
101 | } |
102 | }; |
103 | |
104 | Q_DECLARE_TYPEINFO(QPoint, Q_PRIMITIVE_TYPE); |
105 | |
106 | /***************************************************************************** |
107 | QPoint stream functions |
108 | *****************************************************************************/ |
109 | #ifndef QT_NO_DATASTREAM |
110 | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QPoint &); |
111 | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QPoint &); |
112 | #endif |
113 | |
114 | /***************************************************************************** |
115 | QPoint inline functions |
116 | *****************************************************************************/ |
117 | |
118 | constexpr inline QPoint::QPoint() noexcept : xp(0), yp(0) {} |
119 | |
120 | constexpr inline QPoint::QPoint(int xpos, int ypos) noexcept : xp(xpos), yp(ypos) {} |
121 | |
122 | constexpr inline bool QPoint::isNull() const noexcept |
123 | { |
124 | return xp == 0 && yp == 0; |
125 | } |
126 | |
127 | constexpr inline int QPoint::x() const noexcept |
128 | { |
129 | return xp; |
130 | } |
131 | |
132 | constexpr inline int QPoint::y() const noexcept |
133 | { |
134 | return yp; |
135 | } |
136 | |
137 | constexpr inline void QPoint::setX(int xpos) noexcept |
138 | { |
139 | xp = xpos; |
140 | } |
141 | |
142 | constexpr inline void QPoint::setY(int ypos) noexcept |
143 | { |
144 | yp = ypos; |
145 | } |
146 | |
147 | inline int constexpr QPoint::manhattanLength() const |
148 | { |
149 | return qAbs(t: x()) + qAbs(t: y()); |
150 | } |
151 | |
152 | constexpr inline int &QPoint::rx() noexcept |
153 | { |
154 | return xp; |
155 | } |
156 | |
157 | constexpr inline int &QPoint::ry() noexcept |
158 | { |
159 | return yp; |
160 | } |
161 | |
162 | constexpr inline QPoint &QPoint::operator+=(const QPoint &p) |
163 | { |
164 | xp += p.xp; |
165 | yp += p.yp; |
166 | return *this; |
167 | } |
168 | |
169 | constexpr inline QPoint &QPoint::operator-=(const QPoint &p) |
170 | { |
171 | xp -= p.xp; |
172 | yp -= p.yp; |
173 | return *this; |
174 | } |
175 | |
176 | constexpr inline QPoint &QPoint::operator*=(float factor) |
177 | { |
178 | xp = qRound(f: xp * factor); |
179 | yp = qRound(f: yp * factor); |
180 | return *this; |
181 | } |
182 | |
183 | constexpr inline QPoint &QPoint::operator*=(double factor) |
184 | { |
185 | xp = qRound(d: xp * factor); |
186 | yp = qRound(d: yp * factor); |
187 | return *this; |
188 | } |
189 | |
190 | constexpr inline QPoint &QPoint::operator*=(int factor) |
191 | { |
192 | xp = xp * factor; |
193 | yp = yp * factor; |
194 | return *this; |
195 | } |
196 | |
197 | constexpr inline QPoint &QPoint::operator/=(qreal c) |
198 | { |
199 | xp = qRound(d: xp / c); |
200 | yp = qRound(d: yp / c); |
201 | return *this; |
202 | } |
203 | |
204 | #ifndef QT_NO_DEBUG_STREAM |
205 | Q_CORE_EXPORT QDebug operator<<(QDebug, const QPoint &); |
206 | #endif |
207 | |
208 | Q_CORE_EXPORT size_t qHash(QPoint key, size_t seed = 0) noexcept; |
209 | |
210 | |
211 | |
212 | |
213 | class QPointF |
214 | { |
215 | public: |
216 | constexpr QPointF() noexcept; |
217 | constexpr QPointF(const QPoint &p) noexcept; |
218 | constexpr QPointF(qreal xpos, qreal ypos) noexcept; |
219 | |
220 | constexpr inline qreal manhattanLength() const; |
221 | |
222 | inline bool isNull() const noexcept; |
223 | |
224 | constexpr inline qreal x() const noexcept; |
225 | constexpr inline qreal y() const noexcept; |
226 | constexpr inline void setX(qreal x) noexcept; |
227 | constexpr inline void setY(qreal y) noexcept; |
228 | |
229 | constexpr QPointF transposed() const noexcept { return {yp, xp}; } |
230 | |
231 | constexpr inline qreal &rx() noexcept; |
232 | constexpr inline qreal &ry() noexcept; |
233 | |
234 | constexpr inline QPointF &operator+=(const QPointF &p); |
235 | constexpr inline QPointF &operator-=(const QPointF &p); |
236 | constexpr inline QPointF &operator*=(qreal c); |
237 | constexpr inline QPointF &operator/=(qreal c); |
238 | |
239 | constexpr static inline qreal dotProduct(const QPointF &p1, const QPointF &p2) |
240 | { |
241 | return p1.xp * p2.xp + p1.yp * p2.yp; |
242 | } |
243 | |
244 | QT_WARNING_PUSH |
245 | QT_WARNING_DISABLE_FLOAT_COMPARE |
246 | friend constexpr inline bool operator==(const QPointF &p1, const QPointF &p2) |
247 | { |
248 | return ((!p1.xp || !p2.xp) ? qFuzzyIsNull(d: p1.xp - p2.xp) : qFuzzyCompare(p1: p1.xp, p2: p2.xp)) |
249 | && ((!p1.yp || !p2.yp) ? qFuzzyIsNull(d: p1.yp - p2.yp) : qFuzzyCompare(p1: p1.yp, p2: p2.yp)); |
250 | } |
251 | friend constexpr inline bool operator!=(const QPointF &p1, const QPointF &p2) |
252 | { |
253 | return !(p1 == p2); |
254 | } |
255 | QT_WARNING_POP |
256 | |
257 | friend constexpr inline QPointF operator+(const QPointF &p1, const QPointF &p2) |
258 | { return QPointF(p1.xp + p2.xp, p1.yp + p2.yp); } |
259 | friend constexpr inline QPointF operator-(const QPointF &p1, const QPointF &p2) |
260 | { return QPointF(p1.xp - p2.xp, p1.yp - p2.yp); } |
261 | friend constexpr inline QPointF operator*(const QPointF &p, qreal c) |
262 | { return QPointF(p.xp * c, p.yp * c); } |
263 | friend constexpr inline QPointF operator*(qreal c, const QPointF &p) |
264 | { return QPointF(p.xp * c, p.yp * c); } |
265 | friend constexpr inline QPointF operator+(const QPointF &p) |
266 | { return p; } |
267 | friend constexpr inline QPointF operator-(const QPointF &p) |
268 | { return QPointF(-p.xp, -p.yp); } |
269 | friend constexpr inline QPointF operator/(const QPointF &p, qreal divisor) |
270 | { |
271 | Q_ASSERT(divisor < 0 || divisor > 0); |
272 | return QPointF(p.xp / divisor, p.yp / divisor); |
273 | } |
274 | |
275 | constexpr QPoint toPoint() const; |
276 | |
277 | #if defined(Q_OS_DARWIN) || defined(Q_QDOC) |
278 | [[nodiscard]] Q_CORE_EXPORT static QPointF fromCGPoint(CGPoint point) noexcept; |
279 | [[nodiscard]] Q_CORE_EXPORT CGPoint toCGPoint() const noexcept; |
280 | #endif |
281 | |
282 | private: |
283 | friend class QTransform; |
284 | |
285 | qreal xp; |
286 | qreal yp; |
287 | |
288 | template <std::size_t I, |
289 | typename P, |
290 | std::enable_if_t<(I < 2), bool> = true, |
291 | std::enable_if_t<std::is_same_v<q20::remove_cvref_t<P>, QPointF>, bool> = true> |
292 | friend constexpr decltype(auto) get(P &&p) noexcept |
293 | { |
294 | if constexpr (I == 0) |
295 | return q23::forward_like<P>(p.xp); |
296 | else if constexpr (I == 1) |
297 | return q23::forward_like<P>(p.yp); |
298 | } |
299 | }; |
300 | |
301 | Q_DECLARE_TYPEINFO(QPointF, Q_PRIMITIVE_TYPE); |
302 | |
303 | size_t qHash(QPointF, size_t seed = 0) = delete; |
304 | |
305 | /***************************************************************************** |
306 | QPointF stream functions |
307 | *****************************************************************************/ |
308 | #ifndef QT_NO_DATASTREAM |
309 | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QPointF &); |
310 | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QPointF &); |
311 | #endif |
312 | |
313 | /***************************************************************************** |
314 | QPointF inline functions |
315 | *****************************************************************************/ |
316 | |
317 | constexpr inline QPointF::QPointF() noexcept : xp(0), yp(0) { } |
318 | |
319 | constexpr inline QPointF::QPointF(qreal xpos, qreal ypos) noexcept : xp(xpos), yp(ypos) { } |
320 | |
321 | constexpr inline QPointF::QPointF(const QPoint &p) noexcept : xp(p.x()), yp(p.y()) { } |
322 | |
323 | constexpr inline qreal QPointF::manhattanLength() const |
324 | { |
325 | return qAbs(t: x()) + qAbs(t: y()); |
326 | } |
327 | |
328 | inline bool QPointF::isNull() const noexcept |
329 | { |
330 | return qIsNull(d: xp) && qIsNull(d: yp); |
331 | } |
332 | |
333 | constexpr inline qreal QPointF::x() const noexcept |
334 | { |
335 | return xp; |
336 | } |
337 | |
338 | constexpr inline qreal QPointF::y() const noexcept |
339 | { |
340 | return yp; |
341 | } |
342 | |
343 | constexpr inline void QPointF::setX(qreal xpos) noexcept |
344 | { |
345 | xp = xpos; |
346 | } |
347 | |
348 | constexpr inline void QPointF::setY(qreal ypos) noexcept |
349 | { |
350 | yp = ypos; |
351 | } |
352 | |
353 | constexpr inline qreal &QPointF::rx() noexcept |
354 | { |
355 | return xp; |
356 | } |
357 | |
358 | constexpr inline qreal &QPointF::ry() noexcept |
359 | { |
360 | return yp; |
361 | } |
362 | |
363 | constexpr inline QPointF &QPointF::operator+=(const QPointF &p) |
364 | { |
365 | xp += p.xp; |
366 | yp += p.yp; |
367 | return *this; |
368 | } |
369 | |
370 | constexpr inline QPointF &QPointF::operator-=(const QPointF &p) |
371 | { |
372 | xp -= p.xp; |
373 | yp -= p.yp; |
374 | return *this; |
375 | } |
376 | |
377 | constexpr inline QPointF &QPointF::operator*=(qreal c) |
378 | { |
379 | xp *= c; |
380 | yp *= c; |
381 | return *this; |
382 | } |
383 | |
384 | constexpr inline QPointF &QPointF::operator/=(qreal divisor) |
385 | { |
386 | Q_ASSERT(divisor > 0 || divisor < 0); |
387 | xp /= divisor; |
388 | yp /= divisor; |
389 | return *this; |
390 | } |
391 | |
392 | constexpr QPointF QPoint::toPointF() const noexcept { return *this; } |
393 | |
394 | constexpr inline QPoint QPointF::toPoint() const |
395 | { |
396 | return QPoint(qRound(d: xp), qRound(d: yp)); |
397 | } |
398 | |
399 | #ifndef QT_NO_DEBUG_STREAM |
400 | Q_CORE_EXPORT QDebug operator<<(QDebug d, const QPointF &p); |
401 | #endif |
402 | |
403 | QT_END_NAMESPACE |
404 | |
405 | /***************************************************************************** |
406 | QPoint/QPointF tuple protocol |
407 | *****************************************************************************/ |
408 | |
409 | namespace std { |
410 | template <> |
411 | class tuple_size<QT_PREPEND_NAMESPACE(QPoint)> : public integral_constant<size_t, 2> {}; |
412 | template <> |
413 | class tuple_element<0, QT_PREPEND_NAMESPACE(QPoint)> { public: using type = int; }; |
414 | template <> |
415 | class tuple_element<1, QT_PREPEND_NAMESPACE(QPoint)> { public: using type = int; }; |
416 | |
417 | template <> |
418 | class tuple_size<QT_PREPEND_NAMESPACE(QPointF)> : public integral_constant<size_t, 2> {}; |
419 | template <> |
420 | class tuple_element<0, QT_PREPEND_NAMESPACE(QPointF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); }; |
421 | template <> |
422 | class tuple_element<1, QT_PREPEND_NAMESPACE(QPointF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); }; |
423 | } |
424 | |
425 | #endif // QPOINT_H |
426 | |