1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquicktranslate_p.h"
5#include "qquickitem_p.h"
6
7QT_BEGIN_NAMESPACE
8
9class QQuickTranslatePrivate : public QQuickTransformPrivate
10{
11public:
12 QQuickTranslatePrivate()
13 : x(0), y(0) {}
14
15 qreal x;
16 qreal y;
17};
18
19
20/*!
21 \qmltype Translate
22 \nativetype QQuickTranslate
23 \inqmlmodule QtQuick
24 \ingroup qtquick-visual-transforms
25 \brief Provides a way to move an Item without changing its x or y properties.
26
27 The Translate type provides independent control over position in addition
28 to the Item's x and y properties.
29
30 The following example moves the Y axis of the \l Rectangle items while
31 still allowing the \l Row to lay the items out as if they had not been
32 transformed:
33
34 \qml
35 import QtQuick 2.0
36
37 Row {
38 Rectangle {
39 width: 100; height: 100
40 color: "blue"
41 transform: Translate { y: 20 }
42 }
43 Rectangle {
44 width: 100; height: 100
45 color: "red"
46 transform: Translate { y: -20 }
47 }
48 }
49 \endqml
50
51 \image translate.png
52*/
53QQuickTranslate::QQuickTranslate(QObject *parent)
54: QQuickTransform(*new QQuickTranslatePrivate, parent)
55{
56}
57
58/*!
59 \qmlproperty real QtQuick::Translate::x
60
61 The translation along the X axis.
62
63 The default value is 0.0.
64*/
65qreal QQuickTranslate::x() const
66{
67 Q_D(const QQuickTranslate);
68 return d->x;
69}
70
71void QQuickTranslate::setX(qreal x)
72{
73 Q_D(QQuickTranslate);
74 if (d->x == x)
75 return;
76 d->x = x;
77 update();
78 emit xChanged();
79}
80
81/*!
82 \qmlproperty real QtQuick::Translate::y
83
84 The translation along the Y axis.
85
86 The default value is 0.0.
87*/
88qreal QQuickTranslate::y() const
89{
90 Q_D(const QQuickTranslate);
91 return d->y;
92}
93void QQuickTranslate::setY(qreal y)
94{
95 Q_D(QQuickTranslate);
96 if (d->y == y)
97 return;
98 d->y = y;
99 update();
100 emit yChanged();
101}
102
103void QQuickTranslate::applyTo(QMatrix4x4 *matrix) const
104{
105 Q_D(const QQuickTranslate);
106 matrix->translate(x: d->x, y: d->y, z: 0);
107}
108
109class QQuickScalePrivate : public QQuickTransformPrivate
110{
111public:
112 QQuickScalePrivate()
113 : xScale(1), yScale(1), zScale(1) {}
114 QVector3D origin;
115 qreal xScale;
116 qreal yScale;
117 qreal zScale;
118};
119
120/*!
121 \qmltype Scale
122 \nativetype QQuickScale
123 \inqmlmodule QtQuick
124 \ingroup qtquick-visual-transforms
125 \brief Provides a way to scale an Item.
126
127 The Scale type provides a way to scale an \l Item through a scale-type
128 transform.
129
130 It allows different scaling values for the x and y axes, and allows the
131 scale to be relative to an arbitrary point. This gives more control over
132 item scaling than the \l{Item::}{scale} property.
133
134 The following example scales the X axis of the Rectangle, relative to
135 its interior point (25, 25):
136
137 \qml
138 Rectangle {
139 width: 100; height: 100
140 color: "blue"
141 transform: Scale { origin.x: 25; origin.y: 25; xScale: 3}
142 }
143 \endqml
144
145 \sa Rotation, Translate
146*/
147QQuickScale::QQuickScale(QObject *parent)
148 : QQuickTransform(*new QQuickScalePrivate, parent)
149{
150}
151
152/*!
153 \qmlpropertygroup QtQuick::Scale::origin
154 \qmlproperty real QtQuick::Scale::origin.x
155 \qmlproperty real QtQuick::Scale::origin.y
156
157 This property holds the point that the item is scaled from (that is,
158 the point that stays fixed relative to the parent as the rest of the
159 item grows).
160
161 The default value of the origin is (0, 0).
162*/
163QVector3D QQuickScale::origin() const
164{
165 Q_D(const QQuickScale);
166 return d->origin;
167}
168void QQuickScale::setOrigin(const QVector3D &point)
169{
170 Q_D(QQuickScale);
171 if (d->origin == point)
172 return;
173 d->origin = point;
174 update();
175 emit originChanged();
176}
177
178/*!
179 \qmlproperty real QtQuick::Scale::xScale
180
181 The scaling factor for the X axis.
182
183 The default value is 1.0.
184*/
185qreal QQuickScale::xScale() const
186{
187 Q_D(const QQuickScale);
188 return d->xScale;
189}
190void QQuickScale::setXScale(qreal scale)
191{
192 Q_D(QQuickScale);
193 if (d->xScale == scale)
194 return;
195 d->xScale = scale;
196 update();
197 emit xScaleChanged();
198 emit scaleChanged();
199}
200
201/*!
202 \qmlproperty real QtQuick::Scale::yScale
203
204 The scaling factor for the Y axis.
205
206 The default value is 1.0.
207*/
208qreal QQuickScale::yScale() const
209{
210 Q_D(const QQuickScale);
211 return d->yScale;
212}
213void QQuickScale::setYScale(qreal scale)
214{
215 Q_D(QQuickScale);
216 if (d->yScale == scale)
217 return;
218 d->yScale = scale;
219 update();
220 emit yScaleChanged();
221 emit scaleChanged();
222}
223
224/*!
225 \qmlproperty real QtQuick::Scale::zScale
226 \internal
227
228 The scaling factor for the Z axis.
229
230 The default value is 1.0.
231*/
232qreal QQuickScale::zScale() const
233{
234 Q_D(const QQuickScale);
235 return d->zScale;
236}
237void QQuickScale::setZScale(qreal scale)
238{
239 Q_D(QQuickScale);
240 if (d->zScale == scale)
241 return;
242 d->zScale = scale;
243 update();
244 emit zScaleChanged();
245 emit scaleChanged();
246}
247
248void QQuickScale::applyTo(QMatrix4x4 *matrix) const
249{
250 Q_D(const QQuickScale);
251 matrix->translate(vector: d->origin);
252 matrix->scale(x: d->xScale, y: d->yScale, z: d->zScale);
253 matrix->translate(vector: -d->origin);
254}
255
256class QQuickRotationPrivate : public QQuickTransformPrivate
257{
258public:
259 QQuickRotationPrivate()
260 : angle(0), axis(0, 0, 1) {}
261 QVector3D origin;
262 qreal angle;
263 QVector3D axis;
264};
265
266/*!
267 \qmltype Rotation
268 \nativetype QQuickRotation
269 \inqmlmodule QtQuick
270 \ingroup qtquick-visual-transforms
271 \brief Provides a way to rotate an Item.
272
273 The Rotation type provides a way to rotate an \l Item through a
274 rotation-type transform.
275
276 It allows (z axis) rotation to be relative to an arbitrary point, and also
277 provides a way to specify 3D-like rotations for Items. This gives more
278 control over item rotation than the \l{Item::}{rotation} property.
279
280 The following example rotates a Rectangle around its interior point
281 (25, 25):
282
283 \qml
284 Rectangle {
285 width: 100; height: 100
286 color: "blue"
287 transform: Rotation { origin.x: 25; origin.y: 25; angle: 45}
288 }
289 \endqml
290
291 For 3D-like item rotations, you must specify the axis of rotation in
292 addition to the origin point. The following example shows various 3D-like
293 rotations applied to an \l Image.
294
295 \snippet qml/rotation.qml 0
296
297 \image axisrotation.png
298
299 \sa {customitems/dialcontrol}{Dial Control example}, {Qt Quick Demo - Clocks}
300*/
301QQuickRotation::QQuickRotation(QObject *parent)
302 : QQuickTransform(*new QQuickRotationPrivate, parent)
303{
304}
305
306/*!
307 \qmlpropertygroup QtQuick::Rotation::origin
308 \qmlproperty real QtQuick::Rotation::origin.x
309 \qmlproperty real QtQuick::Rotation::origin.y
310
311 The origin point of the rotation (i.e., the point that stays fixed
312 relative to the parent as the rest of the item rotates). By default
313 the origin is (0, 0).
314*/
315QVector3D QQuickRotation::origin() const
316{
317 Q_D(const QQuickRotation);
318 return d->origin;
319}
320
321void QQuickRotation::setOrigin(const QVector3D &point)
322{
323 Q_D(QQuickRotation);
324 if (d->origin == point)
325 return;
326 d->origin = point;
327 update();
328 emit originChanged();
329}
330
331/*!
332 \qmlproperty real QtQuick::Rotation::angle
333
334 The angle to rotate, in degrees clockwise.
335*/
336qreal QQuickRotation::angle() const
337{
338 Q_D(const QQuickRotation);
339 return d->angle;
340}
341void QQuickRotation::setAngle(qreal angle)
342{
343 Q_D(QQuickRotation);
344 if (d->angle == angle)
345 return;
346 d->angle = angle;
347 update();
348 emit angleChanged();
349}
350
351/*!
352 \qmlpropertygroup QtQuick::Rotation::axis
353 \qmlproperty real QtQuick::Rotation::axis.x
354 \qmlproperty real QtQuick::Rotation::axis.y
355 \qmlproperty real QtQuick::Rotation::axis.z
356
357 The axis to rotate around. For simple (2D) rotation around a point, you
358 do not need to specify an axis, as the default axis is the z axis
359 (\c{ axis { x: 0; y: 0; z: 1 } }).
360
361 For a typical 3D-like rotation you will usually specify both the origin
362 and the axis.
363
364 \image 3d-rotation-axis.png
365*/
366QVector3D QQuickRotation::axis() const
367{
368 Q_D(const QQuickRotation);
369 return d->axis;
370}
371void QQuickRotation::setAxis(const QVector3D &axis)
372{
373 Q_D(QQuickRotation);
374 if (d->axis == axis)
375 return;
376 d->axis = axis;
377 update();
378 emit axisChanged();
379}
380
381void QQuickRotation::setAxis(Qt::Axis axis)
382{
383 switch (axis)
384 {
385 case Qt::XAxis:
386 setAxis(QVector3D(1, 0, 0));
387 break;
388 case Qt::YAxis:
389 setAxis(QVector3D(0, 1, 0));
390 break;
391 case Qt::ZAxis:
392 setAxis(QVector3D(0, 0, 1));
393 break;
394 }
395}
396
397void QQuickRotation::applyTo(QMatrix4x4 *matrix) const
398{
399 Q_D(const QQuickRotation);
400
401 if (d->angle == 0. || d->axis.isNull())
402 return;
403
404 matrix->translate(vector: d->origin);
405 matrix->projectedRotate(angle: d->angle, x: d->axis.x(), y: d->axis.y(), z: d->axis.z());
406 matrix->translate(vector: -d->origin);
407}
408
409/*!
410 \qmltype Shear
411 \nativetype QQuickShear
412 \inqmlmodule QtQuick
413 \ingroup qtquick-visual-transforms
414 \since 6.9
415 \brief Provides a way to shear an Item.
416
417 The Shear type provides a way to transform an \l Item by a two-dimensional shear-type
418 matrix, sometimes known as a \e skew transform.
419
420 \qml
421 Rectangle {
422 width: 100; height: 100
423 color: "blue"
424 transform: Shear {
425 xFactor: 1.0
426 }
427 }
428 \endqml
429
430 This shears the item by a factor of \c 1.0 along the x-axis without modifying anything along the
431 y-axis. Each point \c P is displaced by \c{xFactor(P.y - origin.y)} (the signed vertical
432 distance to the \l{origin} multiplied with the \l{xFactor}). Setting the \l{yFactor} shears the
433 item along the y-axis and proportionally to the horizontal distance.
434
435 \image x-shear.png
436
437 Since the default origin is at \c{(0, 0)}, the top of the item remains untransformed, whereas
438 the bottom is displaced 100 pixels to the right (corresponding to the height of the item.)
439
440 This code is equivalent to the following:
441
442 \qml
443 Rectangle {
444 width: 100; height: 100
445 color: "blue"
446 transform: Shear {
447 xAngle: 45.0
448 }
449 }
450 \endqml
451
452 \note If both \c{xFactor}/\c{yFactor} and \c{xAngle}/\c{yAngle} are set, then the sum of the
453 two displacements will be used.
454*/
455class QQuickShearPrivate : public QQuickTransformPrivate
456{
457public:
458 QVector3D origin;
459 qreal xFactor = 0.0;
460 qreal yFactor = 0.0;
461 qreal xAngle = 0.0;
462 qreal yAngle = 0.0;
463};
464
465QQuickShear::QQuickShear(QObject *parent)
466 : QQuickTransform(*new QQuickShearPrivate, parent)
467{
468}
469
470/*!
471 \qmlpropertygroup QtQuick::Shear::origin
472 \qmlproperty real QtQuick::Shear::origin.x
473 \qmlproperty real QtQuick::Shear::origin.y
474
475 The origin point of the transformation (i.e., the point that stays fixed relative to the parent
476 as the rest of the item is sheared).
477
478 By default the origin is \c (0, 0).
479*/
480QVector3D QQuickShear::origin() const
481{
482 Q_D(const QQuickShear);
483 return d->origin;
484}
485
486void QQuickShear::setOrigin(const QVector3D &point)
487{
488 Q_D(QQuickShear);
489 if (d->origin == point)
490 return;
491 d->origin = point;
492 update();
493 emit originChanged();
494}
495
496/*!
497 \qmlproperty real QtQuick::Shear::xFactor
498
499 The factor by which to shear the item's coordinate system along the x-axis. Each point \c P is
500 displaced by \c{xFactor(P.y - origin.y)}
501
502 This corresponds to the \c sh parameter in \l{QTransform::shear()} and the \c xShear parameter
503 in calls to \l{PlanarTransform::fromShear()}.
504
505 The default value is \c 0.0.
506
507 \sa xAngle
508*/
509qreal QQuickShear::xFactor() const
510{
511 Q_D(const QQuickShear);
512 return d->xFactor;
513}
514void QQuickShear::setXFactor(qreal xFactor)
515{
516 Q_D(QQuickShear);
517 if (d->xFactor == xFactor)
518 return;
519 d->xFactor = xFactor;
520 update();
521 emit xFactorChanged();
522}
523
524/*!
525 \qmlproperty real QtQuick::Shear::yFactor
526
527 The factor by which to shear the item's coordinate system along the y-axis. The factor by which
528 to shear the item's coordinate system along the x-axis. Each point \c P is displaced by
529 \c{xFactor(P.y - origin.y)}
530
531 This corresponds to the \c sv parameter in \l{QTransform::shear()} and the \c yShear parameter
532 in calls to \l{PlanarTransform::fromShear()}.
533
534 The default value is \c 0.0.
535
536 \sa yAngle
537*/
538qreal QQuickShear::yFactor() const
539{
540 Q_D(const QQuickShear);
541 return d->yFactor;
542}
543void QQuickShear::setYFactor(qreal yFactor)
544{
545 Q_D(QQuickShear);
546 if (d->yFactor == yFactor)
547 return;
548 d->yFactor = yFactor;
549 update();
550 emit yFactorChanged();
551}
552
553/*!
554 \qmlproperty real QtQuick::Shear::xAngle
555
556 The angle (in degrees) by which to shear the item's coordinate system along the x-axis. This
557 is equivalent to setting \l{xFactor} to \c{tan(xAngle)}.
558
559 The default value is \c 0.0.
560
561 \sa xFactor
562*/
563qreal QQuickShear::xAngle() const
564{
565 Q_D(const QQuickShear);
566 return d->xAngle;
567}
568void QQuickShear::setXAngle(qreal xAngle)
569{
570 Q_D(QQuickShear);
571 if (d->xAngle == xAngle)
572 return;
573 d->xAngle = xAngle;
574 update();
575 emit xAngleChanged();
576}
577
578/*!
579 \qmlproperty real QtQuick::Shear::yAngle
580
581 The angle (in degrees) by which to shear the item's coordinate system along the y-axis. This
582 is equivalent to setting \l{yFactor} to \c{tan(yAngle)}.
583
584 The default value is \c 0.0.
585
586 \sa yFactor
587*/
588qreal QQuickShear::yAngle() const
589{
590 Q_D(const QQuickShear);
591 return d->yAngle;
592}
593void QQuickShear::setYAngle(qreal yAngle)
594{
595 Q_D(QQuickShear);
596 if (d->yAngle == yAngle)
597 return;
598 d->yAngle = yAngle;
599 update();
600 emit yAngleChanged();
601}
602
603void QQuickShear::applyTo(QMatrix4x4 *matrix) const
604{
605 Q_D(const QQuickShear);
606 if (d->xFactor == 0.0 && d->yFactor == 0.0 && d->xAngle == 0.0 && d->yAngle == 0.0)
607 return;
608
609 const qreal xShear = qTan(v: qDegreesToRadians(degrees: d->xAngle)) + d->xFactor;
610 const qreal yShear = qTan(v: qDegreesToRadians(degrees: d->yAngle)) + d->yFactor;
611
612 matrix->translate(vector: d->origin);
613 *matrix *= QMatrix4x4(1.0, xShear, 0.0, 0.0,
614 yShear, 1.0, 0.0, 0.0,
615 0.0, 0.0, 1.0, 0.0,
616 0.0, 0.0, 0.0, 1.0);
617 matrix->translate(vector: -d->origin);
618}
619
620
621class QQuickMatrix4x4Private : public QQuickTransformPrivate
622{
623public:
624 QQuickMatrix4x4Private()
625 : matrix() {}
626 QMatrix4x4 matrix;
627};
628
629/*!
630 \qmltype Matrix4x4
631 \nativetype QQuickMatrix4x4
632 \inqmlmodule QtQuick
633 \ingroup qtquick-visual-transforms
634 \since 5.3
635 \brief Provides a way to apply a 4x4 tranformation matrix to an \l Item.
636
637 The Matrix4x4 type provides a way to apply a transformation to an
638 \l Item through a 4x4 matrix.
639
640 It allows for a combination of rotation, scale, translatation and shearing
641 by using just one tranformation provided in a 4x4-matrix.
642
643 The following example rotates a Rectangle 45 degress (PI/4):
644
645 \qml
646 Rectangle {
647 width: 100
648 height: 100
649 color: "red"
650
651 transform: Matrix4x4 {
652 property real a: Math.PI / 4
653 matrix: Qt.matrix4x4(Math.cos(a), -Math.sin(a), 0, 0,
654 Math.sin(a), Math.cos(a), 0, 0,
655 0, 0, 1, 0,
656 0, 0, 0, 1)
657 }
658 }
659 \endqml
660*/
661QQuickMatrix4x4::QQuickMatrix4x4(QObject *parent)
662 : QQuickTransform(*new QQuickMatrix4x4Private, parent)
663{
664}
665
666/*!
667 \qmlproperty matrix4x4 QtQuick::Matrix4x4::matrix
668
669 4x4-matrix which will be used in the tranformation of an \l Item
670*/
671QMatrix4x4 QQuickMatrix4x4::matrix() const
672{
673 Q_D(const QQuickMatrix4x4);
674 return d->matrix;
675}
676
677void QQuickMatrix4x4::setMatrix(const QMatrix4x4 &matrix)
678{
679 Q_D(QQuickMatrix4x4);
680 if (d->matrix == matrix)
681 return;
682 d->matrix = matrix;
683 update();
684 emit matrixChanged();
685}
686
687void QQuickMatrix4x4::applyTo(QMatrix4x4 *matrix) const
688{
689 Q_D(const QQuickMatrix4x4);
690 *matrix *= d->matrix;
691}
692
693QT_END_NAMESPACE
694
695#include "moc_qquicktranslate_p.cpp"
696

source code of qtdeclarative/src/quick/items/qquicktranslate.cpp