Coverage Report

Created: 2026-02-10 07:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/painting/qtransform.h
Line
Count
Source
1
// Copyright (C) 2016 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
#ifndef QTRANSFORM_H
4
#define QTRANSFORM_H
5
6
#include <QtGui/qtguiglobal.h>
7
#include <QtGui/qpolygon.h>
8
#include <QtGui/qregion.h>
9
#include <QtGui/qwindowdefs.h>
10
#include <QtCore/qline.h>
11
#include <QtCore/qpoint.h>
12
#include <QtCore/qrect.h>
13
14
QT_BEGIN_NAMESPACE
15
16
class QVariant;
17
class QPainterPath;
18
19
class Q_GUI_EXPORT QTransform
20
{
21
public:
22
    enum TransformationType {
23
        TxNone      = 0x00,
24
        TxTranslate = 0x01,
25
        TxScale     = 0x02,
26
        TxRotate    = 0x04,
27
        TxShear     = 0x08,
28
        TxProject   = 0x10
29
    };
30
31
0
    inline explicit QTransform(Qt::Initialization) {}
32
    inline QTransform()
33
        : m_matrix{ {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }
34
        , m_type(TxNone)
35
0
        , m_dirty(TxNone) {}
36
    QTransform(qreal h11, qreal h12, qreal h13,
37
               qreal h21, qreal h22, qreal h23,
38
               qreal h31, qreal h32, qreal h33)
39
        : m_matrix{ {h11, h12, h13}, {h21, h22, h23}, {h31, h32, h33} }
40
        , m_type(TxNone)
41
0
        , m_dirty(TxProject) {}
42
    QTransform(qreal h11, qreal h12, qreal h21,
43
               qreal h22, qreal dx, qreal dy)
44
        : m_matrix{ {h11, h12, 0}, {h21, h22, 0}, {dx, dy, 1} }
45
        , m_type(TxNone)
46
0
        , m_dirty(TxShear) {}
47
48
    QTransform &operator=(QTransform &&other) noexcept = default;
49
    QTransform &operator=(const QTransform &) noexcept = default;
50
    QTransform(QTransform &&other) noexcept = default;
51
    QTransform(const QTransform &other) noexcept = default;
52
53
    bool isAffine() const;
54
    bool isIdentity() const;
55
    bool isInvertible() const;
56
    bool isScaling() const;
57
    bool isRotating() const;
58
    bool isTranslating() const;
59
60
    TransformationType type() const;
61
62
    inline qreal determinant() const;
63
64
    qreal m11() const;
65
    qreal m12() const;
66
    qreal m13() const;
67
    qreal m21() const;
68
    qreal m22() const;
69
    qreal m23() const;
70
    qreal m31() const;
71
    qreal m32() const;
72
    qreal m33() const;
73
    qreal dx() const;
74
    qreal dy() const;
75
76
    void setMatrix(qreal m11, qreal m12, qreal m13,
77
                   qreal m21, qreal m22, qreal m23,
78
                   qreal m31, qreal m32, qreal m33);
79
80
    [[nodiscard]] QTransform inverted(bool *invertible = nullptr) const;
81
    [[nodiscard]] QTransform adjoint() const;
82
    [[nodiscard]] QTransform transposed() const;
83
84
    QTransform &translate(qreal dx, qreal dy);
85
    QTransform &scale(qreal sx, qreal sy);
86
    QTransform &shear(qreal sh, qreal sv);
87
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
88
    QTransform &rotate(qreal a, Qt::Axis axis, qreal distanceToPlane);
89
    // ### Qt7: Remove
90
    QTransform &rotate(qreal a, Qt::Axis axis = Qt::ZAxis);
91
    QTransform &rotateRadians(qreal a, Qt::Axis axis, qreal distanceToPlane);
92
    // ### Qt7: Remove
93
    QTransform &rotateRadians(qreal a, Qt::Axis axis = Qt::ZAxis);
94
#else
95
    QTransform &rotate(qreal a, Qt::Axis axis = Qt::ZAxis, qreal distanceToPlane = 1024.0f);
96
    QTransform &rotateRadians(qreal a, Qt::Axis axis = Qt::ZAxis, qreal distanceToPlane = 1024.0f);
97
#endif
98
99
    static bool squareToQuad(const QPolygonF &square, QTransform &result);
100
    static bool quadToSquare(const QPolygonF &quad, QTransform &result);
101
    static bool quadToQuad(const QPolygonF &one,
102
                           const QPolygonF &two,
103
                           QTransform &result);
104
105
    bool operator==(const QTransform &) const;
106
    bool operator!=(const QTransform &) const;
107
108
    QTransform &operator*=(const QTransform &);
109
    QTransform operator*(const QTransform &o) const;
110
111
    operator QVariant() const;
112
113
    void reset();
114
    QPoint       map(const QPoint &p) const;
115
    QPointF      map(const QPointF &p) const;
116
    QLine        map(const QLine &l) const;
117
    QLineF       map(const QLineF &l) const;
118
    QPolygonF    map(const QPolygonF &a) const;
119
    QPolygon     map(const QPolygon &a) const;
120
    QRegion      map(const QRegion &r) const;
121
    QPainterPath map(const QPainterPath &p) const;
122
    QPolygon     mapToPolygon(const QRect &r) const;
123
    QRect mapRect(const QRect &) const;
124
    QRectF mapRect(const QRectF &) const;
125
    void map(int x, int y, int *tx, int *ty) const;
126
    void map(qreal x, qreal y, qreal *tx, qreal *ty) const;
127
128
    QTransform &operator*=(qreal div);
129
    QTransform &operator/=(qreal div);
130
    QTransform &operator+=(qreal div);
131
    QTransform &operator-=(qreal div);
132
133
    static QTransform fromTranslate(qreal dx, qreal dy);
134
    static QTransform fromScale(qreal dx, qreal dy);
135
136
private:
137
    struct Affine {
138
             qreal (& m_matrix)[3][3];
139
        };
140
141
public:
142
0
    auto asAffineMatrix() { return Affine { m_matrix }; }
143
    friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &s, Affine &m);
144
    friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &s, const Affine &m);
