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
217
218
219
220
221
222
223
224
225
228
229
230
233
234
235
236
237
238
239
240
241
244
245
246
247
248
249
250
253
254
255
256
257
258
261
262
263QTransform QTransform::adjoint()
const
268 h11 = m_matrix[1][1] * m_matrix[2][2] - m_matrix[1][2] * m_matrix[2][1];
269 h21 = m_matrix[1][2] * m_matrix[2][0] - m_matrix[1][0] * m_matrix[2][2];
270 h31 = m_matrix[1][0] * m_matrix[2][1] - m_matrix[1][1] * m_matrix[2][0];
271 h12 = m_matrix[0][2] * m_matrix[2][1] - m_matrix[0][1] * m_matrix[2][2];
272 h22 = m_matrix[0][0] * m_matrix[2][2] - m_matrix[0][2] * m_matrix[2][0];
273 h32 = m_matrix[0][1] * m_matrix[2][0] - m_matrix[0][0] * m_matrix[2][1];
274 h13 = m_matrix[0][1] * m_matrix[1][2] - m_matrix[0][2] * m_matrix[1][1];
275 h23 = m_matrix[0][2] * m_matrix[1][0] - m_matrix[0][0] * m_matrix[1][2];
276 h33 = m_matrix[0][0] * m_matrix[1][1] - m_matrix[0][1] * m_matrix[1][0];
278 return QTransform(h11, h12, h13,
284
285
286QTransform QTransform::transposed()
const
288 QTransform t(m_matrix[0][0], m_matrix[1][0], m_matrix[2][0],
289 m_matrix[0][1], m_matrix[1][1], m_matrix[2][1],
290 m_matrix[0][2], m_matrix[1][2], m_matrix[2][2]);
295
296
297
298
299
300
301
302
303
304QTransform QTransform::inverted(
bool *invertible)
const
309 switch(inline_type()) {
313 invert.m_matrix[2][0] = -m_matrix[2][0];
314 invert.m_matrix[2][1] = -m_matrix[2][1];
317 inv = !qFuzzyIsNull(m_matrix[0][0]);
318 inv &= !qFuzzyIsNull(m_matrix[1][1]);
320 invert.m_matrix[0][0] = 1. / m_matrix[0][0];
321 invert.m_matrix[1][1] = 1. / m_matrix[1][1];
322 invert.m_matrix[2][0] = -m_matrix[2][0] * invert.m_matrix[0][0];
323 invert.m_matrix[2][1] = -m_matrix[2][1] * invert.m_matrix[1][1];
328 qreal det = determinant();
329 inv = !qFuzzyIsNull(det);
331 invert = adjoint() / det;
340 invert.m_type = m_type;
341 invert.m_dirty = m_dirty;
348
349
350
351
352
353QTransform &QTransform::translate(qreal dx, qreal dy)
355 if (dx == 0 && dy == 0)
358 if (qIsNaN(dx) || qIsNaN(dy)) {
359 nanWarning(
"translate");
364 switch(inline_type()) {
370 m_matrix[2][0] += dx;
371 m_matrix[2][1] += dy;
374 m_matrix[2][0] += dx * m_matrix[0][0];
375 m_matrix[2][1] += dy * m_matrix[1][1];
378 m_matrix[2][2] += dx * m_matrix[0][2] + dy * m_matrix[1][2];
382 m_matrix[2][0] += dx * m_matrix[0][0] + dy * m_matrix[1][0];
383 m_matrix[2][1] += dy * m_matrix[1][1] + dx * m_matrix[0][1];
386 if (m_dirty < TxTranslate)
387 m_dirty = TxTranslate;
392
393
394
395
396
397
398QTransform QTransform::fromTranslate(qreal dx, qreal dy)
401 if (qIsNaN(dx) || qIsNaN(dy)) {
402 nanWarning(
"fromTranslate");
406 QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1);
407 if (dx == 0 && dy == 0)
408 transform.m_type = TxNone;
410 transform.m_type = TxTranslate;
411 transform.m_dirty = TxNone;
416
417
418
419
420
421QTransform & QTransform::scale(qreal sx, qreal sy)
423 if (sx == 1 && sy == 1)
426 if (qIsNaN(sx) || qIsNaN(sy)) {
432 switch(inline_type()) {
439 m_matrix[0][2] *= sx;
440 m_matrix[1][2] *= sy;
444 m_matrix[0][1] *= sx;
445 m_matrix[1][0] *= sy;
448 m_matrix[0][0] *= sx;
449 m_matrix[1][1] *= sy;
452 if (m_dirty < TxScale)
458
459
460
461
462
463
464QTransform QTransform::fromScale(qreal sx, qreal sy)
467 if (qIsNaN(sx) || qIsNaN(sy)) {
468 nanWarning(
"fromScale");
472 QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1);
473 if (sx == 1. && sy == 1.)
474 transform.m_type = TxNone;
476 transform.m_type = TxScale;
477 transform.m_dirty = TxNone;
482
483
484
485
486
487QTransform & QTransform::shear(qreal sh, qreal sv)
489 if (sh == 0 && sv == 0)
492 if (qIsNaN(sh) || qIsNaN(sv)) {
498 switch(inline_type()) {
505 m_matrix[0][1] = sv*m_matrix[1][1];
506 m_matrix[1][0] = sh*m_matrix[0][0];
509 qreal tm13 = sv * m_matrix[1][2];
510 qreal tm23 = sh * m_matrix[0][2];
511 m_matrix[0][2] += tm13;
512 m_matrix[1][2] += tm23;
517 qreal tm11 = sv * m_matrix[1][0];
518 qreal tm22 = sh * m_matrix[0][1];
519 qreal tm12 = sv * m_matrix[1][1];
520 qreal tm21 = sh * m_matrix[0][0];
521 m_matrix[0][0] += tm11;
522 m_matrix[0][1] += tm12;
523 m_matrix[1][0] += tm21;
524 m_matrix[1][1] += tm22;
528 if (m_dirty < TxShear)
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554QTransform & QTransform::rotate(qreal a, Qt::Axis axis, qreal distanceToPlane)
559 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
560 nanWarning(
"rotate");
567 if (a == 90. || a == -270.)
569 else if (a == 270. || a == -90.)
574 qreal b = qDegreesToRadians(a);
579 if (axis == Qt::ZAxis) {
580 switch(inline_type()) {
583 m_matrix[0][0] = cosa;
584 m_matrix[0][1] = sina;
585 m_matrix[1][0] = -sina;
586 m_matrix[1][1] = cosa;
589 qreal tm11 = cosa * m_matrix[0][0];
590 qreal tm12 = sina * m_matrix[1][1];
591 qreal tm21 = -sina * m_matrix[0][0];
592 qreal tm22 = cosa * m_matrix[1][1];
593 m_matrix[0][0] = tm11;
594 m_matrix[0][1] = tm12;
595 m_matrix[1][0] = tm21;
596 m_matrix[1][1] = tm22;
600 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
601 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
602 m_matrix[0][2] = tm13;
603 m_matrix[1][2] = tm23;
608 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
609 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
610 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
611 qreal tm22 = -sina * m_matrix[0][1] + 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 if (m_dirty < TxRotate)
622 if (!qIsNull(distanceToPlane))
623 sina /= distanceToPlane;
626 if (axis == Qt::YAxis) {
627 result.m_matrix[0][0] = cosa;
628 result.m_matrix[0][2] = -sina;
630 result.m_matrix[1][1] = cosa;
631 result.m_matrix[1][2] = -sina;
633 result.m_type = TxProject;
634 *
this = result * *
this;
640#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
642
643
644
645
646
647
648
649
650
651
652QTransform &QTransform::rotate(qreal a, Qt::Axis axis)
654 return rotate(a, axis, 1024.0);
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis, qreal distanceToPlane)
682 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
683 nanWarning(
"rotateRadians");
687 qreal sina = qSin(a);
688 qreal cosa = qCos(a);
690 if (axis == Qt::ZAxis) {
691 switch(inline_type()) {
694 m_matrix[0][0] = cosa;
695 m_matrix[0][1] = sina;
696 m_matrix[1][0] = -sina;
697 m_matrix[1][1] = cosa;
700 qreal tm11 = cosa * m_matrix[0][0];
701 qreal tm12 = sina * m_matrix[1][1];
702 qreal tm21 = -sina * m_matrix[0][0];
703 qreal tm22 = cosa * m_matrix[1][1];
704 m_matrix[0][0] = tm11;
705 m_matrix[0][1] = tm12;
706 m_matrix[1][0] = tm21;
707 m_matrix[1][1] = tm22;
711 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
712 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
713 m_matrix[0][2] = tm13;
714 m_matrix[1][2] = tm23;
719 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
720 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
721 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
722 qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1];
723 m_matrix[0][0] = tm11;
724 m_matrix[0][1] = tm12;
725 m_matrix[1][0] = tm21;
726 m_matrix[1][1] = tm22;
730 if (m_dirty < TxRotate)
733 if (!qIsNull(distanceToPlane))
734 sina /= distanceToPlane;
737 if (axis == Qt::YAxis) {
738 result.m_matrix[0][0] = cosa;
739 result.m_matrix[0][2] = -sina;
741 result.m_matrix[1][1] = cosa;
742 result.m_matrix[1][2] = -sina;
744 result.m_type = TxProject;
745 *
this = result * *
this;
750#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
752
753
754
755
756
757
758
759
760
761
762QTransform &QTransform::rotateRadians(qreal a, Qt::Axis axis)
764 return rotateRadians(a, axis, 1024.0);
769
770
771
772
773bool QTransform::operator==(
const QTransform &o)
const
775 return m_matrix[0][0] == o.m_matrix[0][0] &&
776 m_matrix[0][1] == o.m_matrix[0][1] &&
777 m_matrix[1][0] == o.m_matrix[1][0] &&
778 m_matrix[1][1] == o.m_matrix[1][1] &&
779 m_matrix[2][0] == o.m_matrix[2][0] &&
780 m_matrix[2][1] == o.m_matrix[2][1] &&
781 m_matrix[0][2] == o.m_matrix[0][2] &&
782 m_matrix[1][2] == o.m_matrix[1][2] &&
783 m_matrix[2][2] == o.m_matrix[2][2];
787
788
789
792 QtPrivate::QHashCombineWithSeed hash(seed);
793 seed = hash(seed, key.m11());
794 seed = hash(seed, key.m12());
795 seed = hash(seed, key.m21());
796 seed = hash(seed, key.m22());
797 seed = hash(seed, key.dx());
798 seed = hash(seed, key.dy());
799 seed = hash(seed, key.m13());
800 seed = hash(seed, key.m23());
801 seed = hash(seed, key.m33());
807
808
809
810
811bool QTransform::operator!=(
const QTransform &o)
const
813 return !operator==(o);
817
818
819
820
821
822
823QTransform & QTransform::operator*=(
const QTransform &o)
825 const TransformationType otherType = o.inline_type();
826 if (otherType == TxNone)
829 const TransformationType thisType = inline_type();
830 if (thisType == TxNone)
833 TransformationType t = qMax(thisType, otherType);
838 m_matrix[2][0] += o.m_matrix[2][0];
839 m_matrix[2][1] += o.m_matrix[2][1];
843 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0];
844 qreal m22 = m_matrix[1][1] * o.m_matrix[1][1];
846 qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + o.m_matrix[2][0];
847 qreal m32 = m_matrix[2][1] * o.m_matrix[1][1] + o.m_matrix[2][1];
849 m_matrix[0][0] = m11;
850 m_matrix[1][1] = m22;
851 m_matrix[2][0] = m31; m_matrix[2][1] = m32;
857 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0] + m_matrix[0][1] * o.m_matrix[1][0];
858 qreal m12 = m_matrix[0][0] * o.m_matrix[0][1] + m_matrix[0][1] * o.m_matrix[1][1];
860 qreal m21 = m_matrix[1][0] * o.m_matrix[0][0] + m_matrix[1][1] * o.m_matrix[1][0];
861 qreal m22 = m_matrix[1][0] * o.m_matrix[0][1] + m_matrix[1][1] * o.m_matrix[1][1];
863 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];
864 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];
866 m_matrix[0][0] = m11;
867 m_matrix[0][1] = m12;
868 m_matrix[1][0] = m21;
869 m_matrix[1][1] = m22;
870 m_matrix[2][0] = m31;
871 m_matrix[2][1] = m32;
876 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];
877 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];
878 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];
880 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];
881 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];
882 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];
884 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];
885 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];
886 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];
888 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
889 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
890 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
901
902
903
904
905
906
907
908QTransform QTransform::operator*(
const QTransform &m)
const
910 const TransformationType otherType = m.inline_type();
911 if (otherType == TxNone)
914 const TransformationType thisType = inline_type();
915 if (thisType == TxNone)
919 TransformationType type = qMax(thisType, otherType);
924 t.m_matrix[2][0] = m_matrix[2][0] + m.m_matrix[2][0];
925 t.m_matrix[2][1] = m_matrix[2][1] + m.m_matrix[2][1];
929 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0];
930 qreal m22 = m_matrix[1][1] * m.m_matrix[1][1];
932 qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m.m_matrix[2][0];
933 qreal m32 = m_matrix[2][1] * m.m_matrix[1][1] + m.m_matrix[2][1];
935 t.m_matrix[0][0] = m11;
936 t.m_matrix[1][1] = m22;
937 t.m_matrix[2][0] = m31;
938 t.m_matrix[2][1] = m32;
944 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0] + m_matrix[0][1] * m.m_matrix[1][0];
945 qreal m12 = m_matrix[0][0] * m.m_matrix[0][1] + m_matrix[0][1] * m.m_matrix[1][1];
947 qreal m21 = m_matrix[1][0] * m.m_matrix[0][0] + m_matrix[1][1] * m.m_matrix[1][0];
948 qreal m22 = m_matrix[1][0] * m.m_matrix[0][1] + m_matrix[1][1] * m.m_matrix[1][1];
950 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];
951 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];
953 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12;
954 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22;
955 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32;
960 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];
961 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];
962 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];
964 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];
965 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];
966 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];
968 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];
969 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];
970 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];
972 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12; t.m_matrix[0][2] = m13;
973 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22; t.m_matrix[1][2] = m23;
974 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32; t.m_matrix[2][2] = m33;
985
986
987
988
989
990
993
994
995
996
997
998
1001
1002
1003
1004
1005
1006
1009
1010
1011
1012
1013
1014
1017
1018
1019
1020
1023
1024
1025
1026
1027
1028
1029
1030void QTransform::reset()
1032 *
this = QTransform();
1035#ifndef QT_NO_DATASTREAM
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046QDataStream & operator<<(QDataStream &s,
const QTransform &m)
1048 s <<
double(m.m11())
1061
1062
1063
1064
1065
1066
1067
1068
1069
1072 double m11, m12, m13,
1085 t.setMatrix(m11, m12, m13,
1093#ifndef QT_NO_DEBUG_STREAM
1096 static const char typeStr[][12] =
1105 "",
"",
"",
"",
"",
"",
"",
1109 QDebugStateSaver saver(dbg);
1110 dbg.nospace() <<
"QTransform(type=" << typeStr[m.type()] <<
','
1111 <<
" 11=" << m.m11()
1112 <<
" 12=" << m.m12()
1113 <<
" 13=" << m.m13()
1114 <<
" 21=" << m.m21()
1115 <<
" 22=" << m.m22()
1116 <<
" 23=" << m.m23()
1117 <<
" 31=" << m.m31()
1118 <<
" 32=" << m.m32()
1119 <<
" 33=" << m.m33()
1127
1128
1129
1130
1131
1132
1133
1134QPoint QTransform::map(
const QPoint &p)
const
1141 do_map(fx, fy, x, y);
1143 return QPoint(qRound(x), qRound(y));
1148
1149
1150
1151
1152
1153
1154
1157
1158
1159
1160
1161
1162QPointF QTransform::map(
const QPointF &p)
const
1169 do_map(fx, fy, x, y);
1171 return QPointF(x, y);
1175
1176
1177
1178
1179
1180
1181
1182
1185
1186
1187
1188
1189
1190
1191
1194
1195
1196
1197
1198
1199
1200
1203
1204
1205
1206
1207
1208QLine QTransform::map(
const QLine &l)
const
1215 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1217 do_map(fx1, fy1, x1, y1);
1218 do_map(fx2, fy2, x2, y2);
1220 return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1224
1225
1226
1227
1228
1229
1230
1231
1232
1234QLineF QTransform::map(
const QLineF &l)
const
1241 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1243 do_map(fx1, fy1, x1, y1);
1244 do_map(fx2, fy2, x2, y2);
1246 return QLineF(x1, y1, x2, y2);
1250
1251
1252
1253
1254
1255
1256
1257
1260
1261
1262
1263
1264
1265
1266
1269
1270
1271
1272
1273
1274
1275
1276QPolygonF QTransform::map(
const QPolygonF &a)
const
1278 TransformationType t = inline_type();
1279 if (t <= TxTranslate)
1280 return a.translated(m_matrix[2][0], m_matrix[2][1]);
1282 int size = a.size();
1285 const QPointF *da = a.constData();
1286 QPointF *dp = p.data();
1288 for(i = 0; i < size; ++i) {
1289 do_map(da[i].x(), da[i].y(), dp[i].rx(), dp[i].ry());
1295
1296
1297
1298
1299
1300
1301
1302
1303QPolygon QTransform::map(
const QPolygon &a)
const
1305 TransformationType t = inline_type();
1306 if (t <= TxTranslate)
1307 return a.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1309 int size = a.size();
1312 const QPoint *da = a.constData();
1313 QPoint *dp = p.data();
1315 for(i = 0; i < size; ++i) {
1316 qreal nx = 0, ny = 0;
1317 do_map(da[i].x(), da[i].y(), nx, ny);
1318 dp[i].rx() = qRound(nx);
1319 dp[i].ry() = qRound(ny);
1325
1326
1327
1328
1329
1330
1331
1333Q_GUI_EXPORT
extern QPainterPath qt_regionToPath(
const QRegion ®ion);
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345QRegion QTransform::map(
const QRegion &r)
const
1347 TransformationType t = inline_type();
1351 if (t == TxTranslate) {
1353 copy.translate(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1359 if (m11() < 0 || m22() < 0) {
1360 for (
const QRect &rect : r)
1361 res += qt_mapFillRect(QRectF(rect), *
this);
1363 QVarLengthArray<QRect, 32> rects;
1364 rects.reserve(r.rectCount());
1365 for (
const QRect &rect : r) {
1366 QRect nr = qt_mapFillRect(QRectF(rect), *
this);
1370 res.setRects(rects.constData(), rects.size());
1375 QPainterPath p = map(qt_regionToPath(r));
1376 return p.toFillPolygon().toPolygon();
1390 return QPointF(x * iw, y * iw);
1397 c.x = transform.m11() * p.x() + transform.m21() * p.y() + transform.m31();
1398 c.y = transform.m12() * p.x() + transform.m22() * p.y() + transform.m32();
1399 c.w = transform.m13() * p.x() + transform.m23() * p.y() + transform.m33();
1403static inline bool lineTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
1404 bool needsMoveTo,
bool needsLineTo =
true)
1406 QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1407 QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1413 const qreal t = (
Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1415 hb.x += (ha.x - hb.x) * t;
1416 hb.y += (ha.y - hb.y) * t;
1419 const qreal t = (
Q_NEAR_CLIP - ha.w) / (hb.w - ha.w);
1421 ha.x += (hb.x - ha.x) * t;
1422 ha.y += (hb.y - ha.y) * t;
1425 const QPointF p = ha.toPoint();
1428 needsMoveTo =
false;
1435 path.moveTo(ha.toPoint());
1438 path.lineTo(hb.toPoint());
1444static inline bool cubicTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
const QPointF &c,
const QPointF &d,
bool needsMoveTo)
1450 qt_scaleForTransform(transform, &scale);
1452 qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1454 QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1456 for (
int i = 0; i < segment.size() - 1; ++i)
1457 if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
1458 needsMoveTo =
false;
1460 return !needsMoveTo;
1463static QPainterPath
mapProjective(
const QTransform &transform,
const QPainterPath &path)
1465 QPainterPath result;
1469 bool needsMoveTo =
true;
1470 for (
int i = 0; i < path.elementCount(); ++i) {
1471 switch (path.elementAt(i).type) {
1472 case QPainterPath::MoveToElement:
1473 if (i > 0 && lastMoveTo != last)
1476 lastMoveTo = path.elementAt(i);
1477 last = path.elementAt(i);
1480 case QPainterPath::LineToElement:
1482 needsMoveTo =
false;
1483 last = path.elementAt(i);
1485 case QPainterPath::CurveToElement:
1486 if (
cubicTo_clipped(result
, transform
, last
, path.elementAt(i)
, path.elementAt(i+1)
, path.elementAt(i+2)
, needsMoveTo
))
1487 needsMoveTo =
false;
1489 last = path.elementAt(i);
1496 if (path.elementCount() > 0 && lastMoveTo != last)
1499 result.setFillRule(path.fillRule());
1504
1505
1506
1507
1508
1509
1510
1511
1514
1515
1516
1517
1518
1519
1520QPainterPath QTransform::map(
const QPainterPath &path)
const
1522 TransformationType t = inline_type();
1523 if (t == TxNone || path.elementCount() == 0)
1527 return mapProjective(*
this, path);
1529 QPainterPath copy = path;
1531 if (t == TxTranslate) {
1532 copy.translate(m_matrix[2][0], m_matrix[2][1]);
1534 copy.setDirty(
true);
1536 for (
int i=0; i<path.elementCount(); ++i) {
1537 QPainterPath::Element &e = copy.d_ptr->elements[i];
1538 do_map(e.x, e.y, e.x, e.y);
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565QPolygon QTransform::mapToPolygon(
const QRect &rect)
const
1567 TransformationType t = inline_type();
1570 qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1572 x[0] = m_matrix[0][0]*rect.x() + m_matrix[2][0];
1573 y[0] = m_matrix[1][1]*rect.y() + m_matrix[2][1];
1574 qreal w = m_matrix[0][0]*rect.width();
1575 qreal h = m_matrix[1][1]*rect.height();
1591 auto right = rect.x() + rect.width();
1592 auto bottom = rect.y() + rect.height();
1593 do_map(rect.x(), rect.y(), x[0], y[0]);
1594 do_map(right, rect.y(), x[1], y[1]);
1595 do_map(right, bottom, x[2], y[2]);
1596 do_map(rect.x(), bottom, x[3], y[3]);
1601 a.setPoints(4, qRound(x[0]), qRound(y[0]),
1602 qRound(x[1]), qRound(y[1]),
1603 qRound(x[2]), qRound(y[2]),
1604 qRound(x[3]), qRound(y[3]));
1609
1610
1611
1612
1613
1614
1615bool QTransform::squareToQuad(
const QPolygonF &quad, QTransform &trans)
1617 if (quad.size() != (quad.isClosed() ? 5 : 4))
1620 qreal dx0 = quad[0].x();
1621 qreal dx1 = quad[1].x();
1622 qreal dx2 = quad[2].x();
1623 qreal dx3 = quad[3].x();
1625 qreal dy0 = quad[0].y();
1626 qreal dy1 = quad[1].y();
1627 qreal dy2 = quad[2].y();
1628 qreal dy3 = quad[3].y();
1630 double ax = dx0 - dx1 + dx2 - dx3;
1631 double ay = dy0 - dy1 + dy2 - dy3;
1634 trans.setMatrix(dx1 - dx0, dy1 - dy0, 0,
1635 dx2 - dx1, dy2 - dy1, 0,
1638 double ax1 = dx1 - dx2;
1639 double ax2 = dx3 - dx2;
1640 double ay1 = dy1 - dy2;
1641 double ay2 = dy3 - dy2;
1644 double gtop = ax * ay2 - ax2 * ay;
1645 double htop = ax1 * ay - ax * ay1;
1646 double bottom = ax1 * ay2 - ax2 * ay1;
1648 double a, b, c, d, e, f, g, h;
1656 a = dx1 - dx0 + g * dx1;
1657 b = dx3 - dx0 + h * dx3;
1659 d = dy1 - dy0 + g * dy1;
1660 e = dy3 - dy0 + h * dy3;
1663 trans.setMatrix(a, d, g,
1672
1673
1674
1675
1676
1677
1678
1679
1680bool QTransform::quadToSquare(
const QPolygonF &quad, QTransform &trans)
1682 if (!squareToQuad(quad, trans))
1685 bool invertible =
false;
1686 trans = trans.inverted(&invertible);
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703bool QTransform::quadToQuad(
const QPolygonF &one,
1704 const QPolygonF &two,
1708 if (!quadToSquare(one, trans))
1710 if (!squareToQuad(two, stq))
1718
1719
1720
1721
1722
1723
1724
1725
1726
1728void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
1729 qreal m21, qreal m22, qreal m23,
1730 qreal m31, qreal m32, qreal m33)
1732 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
1733 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
1734 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
1736 m_dirty = TxProject;
1739QRect QTransform::mapRect(
const QRect &rect)
const
1741 TransformationType t = inline_type();
1742 if (t <= TxTranslate)
1743 return rect.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1746 int x = qRound(m_matrix[0][0] * rect.x() + m_matrix[2][0]);
1747 int y = qRound(m_matrix[1][1] * rect.y() + m_matrix[2][1]);
1748 int w = qRound(m_matrix[0][0] * rect.width());
1749 int h = qRound(m_matrix[1][1] * rect.height());
1758 return QRect(x, y, w, h);
1761 do_map(rect.left(), rect.top(), x, y);
1766 do_map(rect.right() + 1, rect.top(), x, y);
1767 xmin = qMin(xmin, x);
1768 ymin = qMin(ymin, y);
1769 xmax = qMax(xmax, x);
1770 ymax = qMax(ymax, y);
1771 do_map(rect.right() + 1, rect.bottom() + 1, x, y);
1772 xmin = qMin(xmin, x);
1773 ymin = qMin(ymin, y);
1774 xmax = qMax(xmax, x);
1775 ymax = qMax(ymax, y);
1776 do_map(rect.left(), rect.bottom() + 1, x, y);
1777 xmin = qMin(xmin, x);
1778 ymin = qMin(ymin, y);
1779 xmax = qMax(xmax, x);
1780 ymax = qMax(ymax, y);
1781 return QRectF(xmin, ymin, xmax-xmin, ymax-ymin).toRect();
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804QRectF QTransform::mapRect(
const QRectF &rect)
const
1806 TransformationType t = inline_type();
1807 if (t <= TxTranslate)
1808 return rect.translated(m_matrix[2][0], m_matrix[2][1]);
1811 qreal x = m_matrix[0][0] * rect.x() + m_matrix[2][0];
1812 qreal y = m_matrix[1][1] * rect.y() + m_matrix[2][1];
1813 qreal w = m_matrix[0][0] * rect.width();
1814 qreal h = m_matrix[1][1] * rect.height();
1823 return QRectF(x, y, w, h);
1826 do_map(rect.x(), rect.y(), x, y);
1831 do_map(rect.x() + rect.width(), rect.y(), x, y);
1832 xmin = qMin(xmin, x);
1833 ymin = qMin(ymin, y);
1834 xmax = qMax(xmax, x);
1835 ymax = qMax(ymax, y);
1836 do_map(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
1837 xmin = qMin(xmin, x);
1838 ymin = qMin(ymin, y);
1839 xmax = qMax(xmax, x);
1840 ymax = qMax(ymax, y);
1841 do_map(rect.x(), rect.y() + rect.height(), x, y);
1842 xmin = qMin(xmin, x);
1843 ymin = qMin(ymin, y);
1844 xmax = qMax(xmax, x);
1845 ymax = qMax(ymax, y);
1846 return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
1851
1852
1853
1854
1855
1856
1857
1858
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty)
const
1876 do_map(x, y, *tx, *ty);
1880
1881
1882
1883
1884
1885
1886
1887void QTransform::map(
int x,
int y,
int *tx,
int *ty)
const
1889 qreal fx = 0, fy = 0;
1890 do_map(x, y, fx, fy);
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907QTransform::TransformationType QTransform::type()
const
1909 if (m_dirty == TxNone || m_dirty < m_type)
1910 return static_cast<TransformationType>(m_type);
1912 switch (
static_cast<TransformationType>(m_dirty)) {
1914 if (!qFuzzyIsNull(m_matrix[0][2]) || !qFuzzyIsNull(m_matrix[1][2]) || !qFuzzyIsNull(m_matrix[2][2] - 1)) {
1921 if (!qFuzzyIsNull(m_matrix[0][1]) || !qFuzzyIsNull(m_matrix[1][0])) {
1922 const qreal dot = m_matrix[0][0] * m_matrix[1][0] + m_matrix[0][1] * m_matrix[1][1];
1923 if (qFuzzyIsNull(dot))
1931 if (!qFuzzyIsNull(m_matrix[0][0] - 1) || !qFuzzyIsNull(m_matrix[1][1] - 1)) {
1937 if (!qFuzzyIsNull(m_matrix[2][0]) || !qFuzzyIsNull(m_matrix[2][1])) {
1938 m_type = TxTranslate;
1948 return static_cast<TransformationType>(m_type);
1952
1953
1954
1955QTransform::operator QVariant()
const
1957 return QVariant::fromValue(*
this);
1962
1963
1964
1965
1966
1967
1970
1971
1972
1973
1974
1975
1976
1979
1980
1981
1982
1983
1984
1985
1988
1989
1990
1991
1992
1993
1994
1997
1998
1999
2000
2001
2002
2003
2006
2007
2008
2009
2010
2011
2012
2015
2016
2017
2018
2019
2020
2021
2025
2026
2027
2028
2029
2030
2031
2035
2036
2037
2038
2039
2040
2041
2044
2045
2046
2047
2048
2049
2050
2053
2054
2055
2056
2057
2058
2059
2062
2063
2064
2065
2066
2067
2068
2071
2072
2073
2074
2077
2078
2079
2080
2081
2082
2083
2086
2087
2088
2089
2090
2093
2094
2095
2096
2097
2098
2099
2102
2103
2104
2105
2106
2107
2108
2109
2110
2113
2114
2115
2116
2117
2118
2119
2122
2123
2124
2125
2126
2127
2128
2129
2138 const QTransform::TransformationType type = transform.type();
2139 if (type <= QTransform::TxTranslate) {
2143 }
else if (type == QTransform::TxScale) {
2144 const qreal xScale = qAbs(transform.m11());
2145 const qreal yScale = qAbs(transform.m22());
2147 *scale = qMax(xScale, yScale);
2148 return qFuzzyCompare(xScale, yScale);
2152 const qreal xScale1 = transform.m11() * transform.m11()
2153 + transform.m21() * transform.m21();
2154 const qreal yScale1 = transform.m12() * transform.m12()
2155 + transform.m22() * transform.m22();
2158 const qreal xScale2 = transform.m11() * transform.m11()
2159 + transform.m12() * transform.m12();
2160 const qreal yScale2 = transform.m21() * transform.m21()
2161 + transform.m22() * transform.m22();
2164 if (qAbs(xScale1 - yScale1) > qAbs(xScale2 - yScale2)) {
2166 *scale = qSqrt(qMax(xScale1, yScale1));
2168 return type == QTransform::TxRotate && qFuzzyCompare(xScale1, yScale1);
2171 *scale = qSqrt(qMax(xScale2, yScale2));
2173 return type == QTransform::TxRotate && qFuzzyCompare(xScale2, yScale2);
2177QDataStream &
operator>>(QDataStream &s, QTransform::Affine &m)
2179 if (s.version() == 1) {
2180 float m11, m12, m21, m22, dx, dy;
2181 s >> m11; s >> m12; s >> m21; s >> m22; s >> dx; s >> dy;
2183 m.m_matrix[0][0] = m11;
2184 m.m_matrix[0][1] = m12;
2185 m.m_matrix[1][0] = m21;
2186 m.m_matrix[1][1] = m22;
2187 m.m_matrix[2][0] = dx;
2188 m.m_matrix[2][1] = dy;
2190 s >> m.m_matrix[0][0];
2191 s >> m.m_matrix[0][1];
2192 s >> m.m_matrix[1][0];
2193 s >> m.m_matrix[1][1];
2194 s >> m.m_matrix[2][0];
2195 s >> m.m_matrix[2][1];
2197 m.m_matrix[0][2] = 0;
2198 m.m_matrix[1][2] = 0;
2199 m.m_matrix[2][2] = 1;
2203QDataStream &operator<<(QDataStream &s,
const QTransform::Affine &m)
2205 if (s.version() == 1) {
2206 s << (
float)m.m_matrix[0][0]
2207 << (
float)m.m_matrix[0][1]
2208 << (
float)m.m_matrix[1][0]
2209 << (
float)m.m_matrix[1][1]
2210 << (
float)m.m_matrix[2][0]
2211 << (
float)m.m_matrix[2][1];
2213 s << m.m_matrix[0][0]
2218 << 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_)