summaryrefslogtreecommitdiffstats
path: root/src/declarative/fx/qfxtransform.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/fx/qfxtransform.cpp')
-rw-r--r--src/declarative/fx/qfxtransform.cpp522
1 files changed, 295 insertions, 227 deletions
diff --git a/src/declarative/fx/qfxtransform.cpp b/src/declarative/fx/qfxtransform.cpp
index a001214..9f18413 100644
--- a/src/declarative/fx/qfxtransform.cpp
+++ b/src/declarative/fx/qfxtransform.cpp
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
#define M_PI 3.14159265358979323846
#endif
-QML_DEFINE_TYPE(QFxTransform,Transform);
+QML_DEFINE_NOCREATE_TYPE(QFxTransform);
/*!
\qmlclass Transform
@@ -62,6 +62,10 @@ QFxTransform::QFxTransform(QObject *parent) :
{
}
+QFxTransform::~QFxTransform()
+{
+}
+
bool QFxTransform::isIdentity() const
{
return true;
@@ -75,143 +79,192 @@ QSimpleCanvas::Matrix QFxTransform::transform() const
void QFxTransform::update()
{
QFxItem *item = qobject_cast<QFxItem *>(parent());
- if(item)
+ if (item)
item->updateTransform();
}
-QML_DEFINE_TYPE(QFxAxis,Axis);
+/*!
+ \qmlclass Axis
+ \brief An axis that can be used for rotation or translation.
+*/
+
+QML_DEFINE_TYPE(QFxAxis, Axis);
QFxAxis::QFxAxis(QObject *parent)
-: QFxTransform(parent), _xStart(0), _yStart(0), _xEnd(0), _yEnd(0), _zEnd(0), _rotation(0),
- _translation(0), _distanceToPlane(1024.), _dirty(true)
+: QObject(parent), _startX(0), _startY(0), _endX(0), _endY(0), _endZ(0)
{
}
-qreal QFxAxis::xStart() const
+QFxAxis::~QFxAxis()
{
- return _xStart;
}
-void QFxAxis::setXStart(qreal x)
+qreal QFxAxis::startX() const
{
- _xStart = x;
- update();
+ return _startX;
}
-qreal QFxAxis::yStart() const
+void QFxAxis::setStartX(qreal x)
{
- return _yStart;
+ _startX = x;
+ emit updated();
}
-void QFxAxis::setYStart(qreal y)
+qreal QFxAxis::startY() const
{
- _yStart = y;
- update();
+ return _startY;
}
-qreal QFxAxis::xEnd() const
+void QFxAxis::setStartY(qreal y)
{
- return _xEnd;
+ _startY = y;
+ emit updated();
}
-void QFxAxis::setXEnd(qreal x)
+qreal QFxAxis::endX() const
{
- _xEnd = x;
- update();
+ return _endX;
}
-qreal QFxAxis::yEnd() const
+void QFxAxis::setEndX(qreal x)
{
- return _yEnd;
+ _endX = x;
+ emit updated();
}
-void QFxAxis::setYEnd(qreal y)
+qreal QFxAxis::endY() const
{
- _yEnd = y;
- update();
+ return _endY;
}
-qreal QFxAxis::zEnd() const
+void QFxAxis::setEndY(qreal y)
{
- return _zEnd;
+ _endY = y;
+ emit updated();
}
-void QFxAxis::setZEnd(qreal z)
+qreal QFxAxis::endZ() const
{
-#if !defined(QFX_RENDER_OPENGL)
- if(z != 0. && translation() != 0.) {
- qmlInfo(this) << "QTransform cannot translate along Z-axis";
- return;
- }
-#endif
+ return _endZ;
+}
- _zEnd = z;
- update();
+void QFxAxis::setEndZ(qreal z)
+{
+ _endZ = z;
+ emit updated();
}
-qreal QFxAxis::rotation() const
+/*!
+ \qmlclass AxisRotation
+ \brief The AxisRotation element provides a way to rotate an Item around an axis.
+
+ Here is an example of various rotations applied to an \l Image.
+ \code
+ <HorizontalLayout margin="10" spacing="10">
+ <Image src="qt.png"/>
+ <Image src="qt.png">
+ <transform>
+ <AxisRotation axis.startX="30" axis.endX="30" axis.endY="60" angle="18"/>
+ </transform>
+ </Image>
+ <Image src="qt.png">
+ <transform>
+ <AxisRotation axis.startX="30" axis.endX="30" axis.endY="60" angle="36"/>
+ </transform>
+ </Image>
+ <Image src="qt.png">
+ <transform>
+ <AxisRotation axis.startX="30" axis.endX="30" axis.endY="60" angle="54"/>
+ </transform>
+ </Image>
+ <Image src="qt.png">
+ <transform>
+ <AxisRotation axis.startX="30" axis.endX="30" axis.endY="60" angle="72"/>
+ </transform>
+ </Image>
+ </HorizontalLayout>
+ \endcode
+
+ \image axisrotation.png
+*/
+
+QML_DEFINE_TYPE(QFxRotation,AxisRotation);
+
+QFxRotation::QFxRotation(QObject *parent)
+: QFxTransform(parent), _angle(0), _distanceToPlane(1024.), _dirty(true)
{
- return _rotation;
+ connect(&_axis, SIGNAL(updated()), this, SLOT(update()));
}
-void QFxAxis::setRotation(qreal r)
+QFxRotation::~QFxRotation()
{
- _rotation = r;
- update();
}
-qreal QFxAxis::translation() const
+/*!
+ \qmlproperty real AxisRotation::axis.startX
+ \qmlproperty real AxisRotation::axis.startY
+ \qmlproperty real AxisRotation::axis.endX
+ \qmlproperty real AxisRotation::axis.endY
+ \qmlproperty real AxisRotation::axis.endZ
+
+ A rotation axis is specified by 2 points in 3D space: a start point and
+ an end point. The z-position of the start point is assumed to be 0, and cannot
+ be changed.
+*/
+QFxAxis *QFxRotation::axis()
{
- return _translation;
+ return &_axis;
}
-void QFxAxis::setTranslation(qreal t)
+/*!
+ \qmlproperty real AxisRotation::angle
+
+ The angle, in degrees, to rotate around the specified axis.
+*/
+qreal QFxRotation::angle() const
{
-#if !defined(QFX_RENDER_OPENGL)
- if(zEnd() != 0. && t != 0.) {
- qmlInfo(this) << "QTransform cannot translate along Z-axis";
- return;
- }
-#endif
+ return _angle;
+}
- _translation = t;
+void QFxRotation::setAngle(qreal angle)
+{
+ _angle = angle;
update();
}
-bool QFxAxis::isIdentity() const
+bool QFxRotation::isIdentity() const
{
- return (_rotation == 0. && _translation == 0.) ||
- (zEnd() == 0. && yEnd() == yStart() && xEnd() == xStart());
+ return (_angle == 0.) || (_axis.endZ() == 0. && _axis.endY() == _axis.startY() && _axis.endX() == _axis.startX());
}
#if defined(QFX_RENDER_QPAINTER)
const qreal inv_dist_to_plane = 1. / 1024.;
-QTransform QFxAxis::transform() const
+QTransform QFxRotation::transform() const
{
- if(_dirty) {
+ if (_dirty) {
_transform = QTransform();
- if(!isIdentity()) {
- if(rotation() != 0.) {
+ if (!isIdentity()) {
+ if (angle() != 0.) {
QTransform rotTrans;
- rotTrans.translate(-xStart(), -yStart());
+ rotTrans.translate(-_axis.startX(), -_axis.startY());
QTransform rotTrans2;
- rotTrans2.translate(xStart(), yStart());
+ rotTrans2.translate(_axis.startX(), _axis.startY());
- qreal rad = rotation() * 2. * M_PI / 360.;
+ qreal rad = angle() * 2. * M_PI / 360.;
qreal c = ::cos(rad);
qreal s = ::sin(rad);
- qreal x = xEnd() - xStart();
- qreal y = yEnd() - yStart();
- qreal z = zEnd();
+ qreal x = _axis.endX() - _axis.startX();
+ qreal y = _axis.endY() - _axis.startY();
+ qreal z = _axis.endZ();
qreal idtp = inv_dist_to_plane;
- if(distanceToPlane() != 1024.)
+ if (distanceToPlane() != 1024.)
idtp = 1. / distanceToPlane();
qreal len = x * x + y * y + z * z;
- if(len != 1.) {
+ if (len != 1.) {
len = ::sqrt(len);
x /= len;
y /= len;
@@ -226,13 +279,6 @@ QTransform QFxAxis::transform() const
_transform *= rot;
_transform *= rotTrans2;
}
-
- if(translation() != 0.) {
- QTransform trans;
- trans.translate((xEnd() - xStart()) * translation(),
- (yEnd() - yStart()) * translation());
- _transform *= trans;
- }
}
_dirty = false;
@@ -241,27 +287,22 @@ QTransform QFxAxis::transform() const
return _transform;
}
#elif defined(QFX_RENDER_OPENGL)
-QMatrix4x4 QFxAxis::transform() const
+QMatrix4x4 QFxRotation::transform() const
{
- if(_dirty) {
+ if (_dirty) {
_dirty = false;
_transform = QMatrix4x4();
- if(!isIdentity()) {
- if(rotation() != 0.) {
- qreal x = xEnd() - xStart();
- qreal y = yEnd() - yStart();
- qreal z = zEnd();
+ if (!isIdentity()) {
+ if (angle() != 0.) {
+ qreal x = _axis.endX() - _axis.startX();
+ qreal y = _axis.endY() - _axis.startY();
+ qreal z = _axis.endZ();
- _transform.translate(xStart(), yStart(), 0);
- _transform.rotate(rotation(), x, y, z);
- _transform.translate(-xStart(), -yStart(), 0);
+ _transform.translate(_axis.startX(), _axis.startY(), 0);
+ _transform.rotate(angle(), x, y, z);
+ _transform.translate(-_axis.startX(), -_axis.startY(), 0);
}
-
- if(translation() != 0.)
- _transform.translate((xEnd() - xStart()) * translation(),
- (yEnd() - yStart()) * translation(),
- (zEnd()) * translation());
}
}
@@ -269,198 +310,161 @@ QMatrix4x4 QFxAxis::transform() const
}
#endif
-qreal QFxAxis::distanceToPlane() const
+/*!
+ \qmlproperty real AxisRotation::distanceToPlane
+*/
+qreal QFxRotation::distanceToPlane() const
{
return _distanceToPlane;
}
-void QFxAxis::setDistanceToPlane(qreal d)
+void QFxRotation::setDistanceToPlane(qreal d)
{
_distanceToPlane = d;
update();
}
-void QFxAxis::update()
+void QFxRotation::update()
{
_dirty = true;
QFxItem *item = qobject_cast<QFxItem *>(parent());
- if(item)
+ if (item)
item->updateTransform();
}
-QML_DEFINE_TYPE(QFxFlipable,Flipable);
-
-class QFxFlipablePrivate : public QFxItemPrivate
-{
-public:
- QFxFlipablePrivate() : current(QFxFlipable::Front), front(0), back(0) {}
-
- QFxFlipable::Side current;
- QFxItem *front;
- QFxItem *back;
-};
-
/*!
- \qmlclass Flipable QFxFlipable
- \brief The Flipable element provides a surface that can be flipped.
- \inherits Item
-
- Flipable allows you to specify a front and a back and then flip between those sides.
+ \qmlclass AxisTranslation
+ \brief The AxisTranslation element provides a way to move an Item along an axis.
+ The following example translates the image to 10, 3.
\code
- <Flipable id="flipable" width="40" height="40">
+ <Image src="logo.png">
<transform>
- <Axis id="axis" xStart="20" xEnd="20" yStart="20" yEnd="0" />
+ <AxisTranslation axis.startX="0" axis.startY="0" axis.endX="1" axis.endY=".3" distance="10"/>
</transform>
- <front>
- <Image file="front.png"/>
- </front>
- <back>
- <Image file="back.png"/>
- </back>
- <states>
- <State name="back">
- <SetProperty target="{axis}" property="rotation" value="180" />
- </State>
- </states>
- <transitions>
- <Transition>
- <NumericAnimation easing="easeInOutQuad" properties="rotation"/>
- </Transition>
- </transitions>
- </Flipable>
+ </Image>
\endcode
-
- \image flipable.gif
*/
-/*!
- \internal
- \class QFxFlipable
- \brief The QFxFlipable class provides a flipable surface.
-
- \ingroup group_widgets
+QML_DEFINE_TYPE(QFxTranslation,AxisTranslation);
- QFxFlipable allows you to specify a front and a back, as well as an
- axis for the flip.
-*/
+QFxTranslation::QFxTranslation(QObject *parent)
+: QFxTransform(parent), _distance(0), _dirty(true)
+{
+ connect(&_axis, SIGNAL(updated()), this, SLOT(update()));
+}
-QFxFlipable::QFxFlipable(QFxItem *parent)
-: QFxItem(*(new QFxFlipablePrivate), parent)
+QFxTranslation::~QFxTranslation()
{
}
-QFxFlipable::~QFxFlipable()
+/*!
+ \qmlproperty real AxisTranslation::axis.startX
+ \qmlproperty real AxisTranslation::axis.startY
+ \qmlproperty real AxisTranslation::axis.endX
+ \qmlproperty real AxisTranslation::axis.endY
+ \qmlproperty real AxisTranslation::axis.endZ
+
+ A translation axis is specified by 2 points in 3D space: a start point and
+ an end point. The z-position of the start point is assumed to be 0, and cannot
+ be changed. Changing the z-position of the end point is only valid when running
+ under OpenGL.
+*/
+QFxAxis *QFxTranslation::axis()
{
+ return &_axis;
}
/*!
- \qmlproperty Item Flipable::front
- \qmlproperty Item Flipable::back
+ \qmlproperty real AxisTranslation::distance
- The front and back sides of the flipable.
-*/
+ The distance to translate along the specified axis. distance is a multiplier;
+ in the example below, a distance of 1 would translate to 100, 50, while a distance
+ of 0.5 would translate to 50, 25.
-QFxItem *QFxFlipable::front()
+ \code
+ <AxisTranslation axis.startX="0" axis.startY="0" axis.endX="100" axis.endY="50"/>
+ \endcode
+*/
+qreal QFxTranslation::distance() const
{
- Q_D(const QFxFlipable);
- return d->front;
+ return _distance;
}
-void QFxFlipable::setFront(QFxItem *front)
+void QFxTranslation::setDistance(qreal distance)
{
- Q_D(QFxFlipable);
- if(d->front) {
- qmlInfo(this) << "front is a write-once property";
- return;
- }
- d->front = front;
- children()->append(d->front);
- if(Back == d->current)
- d->front->setOpacity(0.);
+ _distance = distance;
+ update();
}
-QFxItem *QFxFlipable::back()
+bool QFxTranslation::isIdentity() const
{
- Q_D(const QFxFlipable);
- return d->back;
+ return (_distance == 0.) || (_axis.endZ() == 0. && _axis.endY() == _axis.startY() && _axis.endX() == _axis.startX());
}
-void QFxFlipable::setBack(QFxItem *back)
+#if defined(QFX_RENDER_QPAINTER)
+QTransform QFxTranslation::transform() const
{
- Q_D(QFxFlipable);
- if(d->back) {
- qmlInfo(this) << "back is a write-once property";
- return;
- }
- d->back = back;
- children()->append(d->back);
- if(Front == d->current)
- d->back->setOpacity(0.);
-}
+ if (_dirty) {
+ _transform = QTransform();
-/*!
- \qmlproperty enumeration Flipable::side
+ if (!isIdentity()) {
+ if (distance() != 0.) {
+ QTransform trans;
+ trans.translate((_axis.endX() - _axis.startX()) * distance(),
+ (_axis.endY() - _axis.startY()) * distance());
+ _transform *= trans;
+ }
+ }
- The side of the Flippable currently visible. Possible values are \c
- Front and \c Back.
-*/
-QFxFlipable::Side QFxFlipable::side() const
-{
- Q_D(const QFxFlipable);
- return d->current;
-}
+ _dirty = false;
+ }
-void QFxFlipable::transformChanged(const QSimpleCanvas::Matrix &trans)
+ return _transform;
+}
+#elif defined(QFX_RENDER_OPENGL)
+QMatrix4x4 QFxRotation::transform() const
{
- Q_D(QFxFlipable);
- QPointF p1(0, 0);
- QPointF p2(1, 0);
- QPointF p3(1, 1);
-
- p1 = trans.map(p1);
- p2 = trans.map(p2);
- p3 = trans.map(p3);
+ if (_dirty) {
+ _dirty = false;
+ _transform = QMatrix4x4();
- qreal cross = (p1.x() - p2.x()) * (p3.y() - p2.y()) -
- (p1.y() - p2.y()) * (p3.x() - p2.x());
+ if (!isIdentity()) {
+ if (distance() != 0.)
+ _transform.translate((_axis.endX() - _axis.startX()) * distance(),
+ (_axis.endY() - _axis.startY()) * distance(),
+ (_axis.endZ()) * distance());
- Side newSide;
- if(cross > 0) {
- newSide = Back;
- } else {
- newSide = Front;
+ }
}
- if(newSide != d->current) {
- d->current = newSide;
- if (d->current==Back) {
- QSimpleCanvas::Matrix mat;
-#ifdef QFX_RENDER_OPENGL
- mat.translate(d->back->width()/2,d->back->height()/2, 0);
- if(d->back->width() && p1.x() >= p2.x())
- mat.rotate(180, 0, 1, 0);
- if(d->back->height() && p2.y() >= p3.y())
- mat.rotate(180, 1, 0, 0);
- mat.translate(-d->back->width()/2,-d->back->height()/2, 0);
-#else
- mat.translate(d->back->width()/2,d->back->height()/2);
- if(d->back->width() && p1.x() >= p2.x())
- mat.rotate(180, Qt::YAxis);
- if(d->back->height() && p2.y() >= p3.y())
- mat.rotate(180, Qt::XAxis);
- mat.translate(-d->back->width()/2,-d->back->height()/2);
+ return _transform;
+}
#endif
- d->back->setTransform(mat);
- }
- if(d->front)
- d->front->setOpacity((d->current==Front)?1.:0.);
- if(d->back)
- d->back->setOpacity((d->current==Back)?1.:0.);
- emit sideChanged();
+
+void QFxTranslation::update()
+{
+ _dirty = true;
+
+#if !defined(QFX_RENDER_OPENGL)
+ if (_axis.endZ() != 0. && distance() != 0.) {
+ qmlInfo(this) << "QTransform cannot translate along Z-axis.";
}
+#endif
+
+ QFxItem *item = qobject_cast<QFxItem *>(parent());
+ if (item)
+ item->updateTransform();
}
+/*!
+ \qmlclass Perspective
+ \brief The Perspective element specifies a perspective transformation.
+
+ A Perspective transform only affects an item when running under OpenGL; when running under software
+ rasterization it has no effect.
+*/
+
QML_DEFINE_TYPE(QFxPerspective,Perspective);
QFxPerspective::QFxPerspective(QObject *parent)
@@ -468,6 +472,10 @@ QFxPerspective::QFxPerspective(QObject *parent)
{
}
+QFxPerspective::~QFxPerspective()
+{
+}
+
#if defined(QFX_RENDER_OPENGL)
bool QFxPerspective::isIdentity() const
{
@@ -486,6 +494,33 @@ QMatrix4x4 QFxPerspective::transform() const
}
#endif
+/*!
+ \qmlproperty real Perspective::angle
+*/
+
+/*!
+ \qmlproperty real Perspective::aspect
+*/
+
+/*!
+ \qmlproperty real Perspective::x
+*/
+
+/*!
+ \qmlproperty real Perspective::y
+*/
+
+/*!
+ \qmlproperty real Perspective::scale
+*/
+
+/*!
+ \qmlclass Squish
+ \brief The Squish element allows you to distort an items appearance by 'squishing' it.
+
+ A Squish transform only affects an item when running under OpenGL; when running under software
+ rasterization it has no effect.
+*/
QML_DEFINE_TYPE(QFxSquish,Squish);
QFxSquish::QFxSquish(QObject *parent)
@@ -493,6 +528,13 @@ QFxSquish::QFxSquish(QObject *parent)
{
}
+QFxSquish::~QFxSquish()
+{
+}
+
+/*!
+ \qmlproperty real Squish::x
+*/
qreal QFxSquish::x() const
{
return p.x();
@@ -504,6 +546,9 @@ void QFxSquish::setX(qreal v)
update();
}
+/*!
+ \qmlproperty real Squish::y
+*/
qreal QFxSquish::y() const
{
return p.y();
@@ -515,6 +560,9 @@ void QFxSquish::setY(qreal v)
update();
}
+/*!
+ \qmlproperty real Squish::width
+*/
qreal QFxSquish::width() const
{
return s.width();
@@ -526,6 +574,9 @@ void QFxSquish::setWidth(qreal v)
update();
}
+/*!
+ \qmlproperty real Squish::height
+*/
qreal QFxSquish::height() const
{
return s.height();
@@ -537,6 +588,10 @@ void QFxSquish::setHeight(qreal v)
update();
}
+/*!
+ \qmlproperty real Squish::topLeftX
+ \qmlproperty real Squish::topLeftY
+*/
qreal QFxSquish::topLeft_x() const
{
return p1.x();
@@ -559,6 +614,10 @@ void QFxSquish::settopLeft_y(qreal v)
update();
}
+/*!
+ \qmlproperty real Squish::topRightX
+ \qmlproperty real Squish::topRightY
+*/
qreal QFxSquish::topRight_x() const
{
return p2.x();
@@ -581,6 +640,10 @@ void QFxSquish::settopRight_y(qreal v)
update();
}
+/*!
+ \qmlproperty real Squish::bottomLeftX
+ \qmlproperty real Squish::bottomLeftY
+*/
qreal QFxSquish::bottomLeft_x() const
{
return p3.x();
@@ -603,6 +666,10 @@ void QFxSquish::setbottomLeft_y(qreal v)
update();
}
+/*!
+ \qmlproperty real Squish::bottomRightX
+ \qmlproperty real Squish::bottomRightY
+*/
qreal QFxSquish::bottomRight_x() const
{
return p4.x();
@@ -628,7 +695,7 @@ void QFxSquish::setbottomRight_y(qreal v)
void QFxSquish::update()
{
QFxItem *item = qobject_cast<QFxItem *>(parent());
- if(item)
+ if (item)
item->updateTransform();
}
@@ -647,10 +714,11 @@ QMatrix4x4 QFxSquish::transform() const
QTransform t;
QMatrix4x4 rv;
- if(QTransform::quadToQuad(poly, poly2, t))
+ if (QTransform::quadToQuad(poly, poly2, t))
rv = QMatrix4x4(t);
return rv;
}
-QT_END_NAMESPACE
#endif
+
+QT_END_NAMESPACE