145
146
private:
147
    inline TransformationType inline_type() const;
148
    void do_map(qreal x, qreal y, qreal &nx, qreal &ny) const;
149
    qreal m_matrix[3][3];
150
151
    mutable uint m_type : 5;
152
    mutable uint m_dirty : 5;
153
};
154
Q_DECLARE_TYPEINFO(QTransform, Q_RELOCATABLE_TYPE);
155
156
Q_GUI_EXPORT Q_DECL_CONST_FUNCTION size_t qHash(const QTransform &key, size_t seed = 0) noexcept;
157
158
/******* inlines *****/
159
inline QTransform::TransformationType QTransform::inline_type() const
160
0
{
161
0
    if (m_dirty == TxNone)
162
0
        return static_cast<TransformationType>(m_type);
163
0
    return type();
164
0
}
165
166
inline bool QTransform::isAffine() const
167
0
{
168
0
    return inline_type() < TxProject;
169
0
}
170
inline bool QTransform::isIdentity() const
171
0
{
172
0
    return inline_type() == TxNone;
173
0
}
174
175
inline bool QTransform::isInvertible() const
176
0
{
177
0
    return !qFuzzyIsNull(determinant());
178
0
}
179
180
inline bool QTransform::isScaling() const
181
0
{
182
0
    return type() >= TxScale;
183
0
}
184
inline bool QTransform::isRotating() const
185
0
{
186
0
    return inline_type() >= TxRotate;
187
0
}
188
189
inline bool QTransform::isTranslating() const
190
0
{
191
0
    return inline_type() >= TxTranslate;
192
0
}
193
194
inline qreal QTransform::determinant() const
195
0
{
196
0
    return m_matrix[0][0] * (m_matrix[2][2] * m_matrix[1][1] - m_matrix[2][1] * m_matrix[1][2]) -
197
0
           m_matrix[1][0] * (m_matrix[2][2] * m_matrix[0][1] - m_matrix[2][1] * m_matrix[0][2]) +
198
0
           m_matrix[2][0] * (m_matrix[1][2] * m_matrix[0][1] - m_matrix[1][1] * m_matrix[0][2]);
199
0
}
200
inline qreal QTransform::m11() const
201
0
{
202
0
    return m_matrix[0][0];
203
0
}
204
inline qreal QTransform::m12() const
205
0
{
206
0
    return m_matrix[0][1];
207
0
}
208
inline qreal QTransform::m13() const
209
0
{
210
0
    return m_matrix[0][2];
211
0
}
212
inline qreal QTransform::m21() const
213
0
{
214
0
    return m_matrix[1][0];
215
0
}
216
inline qreal QTransform::m22() const
217
0
{
218
0
    return m_matrix[1][1];
219
0
}
220
inline qreal QTransform::m23() const
221
0
{
222
0
    return m_matrix[1][2];
223
0
}
224
inline qreal QTransform::m31() const
225
0
{
226
0
    return m_matrix[2][0];
227
0
}
228
inline qreal QTransform::m32() const
229
0
{
230
0
    return m_matrix[2][1];
231
0
}
232
inline qreal QTransform::m33() const
233
0
{
234
0
    return m_matrix[2][2];
235
0
}
236
inline qreal QTransform::dx() const
237
0
{
238
0
    return m_matrix[2][0];
239
0
}
240
inline qreal QTransform::dy() const
241
0
{
242
0
    return m_matrix[2][1];
243
0
}
244
245
QT_WARNING_PUSH
246
QT_WARNING_DISABLE_FLOAT_COMPARE
247
248
inline QTransform &QTransform::operator*=(qreal num)
249
0
{
250
0
    if (num == 1.)
251
0
        return *this;
252
0
    m_matrix[0][0] *= num;
253
0
    m_matrix[0][1] *= num;
254
0
    m_matrix[0][2] *= num;
255
0
    m_matrix[1][0] *= num;
256
0
    m_matrix[1][1] *= num;
257
0
    m_matrix[1][2] *= num;
258
0
    m_matrix[2][0] *= num;
259
0
    m_matrix[2][1] *= num;
260
0
    m_matrix[2][2] *= num;
261
0
    if (m_dirty < TxScale)
262
0
        m_dirty = TxScale;
263
0
    return *this;
264
0
}
265
inline QTransform &QTransform::operator/=(qreal div)
266
0
{
267
0
    if (div == 0)
268
0
        return *this;
269
0
    div = 1/div;
270
0
    return operator*=(div);
271
0
}
272
inline QTransform &QTransform::operator+=(qreal num)
273
0
{
274
0
    if (num == 0)
275
0
        return *this;
276
0
    m_matrix[0][0] += num;
277
0
    m_matrix[0][1] += num;
278
0
    m_matrix[0][2] += num;
279
0
    m_matrix[1][0] += num;
280
0
    m_matrix[1][1] += num;
281
0
    m_matrix[1][2] += num;
282
0
    m_matrix[2][0] += num;
283
0
    m_matrix[2][1] += num;
284
0
    m_matrix[2][2] += num;
285
0
    m_dirty     = TxProject;
286
0
    return *this;
287
0
}
288
inline QTransform &QTransform::operator-=(qreal num)
289
0
{
290
0
    if (num == 0)
291
0
        return *this;
292
0
    m_matrix[0][0] -= num;
293
0
    m_matrix[0][1] -= num;
294
0
    m_matrix[0][2] -= num;
295
0
    m_matrix[1][0] -= num;
296
0
    m_matrix[1][1] -= num;
297
0
    m_matrix[1][2] -= num;
298
0
    m_matrix[2][0] -= num;
299
0
    m_matrix[2][1] -= num;
300
0
    m_matrix[2][2] -= num;
301
0
    m_dirty     = TxProject;
302
0
    return *this;
303
0
}
304
305
QT_WARNING_POP
306
307
inline bool qFuzzyCompare(const QTransform& t1, const QTransform& t2) noexcept
308
0
{
309
0
    return qFuzzyCompare(t1.m11(), t2.m11())
310
0
        && qFuzzyCompare(t1.m12(), t2.m12())
311
0
        && qFuzzyCompare(t1.m13(), t2.m13())
312
0
        && qFuzzyCompare(t1.m21(), t2.m21())
313
0
        && qFuzzyCompare(t1.m22(), t2.m22())
314
0
        && qFuzzyCompare(t1.m23(), t2.m23())
315
0
        && qFuzzyCompare(t1.m31(), t2.m31())
316
0
        && qFuzzyCompare(t1.m32(), t2.m32())
317
0
        && qFuzzyCompare(t1.m33(), t2.m33());
318
0
}
319
320
321
/****** stream functions *******************/
322
#ifndef QT_NO_DATASTREAM
323
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTransform &);
324
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTransform &);
325
#endif
326
327
#ifndef QT_NO_DEBUG_STREAM
328
Q_GUI_EXPORT QDebug operator<<(QDebug, const QTransform &);
329
#endif
330
/****** end stream functions *******************/
331
332
// mathematical semantics
333
inline QPoint operator*(const QPoint &p, const QTransform &m)
334
0
{ return m.map(p); }
335
inline QPointF operator*(const QPointF &p, const QTransform &m)
336
0
{ return m.map(p); }
337
inline QLineF operator*(const QLineF &l, const QTransform &m)
338
0
{ return m.map(l); }
339
inline QLine operator*(const QLine &l, const QTransform &m)
340
0
{ return m.map(l); }
341
inline QPolygon operator *(const QPolygon &a, const QTransform &m)
342
0
{ return m.map(a); }
343
inline QPolygonF operator *(const QPolygonF &a, const QTransform &m)
344
0
{ return m.map(a); }
345
inline QRegion operator *(const QRegion &r, const QTransform &m)
346
0
{ return m.map(r); }
347
348
inline QTransform operator *(const QTransform &a, qreal n)
349
0
{ QTransform t(a); t *= n; return t; }
350
inline QTransform operator /(const QTransform &a, qreal n)
351
0
{ QTransform t(a); t /= n; return t; }
352
inline QTransform operator +(const QTransform &a, qreal n)
353
0
{ QTransform t(a); t += n; return t; }
354
inline QTransform operator -(const QTransform &a, qreal n)
355
0
{ QTransform t(a); t -= n; return t; }
356
357
QT_END_NAMESPACE
358
359
#endif // QTRANSFORM_H