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 test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31#include <qmatrix.h>
32#include <qmath.h>
33#include <qpolygon.h>
34
35#if QT_DEPRECATED_SINCE(5, 15)
36QT_WARNING_PUSH
37QT_WARNING_DISABLE_DEPRECATED
38
39class tst_QWMatrix : public QObject
40{
41 Q_OBJECT
42
43private slots:
44 void mapRect_data();
45 void mapToPolygon_data();
46 void mapRect();
47 void operator_star_qwmatrix();
48 void assignments();
49 void mapToPolygon();
50 void translate();
51 void scale();
52 void mapPolygon();
53
54private:
55 void mapping_data();
56};
57
58void tst_QWMatrix::mapRect_data()
59{
60 mapping_data();
61}
62
63void tst_QWMatrix::mapToPolygon_data()
64{
65 mapping_data();
66}
67
68void tst_QWMatrix::mapping_data()
69{
70 //create the testtable instance and define the elements
71 QTest::addColumn<QMatrix>(name: "matrix");
72 QTest::addColumn<QRect>(name: "src");
73 QTest::addColumn<QPolygon>(name: "res");
74
75 //next we fill it with data
76
77 // identity
78 QTest::newRow( dataTag: "identity" ) << QMatrix( 1, 0, 0, 1, 0, 0 )
79 << QRect( 10, 20, 30, 40 )
80 << QPolygon( QRect( 10, 20, 30, 40 ) );
81 // scaling
82 QTest::newRow( dataTag: "scale 0" ) << QMatrix( 2, 0, 0, 2, 0, 0 )
83 << QRect( 10, 20, 30, 40 )
84 << QPolygon( QRect( 20, 40, 60, 80 ) );
85 QTest::newRow( dataTag: "scale 1" ) << QMatrix( 10, 0, 0, 10, 0, 0 )
86 << QRect( 10, 20, 30, 40 )
87 << QPolygon( QRect( 100, 200, 300, 400 ) );
88 // mirroring
89 QTest::newRow( dataTag: "mirror 0" ) << QMatrix( -1, 0, 0, 1, 0, 0 )
90 << QRect( 10, 20, 30, 40 )
91 << QPolygon( QRect( -40, 20, 30, 40 ) );
92 QTest::newRow( dataTag: "mirror 1" ) << QMatrix( 1, 0, 0, -1, 0, 0 )
93 << QRect( 10, 20, 30, 40 )
94 << QPolygon( QRect( 10, -60, 30, 40 ) );
95 QTest::newRow( dataTag: "mirror 2" ) << QMatrix( -1, 0, 0, -1, 0, 0 )
96 << QRect( 10, 20, 30, 40 )
97 << QPolygon( QRect( -40, -60, 30, 40 ) );
98 QTest::newRow( dataTag: "mirror 3" ) << QMatrix( -2, 0, 0, -2, 0, 0 )
99 << QRect( 10, 20, 30, 40 )
100 << QPolygon( QRect( -80, -120, 60, 80 ) );
101 QTest::newRow( dataTag: "mirror 4" ) << QMatrix( -10, 0, 0, -10, 0, 0 )
102 << QRect( 10, 20, 30, 40 )
103 << QPolygon( QRect( -400, -600, 300, 400 ) );
104 QTest::newRow( dataTag: "mirror 5" ) << QMatrix( -1, 0, 0, 1, 0, 0 )
105 << QRect( 0, 0, 30, 40 )
106 << QPolygon( QRect( -30, 0, 30, 40 ) );
107 QTest::newRow( dataTag: "mirror 6" ) << QMatrix( 1, 0, 0, -1, 0, 0 )
108 << QRect( 0, 0, 30, 40 )
109 << QPolygon( QRect( 0, -40, 30, 40 ) );
110 QTest::newRow( dataTag: "mirror 7" ) << QMatrix( -1, 0, 0, -1, 0, 0 )
111 << QRect( 0, 0, 30, 40 )
112 << QPolygon( QRect( -30, -40, 30, 40 ) );
113 QTest::newRow( dataTag: "mirror 8" ) << QMatrix( -2, 0, 0, -2, 0, 0 )
114 << QRect( 0, 0, 30, 40 )
115 << QPolygon( QRect( -60, -80, 60, 80 ) );
116 QTest::newRow( dataTag: "mirror 9" ) << QMatrix( -10, 0, 0, -10, 0, 0 )
117 << QRect( 0, 0, 30, 40 )
118 << QPolygon( QRect( -300, -400, 300, 400 ) );
119
120 const auto rotate = [](qreal degrees) {
121 const qreal rad = qDegreesToRadians(degrees);
122 return QMatrix(std::cos(x: rad), -std::sin(x: rad),
123 std::sin(x: rad), std::cos(x: rad), 0, 0);
124 };
125
126 // rotations
127 QTest::newRow( dataTag: "rot 0 a" ) << rotate(0.)
128 << QRect( 0, 0, 30, 40 )
129 << QPolygon ( QRect( 0, 0, 30, 40 ) );
130 QTest::newRow( dataTag: "rot 0 b" ) << rotate(0.00001f)
131 << QRect( 0, 0, 30, 40 )
132 << QPolygon ( QRect( 0, 0, 30, 40 ) );
133 QTest::newRow( dataTag: "rot 0 c" ) << rotate(0.)
134 << QRect( 10, 20, 30, 40 )
135 << QPolygon ( QRect( 10, 20, 30, 40 ) );
136 QTest::newRow( dataTag: "rot 0 d" ) << rotate(0.00001f)
137 << QRect( 10, 20, 30, 40 )
138 << QPolygon ( QRect( 10, 20, 30, 40 ) );
139
140#if 0
141 const auto rotScale = [](qreal degrees, qreal scale) {
142 const qreal rad = qDegreesToRadians(degrees);
143 return QMatrix(scale * std::cos(rad), -scale * std::sin(rad),
144 scale * std::sin(rad), scale * std::cos(rad), 0, 0);
145 };
146 // rotations with scaling
147 QTest::newRow( "rotscale 90 a" ) << rotScale(90., 10)
148 << QRect( 0, 0, 30, 40 )
149 << QPolygon( QRect( 0, -299, 400, 300 ) );
150 QTest::newRow( "rotscale 90 b" ) << rotScale(90.00001, 10)
151 << QRect( 0, 0, 30, 40 )
152 << QPolygon( QRect( 0, -299, 400, 300 ) );
153 QTest::newRow( "rotscale 90 c" ) << rotScale(90., 10)
154 << QRect( 10, 20, 30, 40 )
155 << QPolygon( QRect( 200, -399, 400, 300 ) );
156 QTest::newRow( "rotscale 90 d" ) << rotScale(90.00001, 10)
157 << QRect( 10, 20, 30, 40 )
158 << QPolygon( QRect( 200, -399, 400, 300 ) );
159
160 QTest::newRow( "rotscale 180 a" ) << rotScale(180., 10)
161 << QRect( 0, 0, 30, 40 )
162 << QPolygon( QRect( -299, -399, 300, 400 ) );
163 QTest::newRow( "rotscale 180 b" ) << rotScale(180.000001, 10)
164 << QRect( 0, 0, 30, 40 )
165 << QPolygon( QRect( -299, -399, 300, 400 ) );
166 QTest::newRow( "rotscale 180 c" ) << rotScale(180., 10)
167 << QRect( 10, 20, 30, 40 )
168 << QPolygon( QRect( -399, -599, 300, 400 ) );
169 QTest::newRow( "rotscale 180 d" ) << rotScale(180.000001, 10)
170 << QRect( 10, 20, 30, 40 )
171 << QPolygon( QRect( -399, -599, 300, 400 ) );
172
173 QTest::newRow( "rotscale 270 a" ) << rotScale(270., 10)
174 << QRect( 0, 0, 30, 40 )
175 << QPolygon( QRect( -399, 00, 400, 300 ) );
176 QTest::newRow( "rotscale 270 b" ) << rotScale(270.0000001, 10)
177 << QRect( 0, 0, 30, 40 )
178 << QPolygon( QRect( -399, 00, 400, 300 ) );
179 QTest::newRow( "rotscale 270 c" ) << rotScale(270., 10)
180 << QRect( 10, 20, 30, 40 )
181 << QPolygon( QRect( -599, 100, 400, 300 ) );
182 QTest::newRow( "rotscale 270 d" ) << rotScale(270.000001, 10)
183 << QRect( 10, 20, 30, 40 )
184 << QPolygon( QRect( -599, 100, 400, 300 ) );
185
186 // rotations that are not multiples of 90 degrees. mapRect returns the bounding rect here.
187 QTest::newRow( "rot 45 a" ) << rotate(45)
188 << QRect( 0, 0, 10, 10 )
189 << QPolygon( QRect( 0, -7, 14, 14 ) );
190 QTest::newRow( "rot 45 b" ) << rotate(45)
191 << QRect( 10, 20, 30, 40 )
192 << QPolygon( QRect( 21, -14, 49, 49 ) );
193 QTest::newRow( "rot 45 c" ) << rotScale(45, 10)
194 << QRect( 0, 0, 10, 10 )
195 << QPolygon( QRect( 0, -70, 141, 141 ) );
196 QTest::newRow( "rot 45 d" ) << rotScale(45, 10)
197 << QRect( 10, 20, 30, 40 )
198 << QPolygon( QRect( 212, -141, 495, 495 ) );
199
200 QTest::newRow( "rot -45 a" ) << rotate(-45)
201 << QRect( 0, 0, 10, 10 )
202 << QPolygon( QRect( -7, 0, 14, 14 ) );
203 QTest::newRow( "rot -45 b" ) << rotate(-45)
204 << QRect( 10, 20, 30, 40 )
205 << QPolygon( QRect( -35, 21, 49, 49 ) );
206 QTest::newRow( "rot -45 c" ) << rotScale(-45, 10)
207 << QRect( 0, 0, 10, 10 )
208 << QPolygon( QRect( -70, 0, 141, 141 ) );
209 QTest::newRow( "rot -45 d" ) << rotScale(-45, 10)
210 << QRect( 10, 20, 30, 40 )
211 << QPolygon( QRect( -353, 212, 495, 495 ) );
212#endif
213}
214
215void tst_QWMatrix::mapRect()
216{
217 QFETCH( QMatrix, matrix );
218 QFETCH( QRect, src );
219// qDebug( "got src: %d/%d (%d/%d), matrix=[ %f %f %f %f %f %f ]",
220// src.x(), src.y(), src.width(), src.height(),
221// matrix.m11(), matrix.m12(), matrix.m21(), matrix.m22(), matrix.dx(), matrix.dy() );
222 QTEST( QPolygon( matrix.mapRect(src) ), "res" );
223}
224
225void tst_QWMatrix::operator_star_qwmatrix()
226{
227 QMatrix m1( 2, 3, 4, 5, 6, 7 );
228 QMatrix m2( 3, 4, 5, 6, 7, 8 );
229
230 QMatrix result1x2( 21, 26, 37, 46, 60, 74 );
231 QMatrix result2x1( 22, 29, 34, 45, 52, 68);
232
233 QMatrix product12 = m1*m2;
234 QMatrix product21 = m2*m1;
235
236 QVERIFY( product12==result1x2 );
237 QVERIFY( product21==result2x1 );
238}
239
240
241void tst_QWMatrix::assignments()
242{
243 QMatrix m;
244 m.scale(sx: 2, sy: 3);
245 m.rotate(a: 45);
246 m.shear(sh: 4, sv: 5);
247
248 QMatrix c1(m);
249
250 QCOMPARE(m.m11(), c1.m11());
251 QCOMPARE(m.m12(), c1.m12());
252 QCOMPARE(m.m21(), c1.m21());
253 QCOMPARE(m.m22(), c1.m22());
254 QCOMPARE(m.dx(), c1.dx());
255 QCOMPARE(m.dy(), c1.dy());
256
257 QMatrix c2 = m;
258 QCOMPARE(m.m11(), c2.m11());
259 QCOMPARE(m.m12(), c2.m12());
260 QCOMPARE(m.m21(), c2.m21());
261 QCOMPARE(m.m22(), c2.m22());
262 QCOMPARE(m.dx(), c2.dx());
263 QCOMPARE(m.dy(), c2.dy());
264}
265
266
267void tst_QWMatrix::mapToPolygon()
268{
269 QFETCH( QMatrix, matrix );
270 QFETCH( QRect, src );
271 QFETCH( QPolygon, res );
272
273 QCOMPARE( matrix.mapToPolygon( src ), res );
274}
275
276
277void tst_QWMatrix::translate()
278{
279 QMatrix m( 1, 2, 3, 4, 5, 6 );
280 QMatrix res2( m );
281 QMatrix res( 1, 2, 3, 4, 75, 106 );
282 m.translate( dx: 10, dy: 20 );
283 QVERIFY( m == res );
284 m.translate( dx: -10, dy: -20 );
285 QVERIFY( m == res2 );
286}
287
288void tst_QWMatrix::scale()
289{
290 QMatrix m( 1, 2, 3, 4, 5, 6 );
291 QMatrix res2( m );
292 QMatrix res( 10, 20, 60, 80, 5, 6 );
293 m.scale( sx: 10, sy: 20 );
294 QVERIFY( m == res );
295 m.scale( sx: 1./10., sy: 1./20. );
296 QVERIFY( m == res2 );
297}
298
299void tst_QWMatrix::mapPolygon()
300{
301 QPolygon poly;
302 poly << QPoint(0, 0) << QPoint(1, 1) << QPoint(100, 1) << QPoint(1, 100) << QPoint(-1, -1) << QPoint(-1000, 1000);
303
304 {
305 QMatrix m;
306 m.rotate(a: 90);
307
308 // rotating 90 degrees four times should result in original poly
309 QPolygon mapped = m.map(a: m.map(a: m.map(a: m.map(a: poly))));
310 QCOMPARE(mapped, poly);
311
312 QMatrix m2;
313 m2.scale(sx: 10, sy: 10);
314 QMatrix m3;
315 m3.scale(sx: 0.1, sy: 0.1);
316
317 mapped = m3.map(a: m2.map(a: poly));
318 QCOMPARE(mapped, poly);
319 }
320
321 {
322 QMatrix m(1, 2, 3, 4, 5, 6);
323
324 QPolygon mapped = m.map(a: poly);
325 for (int i = 0; i < mapped.size(); ++i)
326 QCOMPARE(mapped.at(i), m.map(poly.at(i)));
327 }
328}
329
330QT_WARNING_POP
331#endif
332
333QTEST_APPLESS_MAIN(tst_QWMatrix)
334#include "tst_qwmatrix.moc"
335

source code of qtbase/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp