summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qtransform.cpp
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2009-08-04 09:00:23 +1000
committerWarwick Allison <warwick.allison@nokia.com>2009-08-04 09:00:23 +1000
commit897014a47b41dcf2b9d91549be9b96890d5291c7 (patch)
tree91da900adb42122eebdef573c012051ea511e42d /src/gui/painting/qtransform.cpp
parent37cdd053623bfadded77ba6ad34e0d4c45158cc7 (diff)
parent2076f150995e541308b1d8da936b3e12ab68b886 (diff)
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Diffstat (limited to 'src/gui/painting/qtransform.cpp')
-rw-r--r--src/gui/painting/qtransform.cpp47
1 files changed, 25 insertions, 22 deletions
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index a322fe4de..0a64e4ede 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -48,6 +48,8 @@
#include "qvariant.h"
#include <qmath.h>
+#include <private/qbezier_p.h>
+
QT_BEGIN_NAMESPACE
#define Q_NEAR_CLIP 0.000001
@@ -1492,27 +1494,12 @@ static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transfor
static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo)
{
- const QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
- const QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
- const QHomogeneousCoordinate hc = mapHomogeneous(transform, c);
- const QHomogeneousCoordinate hd = mapHomogeneous(transform, d);
-
- if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP && hc.w < Q_NEAR_CLIP && hd.w < Q_NEAR_CLIP)
- return false;
+ // Convert projective xformed curves to line
+ // segments so they can be transformed more accurately
+ QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon();
- if (ha.w >= Q_NEAR_CLIP && hb.w >= Q_NEAR_CLIP && hc.w >= Q_NEAR_CLIP && hd.w >= Q_NEAR_CLIP) {
- if (needsMoveTo)
- path.moveTo(ha.toPoint());
-
- path.cubicTo(hb.toPoint(), hc.toPoint(), hd.toPoint());
- return true;
- }
-
- if (lineTo_clipped(path, transform, a, b, needsMoveTo))
- needsMoveTo = false;
- if (lineTo_clipped(path, transform, b, c, needsMoveTo))
- needsMoveTo = false;
- if (lineTo_clipped(path, transform, c, d, needsMoveTo))
+ for (int i = 0; i < segment.size() - 1; ++i)
+ if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
needsMoveTo = false;
return !needsMoveTo;
@@ -1793,6 +1780,14 @@ void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
m_dirty = TxProject;
}
+static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform)
+{
+ const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right());
+ const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom());
+
+ return wx + wy + transform.m33() < Q_NEAR_CLIP;
+}
+
QRect QTransform::mapRect(const QRect &rect) const
{
TransformationType t = inline_type();
@@ -1813,7 +1808,7 @@ QRect QTransform::mapRect(const QRect &rect) const
y -= h;
}
return QRect(x, y, w, h);
- } else {
+ } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
// see mapToPolygon for explanations of the algorithm.
qreal x = 0, y = 0;
MAP(rect.left(), rect.top(), x, y);
@@ -1837,6 +1832,10 @@ QRect QTransform::mapRect(const QRect &rect) const
xmax = qMax(xmax, x);
ymax = qMax(ymax, y);
return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin));
+ } else {
+ QPainterPath path;
+ path.addRect(rect);
+ return map(path).boundingRect().toRect();
}
}
@@ -1879,7 +1878,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const
y -= h;
}
return QRectF(x, y, w, h);
- } else {
+ } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
qreal x = 0, y = 0;
MAP(rect.x(), rect.y(), x, y);
qreal xmin = x;
@@ -1902,6 +1901,10 @@ QRectF QTransform::mapRect(const QRectF &rect) const
xmax = qMax(xmax, x);
ymax = qMax(ymax, y);
return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
+ } else {
+ QPainterPath path;
+ path.addRect(rect);
+ return map(path).boundingRect();
}
}