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
214
215
216
217
218
219
220
221
222
225
226
227
230
231
232
233
234
235
236
237
238
241
242
243
244
245
246
247
250
251
252
253
254
255
258
259
260QTransform QTransform::adjoint()
const
265 h11 = m_matrix[1][1] * m_matrix[2][2] - m_matrix[1][2] * m_matrix[2][1];
266 h21 = m_matrix[1][2] * m_matrix[2][0] - m_matrix[1][0] * m_matrix[2][2];
267 h31 = m_matrix[1][0] * m_matrix[2][1] - m_matrix[1][1] * m_matrix[2][0];
268 h12 = m_matrix[0][2] * m_matrix[2][1] - m_matrix[0][1] * m_matrix[2][2];
269 h22 = m_matrix[0][0] * m_matrix[2][2] - m_matrix[0][2] * m_matrix[2][0];
270 h32 = m_matrix[0][1] * m_matrix[2][0] - m_matrix[0][0] * m_matrix[2][1];
271 h13 = m_matrix[0][1] * m_matrix[1][2] - m_matrix[0][2] * m_matrix[1][1];
272 h23 = m_matrix[0][2] * m_matrix[1][0] - m_matrix[0][0] * m_matrix[1][2];
273 h33 = m_matrix[0][0] * m_matrix[1][1] - m_matrix[0][1] * m_matrix[1][0];
275 return QTransform(h11, h12, h13,
281
282
283QTransform QTransform::transposed()
const
285 QTransform t(m_matrix[0][0], m_matrix[1][0], m_matrix[2][0],
286 m_matrix[0][1], m_matrix[1][1], m_matrix[2][1],
287 m_matrix[0][2], m_matrix[1][2], m_matrix[2][2]);
292
293
294
295
296
297
298
299
300
301QTransform QTransform::inverted(
bool *invertible)
const
306 switch(inline_type()) {
310 invert.m_matrix[2][0] = -m_matrix[2][0];
311 invert.m_matrix[2][1] = -m_matrix[2][1];
314 inv = !qFuzzyIsNull(m_matrix[0][0]);
315 inv &= !qFuzzyIsNull(m_matrix[1][1]);
317 invert.m_matrix[0][0] = 1. / m_matrix[0][0];
318 invert.m_matrix[1][1] = 1. / m_matrix[1][1];
319 invert.m_matrix[2][0] = -m_matrix[2][0] * invert.m_matrix[0][0];
320 invert.m_matrix[2][1] = -m_matrix[2][1] * invert.m_matrix[1][1];
325 qreal det = determinant();
326 inv = !qFuzzyIsNull(det);
328 invert = adjoint() / det;
337 invert.m_type = m_type;
338 invert.m_dirty = m_dirty;
345
346
347
348
349
350QTransform &QTransform::translate(qreal dx, qreal dy)
352 if (dx == 0 && dy == 0)
355 if (qIsNaN(dx) || qIsNaN(dy)) {
356 nanWarning(
"translate");
361 switch(inline_type()) {
367 m_matrix[2][0] += dx;
368 m_matrix[2][1] += dy;
371 m_matrix[2][0] += dx * m_matrix[0][0];
372 m_matrix[2][1] += dy * m_matrix[1][1];
375 m_matrix[2][2] += dx * m_matrix[0][2] + dy * m_matrix[1][2];
379 m_matrix[2][0] += dx * m_matrix[0][0] + dy * m_matrix[1][0];
380 m_matrix[2][1] += dy * m_matrix[1][1] + dx * m_matrix[0][1];
383 if (m_dirty < TxTranslate)
384 m_dirty = TxTranslate;
389
390
391
392
393
394
395QTransform QTransform::fromTranslate(qreal dx, qreal dy)
398 if (qIsNaN(dx) || qIsNaN(dy)) {
399 nanWarning(
"fromTranslate");
403 QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1);
404 if (dx == 0 && dy == 0)
405 transform.m_type = TxNone;
407 transform.m_type = TxTranslate;
408 transform.m_dirty = TxNone;
413
414
415
416
417
418QTransform & QTransform::scale(qreal sx, qreal sy)
420 if (sx == 1 && sy == 1)
423 if (qIsNaN(sx) || qIsNaN(sy)) {
429 switch(inline_type()) {
436 m_matrix[0][2] *= sx;
437 m_matrix[1][2] *= sy;
441 m_matrix[0][1] *= sx;
442 m_matrix[1][0] *= sy;
445 m_matrix[0][0] *= sx;
446 m_matrix[1][1] *= sy;
449 if (m_dirty < TxScale)
455
456
457
458
459
460
461QTransform QTransform::fromScale(qreal sx, qreal sy)
464 if (qIsNaN(sx) || qIsNaN(sy)) {
465 nanWarning(
"fromScale");
469 QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1);
470 if (sx == 1. && sy == 1.)
471 transform.m_type = TxNone;
473 transform.m_type = TxScale;
474 transform.m_dirty = TxNone;
479
480
481
482
483
484QTransform & QTransform::shear(qreal sh, qreal sv)
486 if (sh == 0 && sv == 0)
489 if (qIsNaN(sh) || qIsNaN(sv)) {
495 switch(inline_type()) {
502 m_matrix[0][1] = sv*m_matrix[1][1];
503 m_matrix[1][0] = sh*m_matrix[0][0];
506 qreal tm13 = sv * m_matrix[1][2];
507 qreal tm23 = sh * m_matrix[0][2];
508 m_matrix[0][2] += tm13;
509 m_matrix[1][2] += tm23;
514 qreal tm11 = sv * m_matrix[1][0];
515 qreal tm22 = sh * m_matrix[0][1];
516 qreal tm12 = sv * m_matrix[1][1];
517 qreal tm21 = sh * m_matrix[0][0];
518 m_matrix[0][0] += tm11;
519 m_matrix[0][1] += tm12;
520 m_matrix[1][0] += tm21;
521 m_matrix[1][1] += tm22;
525 if (m_dirty < TxShear)
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551QTransform & QTransform::rotate(qreal a, Qt::Axis axis, qreal distanceToPlane)
556 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
557 nanWarning(
"rotate");
564 if (a == 90. || a == -270.)
566 else if (a == 270. || a == -90.)
571 qreal b = qDegreesToRadians(a);
576 if (axis == Qt::ZAxis) {
577 switch(inline_type()) {
580 m_matrix[0][0] = cosa;
581 m_matrix[0][1] = sina;
582 m_matrix[1][0] = -sina;
583 m_matrix[1][1] = cosa;
586 qreal tm11 = cosa * m_matrix[0][0];
587 qreal tm12 = sina * m_matrix[1][1];
588 qreal tm21 = -sina * m_matrix[0][0];
589 qreal tm22 = cosa * m_matrix[1][1];
590 m_matrix[0][0] = tm11;
591 m_matrix[0][1] = tm12;
592 m_matrix[1][0] = tm21;
593 m_matrix[1][1] = tm22;
597 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
598 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
599 m_matrix[0][2] = tm13;
600 m_matrix[1][2] = tm23;
605 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
606 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
607 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
608 qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1];
609 m_matrix[0][0] = tm11;
610 m_matrix[0][1] = tm12;
611 m_matrix[1][0] = tm21;
612 m_matrix[1][1] = tm22;
616 if (m_dirty < TxRotate)
619 if (!qIsNull(distanceToPlane))
620 sina /= distanceToPlane;
623 if (axis == Qt::YAxis) {
624 result.m_matrix[0][0] = cosa;
625 result.m_matrix[0][2] = -sina;
627 result.m_matrix[1][1] = cosa;
628 result.m_matrix[1][2] = -sina;
630 result.m_type = TxProject;
631 *
this = result * *
this;
637#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
639
640
641
642
643
644
645
646
647
648
649QTransform &QTransform::rotate(qreal a, Qt::Axis axis)
651 return rotate(a, axis, 1024.0);
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis, qreal distanceToPlane)
679 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
680 nanWarning(
"rotateRadians");
684 qreal sina = qSin(a);
685 qreal cosa = qCos(a);
687 if (axis == Qt::ZAxis) {
688 switch(inline_type()) {
691 m_matrix[0][0] = cosa;
692 m_matrix[0][1] = sina;
693 m_matrix[1][0] = -sina;
694 m_matrix[1][1] = cosa;
697 qreal tm11 = cosa * m_matrix[0][0];
698 qreal tm12 = sina * m_matrix[1][1];
699 qreal tm21 = -sina * m_matrix[0][0];
700 qreal tm22 = cosa * m_matrix[1][1];
701 m_matrix[0][0] = tm11;
702 m_matrix[0][1] = tm12;
703 m_matrix[1][0] = tm21;
704 m_matrix[1][1] = tm22;
708 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
709 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
710 m_matrix[0][2] = tm13;
711 m_matrix[1][2] = tm23;
716 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
717 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
718 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
719 qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1];
720 m_matrix[0][0] = tm11;
721 m_matrix[0][1] = tm12;
722 m_matrix[1][0] = tm21;
723 m_matrix[1][1] = tm22;
727 if (m_dirty < TxRotate)
730 if (!qIsNull(distanceToPlane))
731 sina /= distanceToPlane;
734 if (axis == Qt::YAxis) {
735 result.m_matrix[0][0] = cosa;
736 result.m_matrix[0][2] = -sina;
738 result.m_matrix[1][1] = cosa;
739 result.m_matrix[1][2] = -sina;
741 result.m_type = TxProject;
742 *
this = result * *
this;
747#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
749
750
751
752
753
754
755
756
757
758
759QTransform &QTransform::rotateRadians(qreal a, Qt::Axis axis)
761 return rotateRadians(a, axis, 1024.0);
766
767
768
769
770bool QTransform::operator==(
const QTransform &o)
const
772 return m_matrix[0][0] == o.m_matrix[0][0] &&
773 m_matrix[0][1] == o.m_matrix[0][1] &&
774 m_matrix[1][0] == o.m_matrix[1][0] &&
775 m_matrix[1][1] == o.m_matrix[1][1] &&
776 m_matrix[2][0] == o.m_matrix[2][0] &&
777 m_matrix[2][1] == o.m_matrix[2][1] &&
778 m_matrix[0][2] == o.m_matrix[0][2] &&
779 m_matrix[1][2] == o.m_matrix[1][2] &&
780 m_matrix[2][2] == o.m_matrix[2][2];
784
785
786
789 QtPrivate::QHashCombineWithSeed hash(seed);
790 seed = hash(seed, key.m11());
791 seed = hash(seed, key.m12());
792 seed = hash(seed, key.m21());
793 seed = hash(seed, key.m22());
794 seed = hash(seed, key.dx());
795 seed = hash(seed, key.dy());
796 seed = hash(seed, key.m13());
797 seed = hash(seed, key.m23());
798 seed = hash(seed, key.m33());
804
805
806
807
808bool QTransform::operator!=(
const QTransform &o)
const
810 return !operator==(o);
814
815
816
817
818
819
820QTransform & QTransform::operator*=(
const QTransform &o)
822 const TransformationType otherType = o.inline_type();
823 if (otherType == TxNone)
826 const TransformationType thisType = inline_type();
827 if (thisType == TxNone)
830 TransformationType t = qMax(thisType, otherType);
835 m_matrix[2][0] += o.m_matrix[2][0];
836 m_matrix[2][1] += o.m_matrix[2][1];
840 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0];
841 qreal m22 = m_matrix[1][1] * o.m_matrix[1][1];
843 qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + o.m_matrix[2][0];
844 qreal m32 = m_matrix[2][1] * o.m_matrix[1][1] + o.m_matrix[2][1];
846 m_matrix[0][0] = m11;
847 m_matrix[1][1] = m22;
848 m_matrix[2][0] = m31; m_matrix[2][1] = m32;
854 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0] + m_matrix[0][1] * o.m_matrix[1][0];
855 qreal m12 = m_matrix[0][0] * o.m_matrix[0][1] + m_matrix[0][1] * o.m_matrix[1][1];
857 qreal m21 = m_matrix[1][0] * o.m_matrix[0][0] + m_matrix[1][1] * o.m_matrix[1][0];
858 qreal m22 = m_matrix[1][0] * o.m_matrix[0][1] + m_matrix[1][1] * o.m_matrix[1][1];
860 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];
861 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];
863 m_matrix[0][0] = m11;
864 m_matrix[0][1] = m12;
865 m_matrix[1][0] = m21;
866 m_matrix[1][1] = m22;
867 m_matrix[2][0] = m31;
868 m_matrix[2][1] = m32;
873 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];
874 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];
875 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];
877 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];
878 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];
879 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];
881 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];
882 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];
883 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];
885 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
886 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
887 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
898
899
900
901
902
903
904
905QTransform QTransform::operator*(
const QTransform &m)
const
907 const TransformationType otherType = m.inline_type();
908 if (otherType == TxNone)
911 const TransformationType thisType = inline_type();
912 if (thisType == TxNone)
916 TransformationType type = qMax(thisType, otherType);
921 t.m_matrix[2][0] = m_matrix[2][0] + m.m_matrix[2][0];
922 t.m_matrix[2][1] = m_matrix[2][1] + m.m_matrix[2][1];
926 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0];
927 qreal m22 = m_matrix[1][1] * m.m_matrix[1][1];
929 qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m.m_matrix[2][0];
930 qreal m32 = m_matrix[2][1] * m.m_matrix[1][1] + m.m_matrix[2][1];
932 t.m_matrix[0][0] = m11;
933 t.m_matrix[1][1] = m22;
934 t.m_matrix[2][0] = m31;
935 t.m_matrix[2][1] = m32;
941 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0] + m_matrix[0][1] * m.m_matrix[1][0];
942 qreal m12 = m_matrix[0][0] * m.m_matrix[0][1] + m_matrix[0][1] * m.m_matrix[1][1];
944 qreal m21 = m_matrix[1][0] * m.m_matrix[0][0] + m_matrix[1][1] * m.m_matrix[1][0];
945 qreal m22 = m_matrix[1][0] * m.m_matrix[0][1] + m_matrix[1][1] * m.m_matrix[1][1];
947 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];
948 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];
950 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12;
951 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22;
952 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32;
957 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];
958 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];
959 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];
961 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];
962 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];
963 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];
965 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];
966 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];
967 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];
969 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12; t.m_matrix[0][2] = m13;
970 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22; t.m_matrix[1][2] = m23;
971 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32; t.m_matrix[2][2] = m33;
982
983
984
985
986
987
990
991
992
993
994
995
998
999
1000
1001
1002
1003
1006
1007
1008
1009
1010
1011
1014
1015
1016
1017
1020
1021
1022
1023
1024
1025
1026
1027void QTransform::reset()
1029 *
this = QTransform();
1032#ifndef QT_NO_DATASTREAM
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043QDataStream & operator<<(QDataStream &s,
const QTransform &m)
1045 s <<
double(m.m11())
1058
1059
1060
1061
1062
1063
1064
1065
1066
1069 double m11, m12, m13,
1082 t.setMatrix(m11, m12, m13,
1090#ifndef QT_NO_DEBUG_STREAM
1093 static const char typeStr[][12] =
1102 "",
"",
"",
"",
"",
"",
"",
1106 QDebugStateSaver saver(dbg);
1107 dbg.nospace() <<
"QTransform(type=" << typeStr[m.type()] <<
','
1108 <<
" 11=" << m.m11()
1109 <<
" 12=" << m.m12()
1110 <<
" 13=" << m.m13()
1111 <<
" 21=" << m.m21()
1112 <<
" 22=" << m.m22()
1113 <<
" 23=" << m.m23()
1114 <<
" 31=" << m.m31()
1115 <<
" 32=" << m.m32()
1116 <<
" 33=" << m.m33()
1124
1125
1126
1127
1128
1129
1130
1131QPoint QTransform::map(
const QPoint &p)
const
1138 do_map(fx, fy, x, y);
1140 return QPoint(qRound(x), qRound(y));
1145
1146
1147
1148
1149
1150
1151
1154
1155
1156
1157
1158
1159QPointF QTransform::map(
const QPointF &p)
const
1166 do_map(fx, fy, x, y);
1168 return QPointF(x, y);
1172
1173
1174
1175
1176
1177
1178
1179
1182
1183
1184
1185
1186
1187
1188
1191
1192
1193
1194
1195
1196
1197
1200
1201
1202
1203
1204
1205QLine QTransform::map(
const QLine &l)
const
1212 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1214 do_map(fx1, fy1, x1, y1);
1215 do_map(fx2, fy2, x2, y2);
1217 return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1221
1222
1223
1224
1225
1226
1227
1228
1229
1231QLineF QTransform::map(
const QLineF &l)
const
1238 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1240 do_map(fx1, fy1, x1, y1);
1241 do_map(fx2, fy2, x2, y2);
1243 return QLineF(x1, y1, x2, y2);
1247
1248
1249
1250
1251
1252
1253
1254
1257
1258
1259
1260
1261
1262
1263
1266
1267
1268
1269
1270
1271
1272
1273QPolygonF QTransform::map(
const QPolygonF &a)
const
1275 TransformationType t = inline_type();
1276 if (t <= TxTranslate)
1277 return a.translated(m_matrix[2][0], m_matrix[2][1]);
1279 int size = a.size();
1282 const QPointF *da = a.constData();
1283 QPointF *dp = p.data();
1285 for(i = 0; i < size; ++i) {
1286 do_map(da[i].x(), da[i].y(), dp[i].rx(), dp[i].ry());
1292
1293
1294
1295
1296
1297
1298
1299
1300QPolygon QTransform::map(
const QPolygon &a)
const
1302 TransformationType t = inline_type();
1303 if (t <= TxTranslate)
1304 return a.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1306 int size = a.size();
1309 const QPoint *da = a.constData();
1310 QPoint *dp = p.data();
1312 for(i = 0; i < size; ++i) {
1313 qreal nx = 0, ny = 0;
1314 do_map(da[i].x(), da[i].y(), nx, ny);
1315 dp[i].rx() = qRound(nx);
1316 dp[i].ry() = qRound(ny);
1322
1323
1324
1325
1326
1327
1328
1330Q_GUI_EXPORT
extern QPainterPath qt_regionToPath(
const QRegion ®ion);
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342QRegion QTransform::map(
const QRegion &r)
const
1344 TransformationType t = inline_type();
1348 if (t == TxTranslate) {
1350 copy.translate(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1356 if (m11() < 0 || m22() < 0) {
1357 for (
const QRect &rect : r)
1358 res += qt_mapFillRect(QRectF(rect), *
this);
1360 QVarLengthArray<QRect, 32> rects;
1361 rects.reserve(r.rectCount());
1362 for (
const QRect &rect : r) {
1363 QRect nr = qt_mapFillRect(QRectF(rect), *
this);
1367 res.setRects(rects.constData(), rects.size());
1372 QPainterPath p = map(qt_regionToPath(r));
1373 return p.toFillPolygon().toPolygon();
1387 return QPointF(x * iw, y * iw);
1394 c.x = transform.m11() * p.x() + transform.m21() * p.y() + transform.m31();
1395 c.y = transform.m12() * p.x() + transform.m22() * p.y() + transform.m32();
1396 c.w = transform.m13() * p.x() + transform.m23() * p.y() + transform.m33();
1400static inline bool lineTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
1401 bool needsMoveTo,
bool needsLineTo =
true)
1403 QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1404 QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1410 const qreal t = (
Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1412 hb.x += (ha.x - hb.x) * t;
1413 hb.y += (ha.y - hb.y) * t;
1416 const qreal t = (
Q_NEAR_CLIP - ha.w) / (hb.w - ha.w);
1418 ha.x += (hb.x - ha.x) * t;
1419 ha.y += (hb.y - ha.y) * t;
1422 const QPointF p = ha.toPoint();
1425 needsMoveTo =
false;
1432 path.moveTo(ha.toPoint());
1435 path.lineTo(hb.toPoint());
1441static inline bool cubicTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
const QPointF &c,
const QPointF &d,
bool needsMoveTo)
1447 qt_scaleForTransform(transform, &scale);
1449 qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1451 QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1453 for (
int i = 0; i < segment.size() - 1; ++i)
1454 if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
1455 needsMoveTo =
false;
1457 return !needsMoveTo;
1460static QPainterPath
mapProjective(
const QTransform &transform,
const QPainterPath &path)
1462 QPainterPath result;
1466 bool needsMoveTo =
true;
1467 for (
int i = 0; i < path.elementCount(); ++i) {
1468 switch (path.elementAt(i).type) {
1469 case QPainterPath::MoveToElement:
1470 if (i > 0 && lastMoveTo != last)
1473 lastMoveTo = path.elementAt(i);
1474 last = path.elementAt(i);
1477 case QPainterPath::LineToElement:
1479 needsMoveTo =
false;
1480 last = path.elementAt(i);
1482 case QPainterPath::CurveToElement:
1483 if (
cubicTo_clipped(result
, transform
, last
, path.elementAt(i)
, path.elementAt(i+1)
, path.elementAt(i+2)
, needsMoveTo
))
1484 needsMoveTo =
false;
1486 last = path.elementAt(i);
1493 if (path.elementCount() > 0 && lastMoveTo != last)
1496 result.setFillRule(path.fillRule());
1501
1502
1503
1504
1505
1506
1507
1508
1511
1512
1513
1514
1515
1516
1517QPainterPath QTransform::map(
const QPainterPath &path)
const
1519 TransformationType t = inline_type();
1520 if (t == TxNone || path.elementCount() == 0)
1524 return mapProjective(*
this, path);
1526 QPainterPath copy = path;
1528 if (t == TxTranslate) {
1529 copy.translate(m_matrix[2][0], m_matrix[2][1]);
1531 copy.setDirty(
true);
1533 for (
int i=0; i<path.elementCount(); ++i) {
1534 QPainterPath::Element &e = copy.d_ptr->elements[i];
1535 do_map(e.x, e.y, e.x, e.y);
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562QPolygon QTransform::mapToPolygon(
const QRect &rect)
const
1564 TransformationType t = inline_type();
1567 qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1569 x[0] = m_matrix[0][0]*rect.x() + m_matrix[2][0];
1570 y[0] = m_matrix[1][1]*rect.y() + m_matrix[2][1];
1571 qreal w = m_matrix[0][0]*rect.width();
1572 qreal h = m_matrix[1][1]*rect.height();
1588 auto right = rect.x() + rect.width();
1589 auto bottom = rect.y() + rect.height();
1590 do_map(rect.x(), rect.y(), x[0], y[0]);
1591 do_map(right, rect.y(), x[1], y[1]);
1592 do_map(right, bottom, x[2], y[2]);
1593 do_map(rect.x(), bottom, x[3], y[3]);
1598 a.setPoints(4, qRound(x[0]), qRound(y[0]),
1599 qRound(x[1]), qRound(y[1]),
1600 qRound(x[2]), qRound(y[2]),
1601 qRound(x[3]), qRound(y[3]));
1606
1607
1608
1609
1610
1611
1612bool QTransform::squareToQuad(
const QPolygonF &quad, QTransform &trans)
1614 if (quad.size() != (quad.isClosed() ? 5 : 4))
1617 qreal dx0 = quad[0].x();
1618 qreal dx1 = quad[1].x();
1619 qreal dx2 = quad[2].x();
1620 qreal dx3 = quad[3].x();
1622 qreal dy0 = quad[0].y();
1623 qreal dy1 = quad[1].y();
1624 qreal dy2 = quad[2].y();
1625 qreal dy3 = quad[3].y();
1627 double ax = dx0 - dx1 + dx2 - dx3;
1628 double ay = dy0 - dy1 + dy2 - dy3;
1631 trans.setMatrix(dx1 - dx0, dy1 - dy0, 0,
1632 dx2 - dx1, dy2 - dy1, 0,
1635 double ax1 = dx1 - dx2;
1636 double ax2 = dx3 - dx2;
1637 double ay1 = dy1 - dy2;
1638 double ay2 = dy3 - dy2;
1641 double gtop = ax * ay2 - ax2 * ay;
1642 double htop = ax1 * ay - ax * ay1;
1643 double bottom = ax1 * ay2 - ax2 * ay1;
1645 double a, b, c, d, e, f, g, h;
1653 a = dx1 - dx0 + g * dx1;
1654 b = dx3 - dx0 + h * dx3;
1656 d = dy1 - dy0 + g * dy1;
1657 e = dy3 - dy0 + h * dy3;
1660 trans.setMatrix(a, d, g,
1669
1670
1671
1672
1673
1674
1675
1676
1677bool QTransform::quadToSquare(
const QPolygonF &quad, QTransform &trans)
1679 if (!squareToQuad(quad, trans))
1682 bool invertible =
false;
1683 trans = trans.inverted(&invertible);
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700bool QTransform::quadToQuad(
const QPolygonF &one,
1701 const QPolygonF &two,
1705 if (!quadToSquare(one, trans))
1707 if (!squareToQuad(two, stq))
1715
1716
1717
1718
1719
1720
1721
1722
1723
1725void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
1726 qreal m21, qreal m22, qreal m23,
1727 qreal m31, qreal m32, qreal m33)
1729 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
1730 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
1731 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
1733 m_dirty = TxProject;
1736QRect QTransform::mapRect(
const QRect &rect)
const
1738 TransformationType t = inline_type();
1739 if (t <= TxTranslate)
1740 return rect.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1743 int x = qRound(m_matrix[0][0] * rect.x() + m_matrix[2][0]);
1744 int y = qRound(m_matrix[1][1] * rect.y() + m_matrix[2][1]);
1745 int w = qRound(m_matrix[0][0] * rect.width());
1746 int h = qRound(m_matrix[1][1] * rect.height());
1755 return QRect(x, y, w, h);
1758 do_map(rect.left(), rect.top(), x, y);
1763 do_map(rect.right() + 1, rect.top(), x, y);
1764 xmin = qMin(xmin, x);
1765 ymin = qMin(ymin, y);
1766 xmax = qMax(xmax, x);
1767 ymax = qMax(ymax, y);
1768 do_map(rect.right() + 1, rect.bottom() + 1, x, y);
1769 xmin = qMin(xmin, x);
1770 ymin = qMin(ymin, y);
1771 xmax = qMax(xmax, x);
1772 ymax = qMax(ymax, y);
1773 do_map(rect.left(), rect.bottom() + 1, x, y);
1774 xmin = qMin(xmin, x);
1775 ymin = qMin(ymin, y);
1776 xmax = qMax(xmax, x);
1777 ymax = qMax(ymax, y);
1778 return QRectF(xmin, ymin, xmax-xmin, ymax-ymin).toRect();
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801QRectF QTransform::mapRect(
const QRectF &rect)
const
1803 TransformationType t = inline_type();
1804 if (t <= TxTranslate)
1805 return rect.translated(m_matrix[2][0], m_matrix[2][1]);
1808 qreal x = m_matrix[0][0] * rect.x() + m_matrix[2][0];
1809 qreal y = m_matrix[1][1] * rect.y() + m_matrix[2][1];
1810 qreal w = m_matrix[0][0] * rect.width();
1811 qreal h = m_matrix[1][1] * rect.height();
1820 return QRectF(x, y, w, h);
1823 do_map(rect.x(), rect.y(), x, y);
1828 do_map(rect.x() + rect.width(), rect.y(), x, y);
1829 xmin = qMin(xmin, x);
1830 ymin = qMin(ymin, y);
1831 xmax = qMax(xmax, x);
1832 ymax = qMax(ymax, y);
1833 do_map(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
1834 xmin = qMin(xmin, x);
1835 ymin = qMin(ymin, y);
1836 xmax = qMax(xmax, x);
1837 ymax = qMax(ymax, y);
1838 do_map(rect.x(), rect.y() + rect.height(), x, y);
1839 xmin = qMin(xmin, x);
1840 ymin = qMin(ymin, y);
1841 xmax = qMax(xmax, x);
1842 ymax = qMax(ymax, y);
1843 return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
1848
1849
1850
1851
1852
1853
1854
1855
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty)
const
1873 do_map(x, y, *tx, *ty);
1877
1878
1879
1880
1881
1882
1883
1884void QTransform::map(
int x,
int y,
int *tx,
int *ty)
const
1886 qreal fx = 0, fy = 0;
1887 do_map(x, y, fx, fy);
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904QTransform::TransformationType QTransform::type()
const
1906 if (m_dirty == TxNone || m_dirty < m_type)
1907 return static_cast<TransformationType>(m_type);
1909 switch (
static_cast<TransformationType>(m_dirty)) {
1911 if (!qFuzzyIsNull(m_matrix[0][2]) || !qFuzzyIsNull(m_matrix[1][2]) || !qFuzzyIsNull(m_matrix[2][2] - 1)) {
1918 if (!qFuzzyIsNull(m_matrix[0][1]) || !qFuzzyIsNull(m_matrix[1][0])) {
1919 const qreal dot = m_matrix[0][0] * m_matrix[1][0] + m_matrix[0][1] * m_matrix[1][1];
1920 if (qFuzzyIsNull(dot))
1928 if (!qFuzzyIsNull(m_matrix[0][0] - 1) || !qFuzzyIsNull(m_matrix[1][1] - 1)) {
1934 if (!qFuzzyIsNull(m_matrix[2][0]) || !qFuzzyIsNull(m_matrix[2][1])) {
1935 m_type = TxTranslate;
1945 return static_cast<TransformationType>(m_type);
1949
1950
1951
1952QTransform::operator QVariant()
const
1954 return QVariant::fromValue(*
this);
1959
1960
1961
1962
1963
1964
1967
1968
1969
1970
1971
1972
1973
1976
1977
1978
1979
1980
1981
1982
1985
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
2022
2023
2024
2025
2026
2027
2028
2032
2033
2034
2035
2036
2037
2038
2041
2042
2043
2044
2045
2046
2047
2050
2051
2052
2053
2054
2055
2056
2059
2060
2061
2062
2063
2064
2065
2068
2069
2070
2071
2074
2075
2076
2077
2078
2079
2080
2083
2084
2085
2086
2087
2090
2091
2092
2093
2094
2095
2096
2099
2100
2101
2102
2103
2104
2105
2106
2107
2110
2111
2112
2113
2114
2115
2116
2119
2120
2121
2122
2123
2124
2125
2126
2135 const QTransform::TransformationType type = transform.type();
2136 if (type <= QTransform::TxTranslate) {
2140 }
else if (type == QTransform::TxScale) {
2141 const qreal xScale = qAbs(transform.m11());
2142 const qreal yScale = qAbs(transform.m22());
2144 *scale = qMax(xScale, yScale);
2145 return qFuzzyCompare(xScale, yScale);
2149 const qreal xScale1 = transform.m11() * transform.m11()
2150 + transform.m21() * transform.m21();
2151 const qreal yScale1 = transform.m12() * transform.m12()
2152 + transform.m22() * transform.m22();
2155 const qreal xScale2 = transform.m11() * transform.m11()
2156 + transform.m12() * transform.m12();
2157 const qreal yScale2 = transform.m21() * transform.m21()
2158 + transform.m22() * transform.m22();
2161 if (qAbs(xScale1 - yScale1) > qAbs(xScale2 - yScale2)) {
2163 *scale = qSqrt(qMax(xScale1, yScale1));
2165 return type == QTransform::TxRotate && qFuzzyCompare(xScale1, yScale1);
2168 *scale = qSqrt(qMax(xScale2, yScale2));
2170 return type == QTransform::TxRotate && qFuzzyCompare(xScale2, yScale2);
2174QDataStream &
operator>>(QDataStream &s, QTransform::Affine &m)
2176 if (s.version() == 1) {
2177 float m11, m12, m21, m22, dx, dy;
2178 s >> m11; s >> m12; s >> m21; s >> m22; s >> dx; s >> dy;
2180 m.m_matrix[0][0] = m11;
2181 m.m_matrix[0][1] = m12;
2182 m.m_matrix[1][0] = m21;
2183 m.m_matrix[1][1] = m22;
2184 m.m_matrix[2][0] = dx;
2185 m.m_matrix[2][1] = dy;
2187 s >> m.m_matrix[0][0];
2188 s >> m.m_matrix[0][1];
2189 s >> m.m_matrix[1][0];
2190 s >> m.m_matrix[1][1];
2191 s >> m.m_matrix[2][0];
2192 s >> m.m_matrix[2][1];
2194 m.m_matrix[0][2] = 0;
2195 m.m_matrix[1][2] = 0;
2196 m.m_matrix[2][2] = 1;
2200QDataStream &operator<<(QDataStream &s,
const QTransform::Affine &m)
2202 if (s.version() == 1) {
2203 s << (
float)m.m_matrix[0][0]
2204 << (
float)m.m_matrix[0][1]
2205 << (
float)m.m_matrix[1][0]
2206 << (
float)m.m_matrix[1][1]
2207 << (
float)m.m_matrix[2][0]
2208 << (
float)m.m_matrix[2][1];
2210 s << m.m_matrix[0][0]
2215 << 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_)