15#include <private/qbezier_p.h>
21static void nanWarning(
const char *func)
23 qWarning(
"QTransform::%s with NaN called", func);
27#define Q_NEAR_CLIP (sizeof(qreal) == sizeof(double) ? 0.000001
: 0.0001
)
29void QTransform::do_map(qreal x, qreal y, qreal &nx, qreal &ny)
const
31 const TransformationType t = inline_type();
33 case QTransform::TxNone:
37 case QTransform::TxTranslate:
38 nx = x + m_matrix[2][0];
39 ny = y + m_matrix[2][1];
41 case QTransform::TxScale:
42 nx = m_matrix[0][0] * x + m_matrix[2][0];
43 ny = m_matrix[1][1] * y + m_matrix[2][1];
45 case QTransform::TxRotate:
46 case QTransform::TxShear:
47 case QTransform::TxProject:
48 nx = m_matrix[0][0] * x + m_matrix[1][0] * y + m_matrix[2][0];
49 ny = m_matrix[0][1] * x + m_matrix[1][1] * y + m_matrix[2][1];
50 if (t == QTransform::TxProject) {
51 qreal w = (m_matrix[0][2] * x + m_matrix[1][2] * y + m_matrix[2][2]);
59 Q_UNREACHABLE_RETURN();
63
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
213
214
215
216
217
218
219
220
221
224
225
226
229
230
231
232
233
234
235
236
237
240
241
242
243
244
245
246
249
250
251
252
253
254
257
258
259QTransform QTransform::adjoint()
const
264 h11 = m_matrix[1][1] * m_matrix[2][2] - m_matrix[1][2] * m_matrix[2][1];
265 h21 = m_matrix[1][2] * m_matrix[2][0] - m_matrix[1][0] * m_matrix[2][2];
266 h31 = m_matrix[1][0] * m_matrix[2][1] - m_matrix[1][1] * m_matrix[2][0];
267 h12 = m_matrix[0][2] * m_matrix[2][1] - m_matrix[0][1] * m_matrix[2][2];
268 h22 = m_matrix[0][0] * m_matrix[2][2] - m_matrix[0][2] * m_matrix[2][0];
269 h32 = m_matrix[0][1] * m_matrix[2][0] - m_matrix[0][0] * m_matrix[2][1];
270 h13 = m_matrix[0][1] * m_matrix[1][2] - m_matrix[0][2] * m_matrix[1][1];
271 h23 = m_matrix[0][2] * m_matrix[1][0] - m_matrix[0][0] * m_matrix[1][2];
272 h33 = m_matrix[0][0] * m_matrix[1][1] - m_matrix[0][1] * m_matrix[1][0];
274 return QTransform(h11, h12, h13,
280
281
282QTransform QTransform::transposed()
const
284 QTransform t(m_matrix[0][0], m_matrix[1][0], m_matrix[2][0],
285 m_matrix[0][1], m_matrix[1][1], m_matrix[2][1],
286 m_matrix[0][2], m_matrix[1][2], m_matrix[2][2]);
291
292
293
294
295
296
297
298
299
300QTransform QTransform::inverted(
bool *invertible)
const
305 switch(inline_type()) {
309 invert.m_matrix[2][0] = -m_matrix[2][0];
310 invert.m_matrix[2][1] = -m_matrix[2][1];
313 inv = !qFuzzyIsNull(m_matrix[0][0]);
314 inv &= !qFuzzyIsNull(m_matrix[1][1]);
316 invert.m_matrix[0][0] = 1. / m_matrix[0][0];
317 invert.m_matrix[1][1] = 1. / m_matrix[1][1];
318 invert.m_matrix[2][0] = -m_matrix[2][0] * invert.m_matrix[0][0];
319 invert.m_matrix[2][1] = -m_matrix[2][1] * invert.m_matrix[1][1];
324 qreal det = determinant();
325 inv = !qFuzzyIsNull(det);
327 invert = adjoint() / det;
336 invert.m_type = m_type;
337 invert.m_dirty = m_dirty;
344
345
346
347
348
349QTransform &QTransform::translate(qreal dx, qreal dy)
351 if (dx == 0 && dy == 0)
354 if (qIsNaN(dx) || qIsNaN(dy)) {
355 nanWarning(
"translate");
360 switch(inline_type()) {
366 m_matrix[2][0] += dx;
367 m_matrix[2][1] += dy;
370 m_matrix[2][0] += dx * m_matrix[0][0];
371 m_matrix[2][1] += dy * m_matrix[1][1];
374 m_matrix[2][2] += dx * m_matrix[0][2] + dy * m_matrix[1][2];
378 m_matrix[2][0] += dx * m_matrix[0][0] + dy * m_matrix[1][0];
379 m_matrix[2][1] += dy * m_matrix[1][1] + dx * m_matrix[0][1];
382 if (m_dirty < TxTranslate)
383 m_dirty = TxTranslate;
388
389
390
391
392
393
394QTransform QTransform::fromTranslate(qreal dx, qreal dy)
397 if (qIsNaN(dx) || qIsNaN(dy)) {
398 nanWarning(
"fromTranslate");
402 QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1);
403 if (dx == 0 && dy == 0)
404 transform.m_type = TxNone;
406 transform.m_type = TxTranslate;
407 transform.m_dirty = TxNone;
412
413
414
415
416
417QTransform & QTransform::scale(qreal sx, qreal sy)
419 if (sx == 1 && sy == 1)
422 if (qIsNaN(sx) || qIsNaN(sy)) {
428 switch(inline_type()) {
435 m_matrix[0][2] *= sx;
436 m_matrix[1][2] *= sy;
440 m_matrix[0][1] *= sx;
441 m_matrix[1][0] *= sy;
444 m_matrix[0][0] *= sx;
445 m_matrix[1][1] *= sy;
448 if (m_dirty < TxScale)
454
455
456
457
458
459
460QTransform QTransform::fromScale(qreal sx, qreal sy)
463 if (qIsNaN(sx) || qIsNaN(sy)) {
464 nanWarning(
"fromScale");
468 QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1);
469 if (sx == 1. && sy == 1.)
470 transform.m_type = TxNone;
472 transform.m_type = TxScale;
473 transform.m_dirty = TxNone;
478
479
480
481
482
483QTransform & QTransform::shear(qreal sh, qreal sv)
485 if (sh == 0 && sv == 0)
488 if (qIsNaN(sh) || qIsNaN(sv)) {
494 switch(inline_type()) {
501 m_matrix[0][1] = sv*m_matrix[1][1];
502 m_matrix[1][0] = sh*m_matrix[0][0];
505 qreal tm13 = sv * m_matrix[1][2];
506 qreal tm23 = sh * m_matrix[0][2];
507 m_matrix[0][2] += tm13;
508 m_matrix[1][2] += tm23;
513 qreal tm11 = sv * m_matrix[1][0];
514 qreal tm22 = sh * m_matrix[0][1];
515 qreal tm12 = sv * m_matrix[1][1];
516 qreal tm21 = sh * m_matrix[0][0];
517 m_matrix[0][0] += tm11;
518 m_matrix[0][1] += tm12;
519 m_matrix[1][0] += tm21;
520 m_matrix[1][1] += tm22;
524 if (m_dirty < TxShear)
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550QTransform & QTransform::rotate(qreal a, Qt::Axis axis, qreal distanceToPlane)
555 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
556 nanWarning(
"rotate");
563 if (a == 90. || a == -270.)
565 else if (a == 270. || a == -90.)
570 qreal b = qDegreesToRadians(a);
575 if (axis == Qt::ZAxis) {
576 switch(inline_type()) {
579 m_matrix[0][0] = cosa;
580 m_matrix[0][1] = sina;
581 m_matrix[1][0] = -sina;
582 m_matrix[1][1] = cosa;
585 qreal tm11 = cosa * m_matrix[0][0];
586 qreal tm12 = sina * m_matrix[1][1];
587 qreal tm21 = -sina * m_matrix[0][0];
588 qreal tm22 = cosa * m_matrix[1][1];
589 m_matrix[0][0] = tm11;
590 m_matrix[0][1] = tm12;
591 m_matrix[1][0] = tm21;
592 m_matrix[1][1] = tm22;
596 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
597 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
598 m_matrix[0][2] = tm13;
599 m_matrix[1][2] = tm23;
604 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
605 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
606 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
607 qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1];
608 m_matrix[0][0] = tm11;
609 m_matrix[0][1] = tm12;
610 m_matrix[1][0] = tm21;
611 m_matrix[1][1] = tm22;
615 if (m_dirty < TxRotate)
618 if (!qIsNull(distanceToPlane))
619 sina /= distanceToPlane;
622 if (axis == Qt::YAxis) {
623 result.m_matrix[0][0] = cosa;
624 result.m_matrix[0][2] = -sina;
626 result.m_matrix[1][1] = cosa;
627 result.m_matrix[1][2] = -sina;
629 result.m_type = TxProject;
630 *
this = result * *
this;
636#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
638
639
640
641
642
643
644
645
646
647
648QTransform &QTransform::rotate(qreal a, Qt::Axis axis)
650 return rotate(a, axis, 1024.0);
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis, qreal distanceToPlane)
678 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
679 nanWarning(
"rotateRadians");
683 qreal sina = qSin(a);
684 qreal cosa = qCos(a);
686 if (axis == Qt::ZAxis) {
687 switch(inline_type()) {
690 m_matrix[0][0] = cosa;
691 m_matrix[0][1] = sina;
692 m_matrix[1][0] = -sina;
693 m_matrix[1][1] = cosa;
696 qreal tm11 = cosa * m_matrix[0][0];
697 qreal tm12 = sina * m_matrix[1][1];
698 qreal tm21 = -sina * m_matrix[0][0];
699 qreal tm22 = cosa * m_matrix[1][1];
700 m_matrix[0][0] = tm11;
701 m_matrix[0][1] = tm12;
702 m_matrix[1][0] = tm21;
703 m_matrix[1][1] = tm22;
707 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
708 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
709 m_matrix[0][2] = tm13;
710 m_matrix[1][2] = tm23;
715 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
716 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
717 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
718 qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1];
719 m_matrix[0][0] = tm11;
720 m_matrix[0][1] = tm12;
721 m_matrix[1][0] = tm21;
722 m_matrix[1][1] = tm22;
726 if (m_dirty < TxRotate)
729 if (!qIsNull(distanceToPlane))
730 sina /= distanceToPlane;
733 if (axis == Qt::YAxis) {
734 result.m_matrix[0][0] = cosa;
735 result.m_matrix[0][2] = -sina;
737 result.m_matrix[1][1] = cosa;
738 result.m_matrix[1][2] = -sina;
740 result.m_type = TxProject;
741 *
this = result * *
this;
746#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
748
749
750
751
752
753
754
755
756
757
758QTransform &QTransform::rotateRadians(qreal a, Qt::Axis axis)
760 return rotateRadians(a, axis, 1024.0);
765
766
767
768
769bool QTransform::operator==(
const QTransform &o)
const
771 return m_matrix[0][0] == o.m_matrix[0][0] &&
772 m_matrix[0][1] == o.m_matrix[0][1] &&
773 m_matrix[1][0] == o.m_matrix[1][0] &&
774 m_matrix[1][1] == o.m_matrix[1][1] &&
775 m_matrix[2][0] == o.m_matrix[2][0] &&
776 m_matrix[2][1] == o.m_matrix[2][1] &&
777 m_matrix[0][2] == o.m_matrix[0][2] &&
778 m_matrix[1][2] == o.m_matrix[1][2] &&
779 m_matrix[2][2] == o.m_matrix[2][2];
783
784
785
788 QtPrivate::QHashCombineWithSeed hash(seed);
789 seed = hash(seed, key.m11());
790 seed = hash(seed, key.m12());
791 seed = hash(seed, key.m21());
792 seed = hash(seed, key.m22());
793 seed = hash(seed, key.dx());
794 seed = hash(seed, key.dy());
795 seed = hash(seed, key.m13());
796 seed = hash(seed, key.m23());
797 seed = hash(seed, key.m33());
803
804
805
806
807bool QTransform::operator!=(
const QTransform &o)
const
809 return !operator==(o);
813
814
815
816
817
818
819QTransform & QTransform::operator*=(
const QTransform &o)
821 const TransformationType otherType = o.inline_type();
822 if (otherType == TxNone)
825 const TransformationType thisType = inline_type();
826 if (thisType == TxNone)
829 TransformationType t = qMax(thisType, otherType);
834 m_matrix[2][0] += o.m_matrix[2][0];
835 m_matrix[2][1] += o.m_matrix[2][1];
839 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0];
840 qreal m22 = m_matrix[1][1] * o.m_matrix[1][1];
842 qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + o.m_matrix[2][0];
843 qreal m32 = m_matrix[2][1] * o.m_matrix[1][1] + o.m_matrix[2][1];
845 m_matrix[0][0] = m11;
846 m_matrix[1][1] = m22;
847 m_matrix[2][0] = m31; m_matrix[2][1] = m32;
853 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0] + m_matrix[0][1] * o.m_matrix[1][0];
854 qreal m12 = m_matrix[0][0] * o.m_matrix[0][1] + m_matrix[0][1] * o.m_matrix[1][1];
856 qreal m21 = m_matrix[1][0] * o.m_matrix[0][0] + m_matrix[1][1] * o.m_matrix[1][0];
857 qreal m22 = m_matrix[1][0] * o.m_matrix[0][1] + m_matrix[1][1] * o.m_matrix[1][1];
859 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];
860 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];
862 m_matrix[0][0] = m11;
863 m_matrix[0][1] = m12;
864 m_matrix[1][0] = m21;
865 m_matrix[1][1] = m22;
866 m_matrix[2][0] = m31;
867 m_matrix[2][1] = m32;
872 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];
873 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];
874 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];
876 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];
877 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];
878 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];
880 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];
881 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];
882 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];
884 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
885 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
886 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
897
898
899
900
901
902
903
904QTransform QTransform::operator*(
const QTransform &m)
const
906 const TransformationType otherType = m.inline_type();
907 if (otherType == TxNone)
910 const TransformationType thisType = inline_type();
911 if (thisType == TxNone)
915 TransformationType type = qMax(thisType, otherType);
920 t.m_matrix[2][0] = m_matrix[2][0] + m.m_matrix[2][0];
921 t.m_matrix[2][1] = m_matrix[2][1] + m.m_matrix[2][1];
925 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0];
926 qreal m22 = m_matrix[1][1] * m.m_matrix[1][1];
928 qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m.m_matrix[2][0];
929 qreal m32 = m_matrix[2][1] * m.m_matrix[1][1] + m.m_matrix[2][1];
931 t.m_matrix[0][0] = m11;
932 t.m_matrix[1][1] = m22;
933 t.m_matrix[2][0] = m31;
934 t.m_matrix[2][1] = m32;
940 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0] + m_matrix[0][1] * m.m_matrix[1][0];
941 qreal m12 = m_matrix[0][0] * m.m_matrix[0][1] + m_matrix[0][1] * m.m_matrix[1][1];
943 qreal m21 = m_matrix[1][0] * m.m_matrix[0][0] + m_matrix[1][1] * m.m_matrix[1][0];
944 qreal m22 = m_matrix[1][0] * m.m_matrix[0][1] + m_matrix[1][1] * m.m_matrix[1][1];
946 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];
947 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];
949 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12;
950 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22;
951 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32;
956 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];
957 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];
958 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];
960 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];
961 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];
962 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];
964 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];
965 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];
966 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];
968 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12; t.m_matrix[0][2] = m13;
969 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22; t.m_matrix[1][2] = m23;
970 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32; t.m_matrix[2][2] = m33;
981
982
983
984
985
986
989
990
991
992
993
994
997
998
999
1000
1001
1002
1005
1006
1007
1008
1009
1010
1013
1014
1015
1016
1019
1020
1021
1022
1023
1024
1025
1026void QTransform::reset()
1028 *
this = QTransform();
1031#ifndef QT_NO_DATASTREAM
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042QDataStream & operator<<(QDataStream &s,
const QTransform &m)
1044 s <<
double(m.m11())
1057
1058
1059
1060
1061
1062
1063
1064
1065
1068 double m11, m12, m13,
1081 t.setMatrix(m11, m12, m13,
1089#ifndef QT_NO_DEBUG_STREAM
1092 static const char typeStr[][12] =
1101 "",
"",
"",
"",
"",
"",
"",
1105 QDebugStateSaver saver(dbg);
1106 dbg.nospace() <<
"QTransform(type=" << typeStr[m.type()] <<
','
1107 <<
" 11=" << m.m11()
1108 <<
" 12=" << m.m12()
1109 <<
" 13=" << m.m13()
1110 <<
" 21=" << m.m21()
1111 <<
" 22=" << m.m22()
1112 <<
" 23=" << m.m23()
1113 <<
" 31=" << m.m31()
1114 <<
" 32=" << m.m32()
1115 <<
" 33=" << m.m33()
1123
1124
1125
1126
1127
1128
1129
1130QPoint QTransform::map(
const QPoint &p)
const
1137 do_map(fx, fy, x, y);
1139 return QPoint(qRound(x), qRound(y));
1144
1145
1146
1147
1148
1149
1150
1153
1154
1155
1156
1157
1158QPointF QTransform::map(
const QPointF &p)
const
1165 do_map(fx, fy, x, y);
1167 return QPointF(x, y);
1171
1172
1173
1174
1175
1176
1177
1178
1181
1182
1183
1184
1185
1186
1187
1190
1191
1192
1193
1194
1195
1196
1199
1200
1201
1202
1203
1204QLine QTransform::map(
const QLine &l)
const
1211 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1213 do_map(fx1, fy1, x1, y1);
1214 do_map(fx2, fy2, x2, y2);
1216 return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1220
1221
1222
1223
1224
1225
1226
1227
1228
1230QLineF QTransform::map(
const QLineF &l)
const
1237 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1239 do_map(fx1, fy1, x1, y1);
1240 do_map(fx2, fy2, x2, y2);
1242 return QLineF(x1, y1, x2, y2);
1246
1247
1248
1249
1250
1251
1252
1253
1256
1257
1258
1259
1260
1261
1262
1265
1266
1267
1268
1269
1270
1271
1272QPolygonF QTransform::map(
const QPolygonF &a)
const
1274 TransformationType t = inline_type();
1275 if (t <= TxTranslate)
1276 return a.translated(m_matrix[2][0], m_matrix[2][1]);
1278 int size = a.size();
1281 const QPointF *da = a.constData();
1282 QPointF *dp = p.data();
1284 for(i = 0; i < size; ++i) {
1285 do_map(da[i].x(), da[i].y(), dp[i].rx(), dp[i].ry());
1291
1292
1293
1294
1295
1296
1297
1298
1299QPolygon QTransform::map(
const QPolygon &a)
const
1301 TransformationType t = inline_type();
1302 if (t <= TxTranslate)
1303 return a.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1305 int size = a.size();
1308 const QPoint *da = a.constData();
1309 QPoint *dp = p.data();
1311 for(i = 0; i < size; ++i) {
1312 qreal nx = 0, ny = 0;
1313 do_map(da[i].x(), da[i].y(), nx, ny);
1314 dp[i].rx() = qRound(nx);
1315 dp[i].ry() = qRound(ny);
1321
1322
1323
1324
1325
1326
1327
1329Q_GUI_EXPORT
extern QPainterPath qt_regionToPath(
const QRegion ®ion);
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341QRegion QTransform::map(
const QRegion &r)
const
1343 TransformationType t = inline_type();
1347 if (t == TxTranslate) {
1349 copy.translate(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1355 if (m11() < 0 || m22() < 0) {
1356 for (
const QRect &rect : r)
1357 res += qt_mapFillRect(QRectF(rect), *
this);
1359 QVarLengthArray<QRect, 32> rects;
1360 rects.reserve(r.rectCount());
1361 for (
const QRect &rect : r) {
1362 QRect nr = qt_mapFillRect(QRectF(rect), *
this);
1366 res.setRects(rects.constData(), rects.size());
1371 QPainterPath p = map(qt_regionToPath(r));
1372 return p.toFillPolygon().toPolygon();
1386 return QPointF(x * iw, y * iw);
1393 c.x = transform.m11() * p.x() + transform.m21() * p.y() + transform.m31();
1394 c.y = transform.m12() * p.x() + transform.m22() * p.y() + transform.m32();
1395 c.w = transform.m13() * p.x() + transform.m23() * p.y() + transform.m33();
1399static inline bool lineTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
1400 bool needsMoveTo,
bool needsLineTo =
true)
1402 QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1403 QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1409 const qreal t = (
Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1411 hb.x += (ha.x - hb.x) * t;
1412 hb.y += (ha.y - hb.y) * t;
1415 const qreal t = (
Q_NEAR_CLIP - ha.w) / (hb.w - ha.w);
1417 ha.x += (hb.x - ha.x) * t;
1418 ha.y += (hb.y - ha.y) * t;
1421 const QPointF p = ha.toPoint();
1424 needsMoveTo =
false;
1431 path.moveTo(ha.toPoint());
1434 path.lineTo(hb.toPoint());
1440static inline bool cubicTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
const QPointF &c,
const QPointF &d,
bool needsMoveTo)
1446 qt_scaleForTransform(transform, &scale);
1448 qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1450 QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1452 for (
int i = 0; i < segment.size() - 1; ++i)
1453 if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
1454 needsMoveTo =
false;
1456 return !needsMoveTo;
1459static QPainterPath
mapProjective(
const QTransform &transform,
const QPainterPath &path)
1461 QPainterPath result;
1465 bool needsMoveTo =
true;
1466 for (
int i = 0; i < path.elementCount(); ++i) {
1467 switch (path.elementAt(i).type) {
1468 case QPainterPath::MoveToElement:
1469 if (i > 0 && lastMoveTo != last)
1472 lastMoveTo = path.elementAt(i);
1473 last = path.elementAt(i);
1476 case QPainterPath::LineToElement:
1478 needsMoveTo =
false;
1479 last = path.elementAt(i);
1481 case QPainterPath::CurveToElement:
1482 if (
cubicTo_clipped(result
, transform
, last
, path.elementAt(i)
, path.elementAt(i+1)
, path.elementAt(i+2)
, needsMoveTo
))
1483 needsMoveTo =
false;
1485 last = path.elementAt(i);
1492 if (path.elementCount() > 0 && lastMoveTo != last)
1495 result.setFillRule(path.fillRule());
1500
1501
1502
1503
1504
1505
1506
1507
1510
1511
1512
1513
1514
1515
1516QPainterPath QTransform::map(
const QPainterPath &path)
const
1518 TransformationType t = inline_type();
1519 if (t == TxNone || path.elementCount() == 0)
1523 return mapProjective(*
this, path);
1525 QPainterPath copy = path;
1527 if (t == TxTranslate) {
1528 copy.translate(m_matrix[2][0], m_matrix[2][1]);
1530 copy.setDirty(
true);
1532 for (
int i=0; i<path.elementCount(); ++i) {
1533 QPainterPath::Element &e = copy.d_ptr->elements[i];
1534 do_map(e.x, e.y, e.x, e.y);
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561QPolygon QTransform::mapToPolygon(
const QRect &rect)
const
1563 TransformationType t = inline_type();
1566 qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1568 x[0] = m_matrix[0][0]*rect.x() + m_matrix[2][0];
1569 y[0] = m_matrix[1][1]*rect.y() + m_matrix[2][1];
1570 qreal w = m_matrix[0][0]*rect.width();
1571 qreal h = m_matrix[1][1]*rect.height();
1587 auto right = rect.x() + rect.width();
1588 auto bottom = rect.y() + rect.height();
1589 do_map(rect.x(), rect.y(), x[0], y[0]);
1590 do_map(right, rect.y(), x[1], y[1]);
1591 do_map(right, bottom, x[2], y[2]);
1592 do_map(rect.x(), bottom, x[3], y[3]);
1597 a.setPoints(4, qRound(x[0]), qRound(y[0]),
1598 qRound(x[1]), qRound(y[1]),
1599 qRound(x[2]), qRound(y[2]),
1600 qRound(x[3]), qRound(y[3]));
1605
1606
1607
1608
1609
1610
1611bool QTransform::squareToQuad(
const QPolygonF &quad, QTransform &trans)
1613 if (quad.size() != (quad.isClosed() ? 5 : 4))
1616 qreal dx0 = quad[0].x();
1617 qreal dx1 = quad[1].x();
1618 qreal dx2 = quad[2].x();
1619 qreal dx3 = quad[3].x();
1621 qreal dy0 = quad[0].y();
1622 qreal dy1 = quad[1].y();
1623 qreal dy2 = quad[2].y();
1624 qreal dy3 = quad[3].y();
1626 double ax = dx0 - dx1 + dx2 - dx3;
1627 double ay = dy0 - dy1 + dy2 - dy3;
1630 trans.setMatrix(dx1 - dx0, dy1 - dy0, 0,
1631 dx2 - dx1, dy2 - dy1, 0,
1634 double ax1 = dx1 - dx2;
1635 double ax2 = dx3 - dx2;
1636 double ay1 = dy1 - dy2;
1637 double ay2 = dy3 - dy2;
1640 double gtop = ax * ay2 - ax2 * ay;
1641 double htop = ax1 * ay - ax * ay1;
1642 double bottom = ax1 * ay2 - ax2 * ay1;
1644 double a, b, c, d, e, f, g, h;
1652 a = dx1 - dx0 + g * dx1;
1653 b = dx3 - dx0 + h * dx3;
1655 d = dy1 - dy0 + g * dy1;
1656 e = dy3 - dy0 + h * dy3;
1659 trans.setMatrix(a, d, g,
1668
1669
1670
1671
1672
1673
1674
1675
1676bool QTransform::quadToSquare(
const QPolygonF &quad, QTransform &trans)
1678 if (!squareToQuad(quad, trans))
1681 bool invertible =
false;
1682 trans = trans.inverted(&invertible);
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699bool QTransform::quadToQuad(
const QPolygonF &one,
1700 const QPolygonF &two,
1704 if (!quadToSquare(one, trans))
1706 if (!squareToQuad(two, stq))
1714
1715
1716
1717
1718
1719
1720
1721
1722
1724void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
1725 qreal m21, qreal m22, qreal m23,
1726 qreal m31, qreal m32, qreal m33)
1728 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
1729 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
1730 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
1732 m_dirty = TxProject;
1735QRect QTransform::mapRect(
const QRect &rect)
const
1737 TransformationType t = inline_type();
1738 if (t <= TxTranslate)
1739 return rect.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1742 int x = qRound(m_matrix[0][0] * rect.x() + m_matrix[2][0]);
1743 int y = qRound(m_matrix[1][1] * rect.y() + m_matrix[2][1]);
1744 int w = qRound(m_matrix[0][0] * rect.width());
1745 int h = qRound(m_matrix[1][1] * rect.height());
1754 return QRect(x, y, w, h);
1757 do_map(rect.left(), rect.top(), x, y);
1762 do_map(rect.right() + 1, rect.top(), x, y);
1763 xmin = qMin(xmin, x);
1764 ymin = qMin(ymin, y);
1765 xmax = qMax(xmax, x);
1766 ymax = qMax(ymax, y);
1767 do_map(rect.right() + 1, rect.bottom() + 1, x, y);
1768 xmin = qMin(xmin, x);
1769 ymin = qMin(ymin, y);
1770 xmax = qMax(xmax, x);
1771 ymax = qMax(ymax, y);
1772 do_map(rect.left(), rect.bottom() + 1, x, y);
1773 xmin = qMin(xmin, x);
1774 ymin = qMin(ymin, y);
1775 xmax = qMax(xmax, x);
1776 ymax = qMax(ymax, y);
1777 return QRectF(xmin, ymin, xmax-xmin, ymax-ymin).toRect();
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800QRectF QTransform::mapRect(
const QRectF &rect)
const
1802 TransformationType t = inline_type();
1803 if (t <= TxTranslate)
1804 return rect.translated(m_matrix[2][0], m_matrix[2][1]);
1807 qreal x = m_matrix[0][0] * rect.x() + m_matrix[2][0];
1808 qreal y = m_matrix[1][1] * rect.y() + m_matrix[2][1];
1809 qreal w = m_matrix[0][0] * rect.width();
1810 qreal h = m_matrix[1][1] * rect.height();
1819 return QRectF(x, y, w, h);
1822 do_map(rect.x(), rect.y(), x, y);
1827 do_map(rect.x() + rect.width(), rect.y(), x, y);
1828 xmin = qMin(xmin, x);
1829 ymin = qMin(ymin, y);
1830 xmax = qMax(xmax, x);
1831 ymax = qMax(ymax, y);
1832 do_map(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
1833 xmin = qMin(xmin, x);
1834 ymin = qMin(ymin, y);
1835 xmax = qMax(xmax, x);
1836 ymax = qMax(ymax, y);
1837 do_map(rect.x(), rect.y() + rect.height(), x, y);
1838 xmin = qMin(xmin, x);
1839 ymin = qMin(ymin, y);
1840 xmax = qMax(xmax, x);
1841 ymax = qMax(ymax, y);
1842 return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
1847
1848
1849
1850
1851
1852
1853
1854
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty)
const
1872 do_map(x, y, *tx, *ty);
1876
1877
1878
1879
1880
1881
1882
1883void QTransform::map(
int x,
int y,
int *tx,
int *ty)
const
1885 qreal fx = 0, fy = 0;
1886 do_map(x, y, fx, fy);
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903QTransform::TransformationType QTransform::type()
const
1905 if (m_dirty == TxNone || m_dirty < m_type)
1906 return static_cast<TransformationType>(m_type);
1908 switch (
static_cast<TransformationType>(m_dirty)) {
1910 if (!qFuzzyIsNull(m_matrix[0][2]) || !qFuzzyIsNull(m_matrix[1][2]) || !qFuzzyIsNull(m_matrix[2][2] - 1)) {
1917 if (!qFuzzyIsNull(m_matrix[0][1]) || !qFuzzyIsNull(m_matrix[1][0])) {
1918 const qreal dot = m_matrix[0][0] * m_matrix[1][0] + m_matrix[0][1] * m_matrix[1][1];
1919 if (qFuzzyIsNull(dot))
1927 if (!qFuzzyIsNull(m_matrix[0][0] - 1) || !qFuzzyIsNull(m_matrix[1][1] - 1)) {
1933 if (!qFuzzyIsNull(m_matrix[2][0]) || !qFuzzyIsNull(m_matrix[2][1])) {
1934 m_type = TxTranslate;
1944 return static_cast<TransformationType>(m_type);
1948
1949
1950
1951QTransform::operator QVariant()
const
1953 return QVariant::fromValue(*
this);
1958
1959
1960
1961
1962
1963
1966
1967
1968
1969
1970
1971
1972
1975
1976
1977
1978
1979
1980
1981
1984
1985
1986
1987
1988
1989
1990
1993
1994
1995
1996
1997
1998
1999
2002
2003
2004
2005
2006
2007
2008
2011
2012
2013
2014
2015
2016
2017
2021
2022
2023
2024
2025
2026
2027
2031
2032
2033
2034
2035
2036
2037
2040
2041
2042
2043
2044
2045
2046
2049
2050
2051
2052
2053
2054
2055
2058
2059
2060
2061
2062
2063
2064
2067
2068
2069
2070
2073
2074
2075
2076
2077
2078
2079
2082
2083
2084
2085
2086
2089
2090
2091
2092
2093
2094
2095
2098
2099
2100
2101
2102
2103
2104
2105
2106
2109
2110
2111
2112
2113
2114
2115
2118
2119
2120
2121
2122
2123
2124
2125
2134 const QTransform::TransformationType type = transform.type();
2135 if (type <= QTransform::TxTranslate) {
2139 }
else if (type == QTransform::TxScale) {
2140 const qreal xScale = qAbs(transform.m11());
2141 const qreal yScale = qAbs(transform.m22());
2143 *scale = qMax(xScale, yScale);
2144 return qFuzzyCompare(xScale, yScale);
2148 const qreal xScale1 = transform.m11() * transform.m11()
2149 + transform.m21() * transform.m21();
2150 const qreal yScale1 = transform.m12() * transform.m12()
2151 + transform.m22() * transform.m22();
2154 const qreal xScale2 = transform.m11() * transform.m11()
2155 + transform.m12() * transform.m12();
2156 const qreal yScale2 = transform.m21() * transform.m21()
2157 + transform.m22() * transform.m22();
2160 if (qAbs(xScale1 - yScale1) > qAbs(xScale2 - yScale2)) {
2162 *scale = qSqrt(qMax(xScale1, yScale1));
2164 return type == QTransform::TxRotate && qFuzzyCompare(xScale1, yScale1);
2167 *scale = qSqrt(qMax(xScale2, yScale2));
2169 return type == QTransform::TxRotate && qFuzzyCompare(xScale2, yScale2);
2173QDataStream &
operator>>(QDataStream &s, QTransform::Affine &m)
2175 if (s.version() == 1) {
2176 float m11, m12, m21, m22, dx, dy;
2177 s >> m11; s >> m12; s >> m21; s >> m22; s >> dx; s >> dy;
2179 m.m_matrix[0][0] = m11;
2180 m.m_matrix[0][1] = m12;
2181 m.m_matrix[1][0] = m21;
2182 m.m_matrix[1][1] = m22;
2183 m.m_matrix[2][0] = dx;
2184 m.m_matrix[2][1] = dy;
2186 s >> m.m_matrix[0][0];
2187 s >> m.m_matrix[0][1];
2188 s >> m.m_matrix[1][0];
2189 s >> m.m_matrix[1][1];
2190 s >> m.m_matrix[2][0];
2191 s >> m.m_matrix[2][1];
2193 m.m_matrix[0][2] = 0;
2194 m.m_matrix[1][2] = 0;
2195 m.m_matrix[2][2] = 1;
2199QDataStream &operator<<(QDataStream &s,
const QTransform::Affine &m)
2201 if (s.version() == 1) {
2202 s << (
float)m.m_matrix[0][0]
2203 << (
float)m.m_matrix[0][1]
2204 << (
float)m.m_matrix[1][0]
2205 << (
float)m.m_matrix[1][1]
2206 << (
float)m.m_matrix[2][0]
2207 << (
float)m.m_matrix[2][1];
2209 s << m.m_matrix[0][0]
2214 << 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_)