16#include <private/qbezier_p.h>
22static void nanWarning(
const char *func)
24 qWarning(
"QTransform::%s with NaN called", func);
28#define Q_NEAR_CLIP (sizeof(qreal) == sizeof(double) ? 0.000001
: 0.0001
)
30void QTransform::do_map(qreal x, qreal y, qreal &nx, qreal &ny)
const
32 const TransformationType t = inline_type();
34 case QTransform::TxNone:
38 case QTransform::TxTranslate:
39 nx = x + m_matrix[2][0];
40 ny = y + m_matrix[2][1];
42 case QTransform::TxScale:
43 nx = m_matrix[0][0] * x + m_matrix[2][0];
44 ny = m_matrix[1][1] * y + m_matrix[2][1];
46 case QTransform::TxRotate:
47 case QTransform::TxShear:
48 case QTransform::TxProject:
49 nx = m_matrix[0][0] * x + m_matrix[1][0] * y + m_matrix[2][0];
50 ny = m_matrix[0][1] * x + m_matrix[1][1] * y + m_matrix[2][1];
51 if (t == QTransform::TxProject) {
52 qreal w = (m_matrix[0][2] * x + m_matrix[1][2] * y + m_matrix[2][2]);
60 Q_UNREACHABLE_RETURN();
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
224
225
226
227
228
229
230
231
232
235
236
237
240
241
242
243
244
245
246
247
248
251
252
253
254
255
256
257
260
261
262
263
264
265
268
269
270QTransform QTransform::adjoint()
const
275 h11 = m_matrix[1][1] * m_matrix[2][2] - m_matrix[1][2] * m_matrix[2][1];
276 h21 = m_matrix[1][2] * m_matrix[2][0] - m_matrix[1][0] * m_matrix[2][2];
277 h31 = m_matrix[1][0] * m_matrix[2][1] - m_matrix[1][1] * m_matrix[2][0];
278 h12 = m_matrix[0][2] * m_matrix[2][1] - m_matrix[0][1] * m_matrix[2][2];
279 h22 = m_matrix[0][0] * m_matrix[2][2] - m_matrix[0][2] * m_matrix[2][0];
280 h32 = m_matrix[0][1] * m_matrix[2][0] - m_matrix[0][0] * m_matrix[2][1];
281 h13 = m_matrix[0][1] * m_matrix[1][2] - m_matrix[0][2] * m_matrix[1][1];
282 h23 = m_matrix[0][2] * m_matrix[1][0] - m_matrix[0][0] * m_matrix[1][2];
283 h33 = m_matrix[0][0] * m_matrix[1][1] - m_matrix[0][1] * m_matrix[1][0];
285 return QTransform(h11, h12, h13,
291
292
293QTransform QTransform::transposed()
const
295 QTransform t(m_matrix[0][0], m_matrix[1][0], m_matrix[2][0],
296 m_matrix[0][1], m_matrix[1][1], m_matrix[2][1],
297 m_matrix[0][2], m_matrix[1][2], m_matrix[2][2]);
302
303
304
305
306
307
308
309
310
311QTransform QTransform::inverted(
bool *invertible)
const
316 switch(inline_type()) {
320 invert.m_matrix[2][0] = -m_matrix[2][0];
321 invert.m_matrix[2][1] = -m_matrix[2][1];
324 inv = !qFuzzyIsNull(m_matrix[0][0]);
325 inv &= !qFuzzyIsNull(m_matrix[1][1]);
327 invert.m_matrix[0][0] = 1. / m_matrix[0][0];
328 invert.m_matrix[1][1] = 1. / m_matrix[1][1];
329 invert.m_matrix[2][0] = -m_matrix[2][0] * invert.m_matrix[0][0];
330 invert.m_matrix[2][1] = -m_matrix[2][1] * invert.m_matrix[1][1];
335 qreal det = determinant();
336 inv = !qFuzzyIsNull(det);
338 invert = adjoint() / det;
347 invert.m_type = m_type;
348 invert.m_dirty = m_dirty;
355
356
357
358
359
360
361
362
363
364
365QTransform &QTransform::translate(qreal dx, qreal dy)
367 if (dx == 0 && dy == 0)
370 if (qIsNaN(dx) || qIsNaN(dy)) {
371 nanWarning(
"translate");
376 switch(inline_type()) {
382 m_matrix[2][0] += dx;
383 m_matrix[2][1] += dy;
386 m_matrix[2][0] += dx * m_matrix[0][0];
387 m_matrix[2][1] += dy * m_matrix[1][1];
390 m_matrix[2][2] += dx * m_matrix[0][2] + dy * m_matrix[1][2];
394 m_matrix[2][0] += dx * m_matrix[0][0] + dy * m_matrix[1][0];
395 m_matrix[2][1] += dy * m_matrix[1][1] + dx * m_matrix[0][1];
398 if (m_dirty < TxTranslate)
399 m_dirty = TxTranslate;
404
405
406
407
408
409
410QTransform QTransform::fromTranslate(qreal dx, qreal dy)
413 if (qIsNaN(dx) || qIsNaN(dy)) {
414 nanWarning(
"fromTranslate");
418 QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1);
419 if (dx == 0 && dy == 0)
420 transform.m_type = TxNone;
422 transform.m_type = TxTranslate;
423 transform.m_dirty = TxNone;
428
429
430
431
432
433
434
435QTransform & QTransform::scale(qreal sx, qreal sy)
437 if (sx == 1 && sy == 1)
440 if (qIsNaN(sx) || qIsNaN(sy)) {
446 switch(inline_type()) {
453 m_matrix[0][2] *= sx;
454 m_matrix[1][2] *= sy;
458 m_matrix[0][1] *= sx;
459 m_matrix[1][0] *= sy;
462 m_matrix[0][0] *= sx;
463 m_matrix[1][1] *= sy;
466 if (m_dirty < TxScale)
472
473
474
475
476
477
478QTransform QTransform::fromScale(qreal sx, qreal sy)
481 if (qIsNaN(sx) || qIsNaN(sy)) {
482 nanWarning(
"fromScale");
486 QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1);
487 if (sx == 1. && sy == 1.)
488 transform.m_type = TxNone;
490 transform.m_type = TxScale;
491 transform.m_dirty = TxNone;
496
497
498
499
500
501
502
503QTransform & QTransform::shear(qreal sh, qreal sv)
505 if (sh == 0 && sv == 0)
508 if (qIsNaN(sh) || qIsNaN(sv)) {
514 switch(inline_type()) {
521 m_matrix[0][1] = sv*m_matrix[1][1];
522 m_matrix[1][0] = sh*m_matrix[0][0];
525 qreal tm13 = sv * m_matrix[1][2];
526 qreal tm23 = sh * m_matrix[0][2];
527 m_matrix[0][2] += tm13;
528 m_matrix[1][2] += tm23;
533 qreal tm11 = sv * m_matrix[1][0];
534 qreal tm22 = sh * m_matrix[0][1];
535 qreal tm12 = sv * m_matrix[1][1];
536 qreal tm21 = sh * m_matrix[0][0];
537 m_matrix[0][0] += tm11;
538 m_matrix[0][1] += tm12;
539 m_matrix[1][0] += tm21;
540 m_matrix[1][1] += tm22;
544 if (m_dirty < TxShear)
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573QTransform & QTransform::rotate(qreal a, Qt::Axis axis, qreal distanceToPlane)
578 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
579 nanWarning(
"rotate");
586 if (a == 90. || a == -270.)
588 else if (a == 270. || a == -90.)
593 qreal b = qDegreesToRadians(a);
598 if (axis == Qt::ZAxis) {
599 switch(inline_type()) {
602 m_matrix[0][0] = cosa;
603 m_matrix[0][1] = sina;
604 m_matrix[1][0] = -sina;
605 m_matrix[1][1] = cosa;
608 qreal tm11 = cosa * m_matrix[0][0];
609 qreal tm12 = sina * m_matrix[1][1];
610 qreal tm21 = -sina * m_matrix[0][0];
611 qreal tm22 = cosa * m_matrix[1][1];
612 m_matrix[0][0] = tm11;
613 m_matrix[0][1] = tm12;
614 m_matrix[1][0] = tm21;
615 m_matrix[1][1] = tm22;
619 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
620 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
621 m_matrix[0][2] = tm13;
622 m_matrix[1][2] = tm23;
627 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
628 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
629 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
630 qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1];
631 m_matrix[0][0] = tm11;
632 m_matrix[0][1] = tm12;
633 m_matrix[1][0] = tm21;
634 m_matrix[1][1] = tm22;
638 if (m_dirty < TxRotate)
641 if (!qIsNull(distanceToPlane))
642 sina /= distanceToPlane;
645 if (axis == Qt::YAxis) {
646 result.m_matrix[0][0] = cosa;
647 result.m_matrix[0][2] = -sina;
649 result.m_matrix[1][1] = cosa;
650 result.m_matrix[1][2] = -sina;
652 result.m_type = TxProject;
653 *
this = result * *
this;
659#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
661
662
663
664
665
666
667
668
669
670
671QTransform &QTransform::rotate(qreal a, Qt::Axis axis)
673 return rotate(a, axis, 1024.0);
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis, qreal distanceToPlane)
704 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
705 nanWarning(
"rotateRadians");
709 qreal sina = qSin(a);
710 qreal cosa = qCos(a);
712 if (axis == Qt::ZAxis) {
713 switch(inline_type()) {
716 m_matrix[0][0] = cosa;
717 m_matrix[0][1] = sina;
718 m_matrix[1][0] = -sina;
719 m_matrix[1][1] = cosa;
722 qreal tm11 = cosa * m_matrix[0][0];
723 qreal tm12 = sina * m_matrix[1][1];
724 qreal tm21 = -sina * m_matrix[0][0];
725 qreal tm22 = cosa * m_matrix[1][1];
726 m_matrix[0][0] = tm11;
727 m_matrix[0][1] = tm12;
728 m_matrix[1][0] = tm21;
729 m_matrix[1][1] = tm22;
733 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
734 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
735 m_matrix[0][2] = tm13;
736 m_matrix[1][2] = tm23;
741 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
742 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
743 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
744 qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1];
745 m_matrix[0][0] = tm11;
746 m_matrix[0][1] = tm12;
747 m_matrix[1][0] = tm21;
748 m_matrix[1][1] = tm22;
752 if (m_dirty < TxRotate)
755 if (!qIsNull(distanceToPlane))
756 sina /= distanceToPlane;
759 if (axis == Qt::YAxis) {
760 result.m_matrix[0][0] = cosa;
761 result.m_matrix[0][2] = -sina;
763 result.m_matrix[1][1] = cosa;
764 result.m_matrix[1][2] = -sina;
766 result.m_type = TxProject;
767 *
this = result * *
this;
772#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
774
775
776
777
778
779
780
781
782
783
784QTransform &QTransform::rotateRadians(qreal a, Qt::Axis axis)
786 return rotateRadians(a, axis, 1024.0);
791
792
793
794
795bool QTransform::operator==(
const QTransform &o)
const
797 return m_matrix[0][0] == o.m_matrix[0][0] &&
798 m_matrix[0][1] == o.m_matrix[0][1] &&
799 m_matrix[1][0] == o.m_matrix[1][0] &&
800 m_matrix[1][1] == o.m_matrix[1][1] &&
801 m_matrix[2][0] == o.m_matrix[2][0] &&
802 m_matrix[2][1] == o.m_matrix[2][1] &&
803 m_matrix[0][2] == o.m_matrix[0][2] &&
804 m_matrix[1][2] == o.m_matrix[1][2] &&
805 m_matrix[2][2] == o.m_matrix[2][2];
809
810
811
814 QtPrivate::QHashCombineWithSeed hash(seed);
815 seed = hash(seed, key.m11());
816 seed = hash(seed, key.m12());
817 seed = hash(seed, key.m21());
818 seed = hash(seed, key.m22());
819 seed = hash(seed, key.dx());
820 seed = hash(seed, key.dy());
821 seed = hash(seed, key.m13());
822 seed = hash(seed, key.m23());
823 seed = hash(seed, key.m33());
829
830
831
832
833bool QTransform::operator!=(
const QTransform &o)
const
835 return !operator==(o);
839
840
841
842
843
844
845
846QTransform & QTransform::operator*=(
const QTransform &o)
848 const TransformationType otherType = o.inline_type();
849 if (otherType == TxNone)
852 const TransformationType thisType = inline_type();
853 if (thisType == TxNone)
856 TransformationType t = qMax(thisType, otherType);
861 m_matrix[2][0] += o.m_matrix[2][0];
862 m_matrix[2][1] += o.m_matrix[2][1];
866 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0];
867 qreal m22 = m_matrix[1][1] * o.m_matrix[1][1];
869 qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + o.m_matrix[2][0];
870 qreal m32 = m_matrix[2][1] * o.m_matrix[1][1] + o.m_matrix[2][1];
872 m_matrix[0][0] = m11;
873 m_matrix[1][1] = m22;
874 m_matrix[2][0] = m31; m_matrix[2][1] = m32;
880 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0] + m_matrix[0][1] * o.m_matrix[1][0];
881 qreal m12 = m_matrix[0][0] * o.m_matrix[0][1] + m_matrix[0][1] * o.m_matrix[1][1];
883 qreal m21 = m_matrix[1][0] * o.m_matrix[0][0] + m_matrix[1][1] * o.m_matrix[1][0];
884 qreal m22 = m_matrix[1][0] * o.m_matrix[0][1] + m_matrix[1][1] * o.m_matrix[1][1];
886 qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + m_matrix[2][1] * o.m_matrix[1][0] + o.m_matrix[2][0];
887 qreal m32 = m_matrix[2][0] * o.m_matrix[0][1] + m_matrix[2][1] * o.m_matrix[1][1] + o.m_matrix[2][1];
889 m_matrix[0][0] = m11;
890 m_matrix[0][1] = m12;
891 m_matrix[1][0] = m21;
892 m_matrix[1][1] = m22;
893 m_matrix[2][0] = m31;
894 m_matrix[2][1] = m32;
899 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0] + m_matrix[0][1] * o.m_matrix[1][0] + m_matrix[0][2] * o.m_matrix[2][0];
900 qreal m12 = m_matrix[0][0] * o.m_matrix[0][1] + m_matrix[0][1] * o.m_matrix[1][1] + m_matrix[0][2] * o.m_matrix[2][1];
901 qreal m13 = m_matrix[0][0] * o.m_matrix[0][2] + m_matrix[0][1] * o.m_matrix[1][2] + m_matrix[0][2] * o.m_matrix[2][2];
903 qreal m21 = m_matrix[1][0] * o.m_matrix[0][0] + m_matrix[1][1] * o.m_matrix[1][0] + m_matrix[1][2] * o.m_matrix[2][0];
904 qreal m22 = m_matrix[1][0] * o.m_matrix[0][1] + m_matrix[1][1] * o.m_matrix[1][1] + m_matrix[1][2] * o.m_matrix[2][1];
905 qreal m23 = m_matrix[1][0] * o.m_matrix[0][2] + m_matrix[1][1] * o.m_matrix[1][2] + m_matrix[1][2] * o.m_matrix[2][2];
907 qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + m_matrix[2][1] * o.m_matrix[1][0] + m_matrix[2][2] * o.m_matrix[2][0];
908 qreal m32 = m_matrix[2][0] * o.m_matrix[0][1] + m_matrix[2][1] * o.m_matrix[1][1] + m_matrix[2][2] * o.m_matrix[2][1];
909 qreal m33 = m_matrix[2][0] * o.m_matrix[0][2] + m_matrix[2][1] * o.m_matrix[1][2] + m_matrix[2][2] * o.m_matrix[2][2];
911 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
912 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
913 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
924
925
926
927
928
929
930
931
932QTransform QTransform::operator*(
const QTransform &m)
const
934 const TransformationType otherType = m.inline_type();
935 if (otherType == TxNone)
938 const TransformationType thisType = inline_type();
939 if (thisType == TxNone)
943 TransformationType type = qMax(thisType, otherType);
948 t.m_matrix[2][0] = m_matrix[2][0] + m.m_matrix[2][0];
949 t.m_matrix[2][1] = m_matrix[2][1] + m.m_matrix[2][1];
953 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0];
954 qreal m22 = m_matrix[1][1] * m.m_matrix[1][1];
956 qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m.m_matrix[2][0];
957 qreal m32 = m_matrix[2][1] * m.m_matrix[1][1] + m.m_matrix[2][1];
959 t.m_matrix[0][0] = m11;
960 t.m_matrix[1][1] = m22;
961 t.m_matrix[2][0] = m31;
962 t.m_matrix[2][1] = m32;
968 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0] + m_matrix[0][1] * m.m_matrix[1][0];
969 qreal m12 = m_matrix[0][0] * m.m_matrix[0][1] + m_matrix[0][1] * m.m_matrix[1][1];
971 qreal m21 = m_matrix[1][0] * m.m_matrix[0][0] + m_matrix[1][1] * m.m_matrix[1][0];
972 qreal m22 = m_matrix[1][0] * m.m_matrix[0][1] + m_matrix[1][1] * m.m_matrix[1][1];
974 qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m_matrix[2][1] * m.m_matrix[1][0] + m.m_matrix[2][0];
975 qreal m32 = m_matrix[2][0] * m.m_matrix[0][1] + m_matrix[2][1] * m.m_matrix[1][1] + m.m_matrix[2][1];
977 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12;
978 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22;
979 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32;
984 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0] + m_matrix[0][1] * m.m_matrix[1][0] + m_matrix[0][2] * m.m_matrix[2][0];
985 qreal m12 = m_matrix[0][0] * m.m_matrix[0][1] + m_matrix[0][1] * m.m_matrix[1][1] + m_matrix[0][2] * m.m_matrix[2][1];
986 qreal m13 = m_matrix[0][0] * m.m_matrix[0][2] + m_matrix[0][1] * m.m_matrix[1][2] + m_matrix[0][2] * m.m_matrix[2][2];
988 qreal m21 = m_matrix[1][0] * m.m_matrix[0][0] + m_matrix[1][1] * m.m_matrix[1][0] + m_matrix[1][2] * m.m_matrix[2][0];
989 qreal m22 = m_matrix[1][0] * m.m_matrix[0][1] + m_matrix[1][1] * m.m_matrix[1][1] + m_matrix[1][2] * m.m_matrix[2][1];
990 qreal m23 = m_matrix[1][0] * m.m_matrix[0][2] + m_matrix[1][1] * m.m_matrix[1][2] + m_matrix[1][2] * m.m_matrix[2][2];
992 qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m_matrix[2][1] * m.m_matrix[1][0] + m_matrix[2][2] * m.m_matrix[2][0];
993 qreal m32 = m_matrix[2][0] * m.m_matrix[0][1] + m_matrix[2][1] * m.m_matrix[1][1] + m_matrix[2][2] * m.m_matrix[2][1];
994 qreal m33 = m_matrix[2][0] * m.m_matrix[0][2] + m_matrix[2][1] * m.m_matrix[1][2] + m_matrix[2][2] * m.m_matrix[2][2];
996 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12; t.m_matrix[0][2] = m13;
997 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22; t.m_matrix[1][2] = m23;
998 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32; t.m_matrix[2][2] = m33;
1009
1010
1011
1012
1013
1014
1017
1018
1019
1020
1021
1022
1025
1026
1027
1028
1029
1030
1033
1034
1035
1036
1037
1038
1041
1042
1043
1044
1047
1048
1049
1050
1051
1052
1053
1054void QTransform::reset()
1056 *
this = QTransform();
1059#ifndef QT_NO_DATASTREAM
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070QDataStream & operator<<(QDataStream &s,
const QTransform &m)
1072 s <<
double(m.m11())
1085
1086
1087
1088
1089
1090
1091
1092
1093
1096 double m11, m12, m13,
1109 t.setMatrix(m11, m12, m13,
1117#ifndef QT_NO_DEBUG_STREAM
1120 static const char typeStr[][12] =
1129 "",
"",
"",
"",
"",
"",
"",
1133 QDebugStateSaver saver(dbg);
1134 dbg.nospace() <<
"QTransform(type=" << typeStr[m.type()] <<
','
1135 <<
" 11=" << m.m11()
1136 <<
" 12=" << m.m12()
1137 <<
" 13=" << m.m13()
1138 <<
" 21=" << m.m21()
1139 <<
" 22=" << m.m22()
1140 <<
" 23=" << m.m23()
1141 <<
" 31=" << m.m31()
1142 <<
" 32=" << m.m32()
1143 <<
" 33=" << m.m33()
1151
1152
1153
1154
1155
1156
1157
1158QPoint QTransform::map(
const QPoint &p)
const
1165 do_map(fx, fy, x, y);
1167 return QPoint(qRound(x), qRound(y));
1172
1173
1174
1175
1176
1177
1178
1181
1182
1183
1184
1185
1186QPointF QTransform::map(
const QPointF &p)
const
1193 do_map(fx, fy, x, y);
1195 return QPointF(x, y);
1199
1200
1201
1202
1203
1204
1205
1206
1209
1210
1211
1212
1213
1214
1215
1218
1219
1220
1221
1222
1223
1224
1227
1228
1229
1230
1231
1232QLine QTransform::map(
const QLine &l)
const
1239 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1241 do_map(fx1, fy1, x1, y1);
1242 do_map(fx2, fy2, x2, y2);
1244 return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1248
1249
1250
1251
1252
1253
1254
1255
1256
1258QLineF QTransform::map(
const QLineF &l)
const
1265 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1267 do_map(fx1, fy1, x1, y1);
1268 do_map(fx2, fy2, x2, y2);
1270 return QLineF(x1, y1, x2, y2);
1274
1275
1276
1277
1278
1279
1280
1281
1284
1285
1286
1287
1288
1289
1290
1293
1294
1295
1296
1297
1298
1299
1300QPolygonF QTransform::map(
const QPolygonF &a)
const
1302 TransformationType t = inline_type();
1303 if (t <= TxTranslate)
1304 return a.translated(m_matrix[2][0], m_matrix[2][1]);
1306 int size = a.size();
1309 const QPointF *da = a.constData();
1310 QPointF *dp = p.data();
1312 for(i = 0; i < size; ++i) {
1313 do_map(da[i].x(), da[i].y(), dp[i].rx(), dp[i].ry());
1319
1320
1321
1322
1323
1324
1325
1326
1327QPolygon QTransform::map(
const QPolygon &a)
const
1329 TransformationType t = inline_type();
1330 if (t <= TxTranslate)
1331 return a.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1333 int size = a.size();
1336 const QPoint *da = a.constData();
1337 QPoint *dp = p.data();
1339 for(i = 0; i < size; ++i) {
1340 qreal nx = 0, ny = 0;
1341 do_map(da[i].x(), da[i].y(), nx, ny);
1342 dp[i].rx() = qRound(nx);
1343 dp[i].ry() = qRound(ny);
1349
1350
1351
1352
1353
1354
1355
1357Q_GUI_EXPORT
extern QPainterPath qt_regionToPath(
const QRegion ®ion);
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369QRegion QTransform::map(
const QRegion &r)
const
1371 TransformationType t = inline_type();
1375 if (t == TxTranslate) {
1377 copy.translate(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1383 if (m11() < 0 || m22() < 0) {
1384 for (
const QRect &rect : r)
1385 res += qt_mapFillRect(QRectF(rect), *
this);
1387 QVarLengthArray<QRect, 32> rects;
1388 rects.reserve(r.rectCount());
1389 for (
const QRect &rect : r) {
1390 QRect nr = qt_mapFillRect(QRectF(rect), *
this);
1394 res.setRects(rects.constData(), rects.size());
1399 QPainterPath p = map(qt_regionToPath(r));
1400 return p.toFillPolygon().toPolygon();
1414 return QPointF(x * iw, y * iw);
1421 c.x = transform.m11() * p.x() + transform.m21() * p.y() + transform.m31();
1422 c.y = transform.m12() * p.x() + transform.m22() * p.y() + transform.m32();
1423 c.w = transform.m13() * p.x() + transform.m23() * p.y() + transform.m33();
1427static inline bool lineTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
1428 bool needsMoveTo,
bool needsLineTo =
true)
1430 QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1431 QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1437 const qreal t = (
Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1439 hb.x += (ha.x - hb.x) * t;
1440 hb.y += (ha.y - hb.y) * t;
1443 const qreal t = (
Q_NEAR_CLIP - ha.w) / (hb.w - ha.w);
1445 ha.x += (hb.x - ha.x) * t;
1446 ha.y += (hb.y - ha.y) * t;
1449 const QPointF p = ha.toPoint();
1452 needsMoveTo =
false;
1459 path.moveTo(ha.toPoint());
1462 path.lineTo(hb.toPoint());
1468static inline bool cubicTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
const QPointF &c,
const QPointF &d,
bool needsMoveTo)
1474 qt_scaleForTransform(transform, &scale);
1476 qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1478 QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1480 for (
int i = 0; i < segment.size() - 1; ++i)
1481 if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
1482 needsMoveTo =
false;
1484 return !needsMoveTo;
1487static QPainterPath
mapProjective(
const QTransform &transform,
const QPainterPath &path)
1489 QPainterPath result;
1493 bool needsMoveTo =
true;
1494 for (
int i = 0; i < path.elementCount(); ++i) {
1495 switch (path.elementAt(i).type) {
1496 case QPainterPath::MoveToElement:
1497 if (i > 0 && lastMoveTo != last)
1500 lastMoveTo = path.elementAt(i);
1501 last = path.elementAt(i);
1504 case QPainterPath::LineToElement:
1506 needsMoveTo =
false;
1507 last = path.elementAt(i);
1509 case QPainterPath::CurveToElement:
1510 if (
cubicTo_clipped(result
, transform
, last
, path.elementAt(i)
, path.elementAt(i+1)
, path.elementAt(i+2)
, needsMoveTo
))
1511 needsMoveTo =
false;
1513 last = path.elementAt(i);
1520 if (path.elementCount() > 0 && lastMoveTo != last)
1523 result.setFillRule(path.fillRule());
1528
1529
1530
1531
1532
1533
1534
1535
1538
1539
1540
1541
1542
1543
1544QPainterPath QTransform::map(
const QPainterPath &path)
const
1546 TransformationType t = inline_type();
1547 if (t == TxNone || path.elementCount() == 0)
1551 return mapProjective(*
this, path);
1553 QPainterPath copy = path;
1555 if (t == TxTranslate) {
1556 copy.translate(m_matrix[2][0], m_matrix[2][1]);
1558 copy.setDirty(
true);
1560 for (
int i=0; i<path.elementCount(); ++i) {
1561 QPainterPath::Element &e = copy.d_ptr->elements[i];
1562 do_map(e.x, e.y, e.x, e.y);
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589QPolygon QTransform::mapToPolygon(
const QRect &rect)
const
1591 TransformationType t = inline_type();
1594 qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1596 x[0] = m_matrix[0][0]*rect.x() + m_matrix[2][0];
1597 y[0] = m_matrix[1][1]*rect.y() + m_matrix[2][1];
1598 qreal w = m_matrix[0][0]*rect.width();
1599 qreal h = m_matrix[1][1]*rect.height();
1615 auto right = rect.x() + rect.width();
1616 auto bottom = rect.y() + rect.height();
1617 do_map(rect.x(), rect.y(), x[0], y[0]);
1618 do_map(right, rect.y(), x[1], y[1]);
1619 do_map(right, bottom, x[2], y[2]);
1620 do_map(rect.x(), bottom, x[3], y[3]);
1625 a.setPoints(4, qRound(x[0]), qRound(y[0]),
1626 qRound(x[1]), qRound(y[1]),
1627 qRound(x[2]), qRound(y[2]),
1628 qRound(x[3]), qRound(y[3]));
1633
1634
1635
1636
1637
1638
1639bool QTransform::squareToQuad(
const QPolygonF &quad, QTransform &trans)
1641 if (quad.size() != (quad.isClosed() ? 5 : 4))
1644 qreal dx0 = quad[0].x();
1645 qreal dx1 = quad[1].x();
1646 qreal dx2 = quad[2].x();
1647 qreal dx3 = quad[3].x();
1649 qreal dy0 = quad[0].y();
1650 qreal dy1 = quad[1].y();
1651 qreal dy2 = quad[2].y();
1652 qreal dy3 = quad[3].y();
1654 double ax = dx0 - dx1 + dx2 - dx3;
1655 double ay = dy0 - dy1 + dy2 - dy3;
1658 trans.setMatrix(dx1 - dx0, dy1 - dy0, 0,
1659 dx2 - dx1, dy2 - dy1, 0,
1662 double ax1 = dx1 - dx2;
1663 double ax2 = dx3 - dx2;
1664 double ay1 = dy1 - dy2;
1665 double ay2 = dy3 - dy2;
1668 double gtop = ax * ay2 - ax2 * ay;
1669 double htop = ax1 * ay - ax * ay1;
1670 double bottom = ax1 * ay2 - ax2 * ay1;
1672 double a, b, c, d, e, f, g, h;
1680 a = dx1 - dx0 + g * dx1;
1681 b = dx3 - dx0 + h * dx3;
1683 d = dy1 - dy0 + g * dy1;
1684 e = dy3 - dy0 + h * dy3;
1687 trans.setMatrix(a, d, g,
1696
1697
1698
1699
1700
1701
1702
1703
1704bool QTransform::quadToSquare(
const QPolygonF &quad, QTransform &trans)
1706 if (!squareToQuad(quad, trans))
1709 bool invertible =
false;
1710 trans = trans.inverted(&invertible);
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727bool QTransform::quadToQuad(
const QPolygonF &one,
1728 const QPolygonF &two,
1732 if (!quadToSquare(one, trans))
1734 if (!squareToQuad(two, stq))
1742
1743
1744
1745
1746
1747
1748
1749
1750
1752void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
1753 qreal m21, qreal m22, qreal m23,
1754 qreal m31, qreal m32, qreal m33)
1756 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
1757 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
1758 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
1760 m_dirty = TxProject;
1763QRect QTransform::mapRect(
const QRect &rect)
const
1765 TransformationType t = inline_type();
1766 if (t <= TxTranslate)
1767 return rect.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1770 int x = qRound(m_matrix[0][0] * rect.x() + m_matrix[2][0]);
1771 int y = qRound(m_matrix[1][1] * rect.y() + m_matrix[2][1]);
1772 int w = qRound(m_matrix[0][0] * rect.width());
1773 int h = qRound(m_matrix[1][1] * rect.height());
1782 return QRect(x, y, w, h);
1785 do_map(rect.left(), rect.top(), x, y);
1790 do_map(rect.right() + 1, rect.top(), x, y);
1791 xmin = qMin(xmin, x);
1792 ymin = qMin(ymin, y);
1793 xmax = qMax(xmax, x);
1794 ymax = qMax(ymax, y);
1795 do_map(rect.right() + 1, rect.bottom() + 1, x, y);
1796 xmin = qMin(xmin, x);
1797 ymin = qMin(ymin, y);
1798 xmax = qMax(xmax, x);
1799 ymax = qMax(ymax, y);
1800 do_map(rect.left(), rect.bottom() + 1, x, y);
1801 xmin = qMin(xmin, x);
1802 ymin = qMin(ymin, y);
1803 xmax = qMax(xmax, x);
1804 ymax = qMax(ymax, y);
1805 return QRectF(xmin, ymin, xmax-xmin, ymax-ymin).toRect();
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828QRectF QTransform::mapRect(
const QRectF &rect)
const
1830 TransformationType t = inline_type();
1831 if (t <= TxTranslate)
1832 return rect.translated(m_matrix[2][0], m_matrix[2][1]);
1835 qreal x = m_matrix[0][0] * rect.x() + m_matrix[2][0];
1836 qreal y = m_matrix[1][1] * rect.y() + m_matrix[2][1];
1837 qreal w = m_matrix[0][0] * rect.width();
1838 qreal h = m_matrix[1][1] * rect.height();
1847 return QRectF(x, y, w, h);
1850 do_map(rect.x(), rect.y(), x, y);
1855 do_map(rect.x() + rect.width(), rect.y(), x, y);
1856 xmin = qMin(xmin, x);
1857 ymin = qMin(ymin, y);
1858 xmax = qMax(xmax, x);
1859 ymax = qMax(ymax, y);
1860 do_map(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
1861 xmin = qMin(xmin, x);
1862 ymin = qMin(ymin, y);
1863 xmax = qMax(xmax, x);
1864 ymax = qMax(ymax, y);
1865 do_map(rect.x(), rect.y() + rect.height(), x, y);
1866 xmin = qMin(xmin, x);
1867 ymin = qMin(ymin, y);
1868 xmax = qMax(xmax, x);
1869 ymax = qMax(ymax, y);
1870 return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
1875
1876
1877
1878
1879
1880
1881
1882
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty)
const
1900 do_map(x, y, *tx, *ty);
1904
1905
1906
1907
1908
1909
1910
1911void QTransform::map(
int x,
int y,
int *tx,
int *ty)
const
1913 qreal fx = 0, fy = 0;
1914 do_map(x, y, fx, fy);
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931QTransform::TransformationType QTransform::type()
const
1933 if (m_dirty == TxNone || m_dirty < m_type)
1934 return static_cast<TransformationType>(m_type);
1936 switch (
static_cast<TransformationType>(m_dirty)) {
1938 if (!qFuzzyIsNull(m_matrix[0][2]) || !qFuzzyIsNull(m_matrix[1][2]) || !qFuzzyIsNull(m_matrix[2][2] - 1)) {
1945 if (!qFuzzyIsNull(m_matrix[0][1]) || !qFuzzyIsNull(m_matrix[1][0])) {
1946 const qreal dot = m_matrix[0][0] * m_matrix[1][0] + m_matrix[0][1] * m_matrix[1][1];
1947 if (qFuzzyIsNull(dot))
1955 if (!qFuzzyIsNull(m_matrix[0][0] - 1) || !qFuzzyIsNull(m_matrix[1][1] - 1)) {
1961 if (!qFuzzyIsNull(m_matrix[2][0]) || !qFuzzyIsNull(m_matrix[2][1])) {
1962 m_type = TxTranslate;
1972 return static_cast<TransformationType>(m_type);
1976
1977
1978
1979QTransform::operator QVariant()
const
1981 return QVariant::fromValue(*
this);
1986
1987
1988
1989
1990
1991
1994
1995
1996
1997
1998
1999
2000
2003
2004
2005
2006
2007
2008
2009
2012
2013
2014
2015
2016
2017
2018
2021
2022
2023
2024
2025
2026
2027
2030
2031
2032
2033
2034
2035
2036
2039
2040
2041
2042
2043
2044
2045
2049
2050
2051
2052
2053
2054
2055
2059
2060
2061
2062
2063
2064
2065
2068
2069
2070
2071
2072
2073
2074
2077
2078
2079
2080
2081
2082
2083
2086
2087
2088
2089
2090
2091
2092
2095
2096
2097
2098
2101
2102
2103
2104
2105
2106
2107
2110
2111
2112
2113
2114
2117
2118
2119
2120
2121
2122
2123
2126
2127
2128
2129
2130
2131
2132
2133
2134
2137
2138
2139
2140
2141
2142
2143
2146
2147
2148
2149
2150
2151
2152
2153
2162 const QTransform::TransformationType type = transform.type();
2163 if (type <= QTransform::TxTranslate) {
2167 }
else if (type == QTransform::TxScale) {
2168 const qreal xScale = qAbs(transform.m11());
2169 const qreal yScale = qAbs(transform.m22());
2171 *scale = qMax(xScale, yScale);
2172 return qFuzzyCompare(xScale, yScale);
2176 const qreal xScale1 = transform.m11() * transform.m11()
2177 + transform.m21() * transform.m21();
2178 const qreal yScale1 = transform.m12() * transform.m12()
2179 + transform.m22() * transform.m22();
2182 const qreal xScale2 = transform.m11() * transform.m11()
2183 + transform.m12() * transform.m12();
2184 const qreal yScale2 = transform.m21() * transform.m21()
2185 + transform.m22() * transform.m22();
2188 if (qAbs(xScale1 - yScale1) > qAbs(xScale2 - yScale2)) {
2190 *scale = qSqrt(qMax(xScale1, yScale1));
2192 return type == QTransform::TxRotate && qFuzzyCompare(xScale1, yScale1);
2195 *scale = qSqrt(qMax(xScale2, yScale2));
2197 return type == QTransform::TxRotate && qFuzzyCompare(xScale2, yScale2);
2201QDataStream &
operator>>(QDataStream &s, QTransform::Affine &m)
2203 if (s.version() == 1) {
2204 float m11, m12, m21, m22, dx, dy;
2205 s >> m11; s >> m12; s >> m21; s >> m22; s >> dx; s >> dy;
2207 m.m_matrix[0][0] = m11;
2208 m.m_matrix[0][1] = m12;
2209 m.m_matrix[1][0] = m21;
2210 m.m_matrix[1][1] = m22;
2211 m.m_matrix[2][0] = dx;
2212 m.m_matrix[2][1] = dy;
2214 s >> m.m_matrix[0][0];
2215 s >> m.m_matrix[0][1];
2216 s >> m.m_matrix[1][0];
2217 s >> m.m_matrix[1][1];
2218 s >> m.m_matrix[2][0];
2219 s >> m.m_matrix[2][1];
2221 m.m_matrix[0][2] = 0;
2222 m.m_matrix[1][2] = 0;
2223 m.m_matrix[2][2] = 1;
2227QDataStream &operator<<(QDataStream &s,
const QTransform::Affine &m)
2229 if (s.version() == 1) {
2230 s << (
float)m.m_matrix[0][0]
2231 << (
float)m.m_matrix[0][1]
2232 << (
float)m.m_matrix[1][0]
2233 << (
float)m.m_matrix[1][1]
2234 << (
float)m.m_matrix[2][0]
2235 << (
float)m.m_matrix[2][1];
2237 s << m.m_matrix[0][0]
2242 << m.m_matrix[2][1];
\inmodule QtCore\reentrant
Combined button and popup list for selecting options.
QDataStream & operator>>(QDataStream &s, QKeyCombination &combination)
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
const QPointF toPoint() const
QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_)