summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2009-06-17 13:46:19 (GMT)
committerSamuel Rødal <sroedal@trolltech.com>2009-06-17 14:29:42 (GMT)
commitc65262cf3e3cd9c72184582306e550f686b2f27e (patch)
tree7e5857a1abf3b3378416810f90c94fc9509b8af8
parente3736c5031b941a665952a9696d989d79b25f32f (diff)
downloadQt-c65262cf3e3cd9c72184582306e550f686b2f27e.zip
Qt-c65262cf3e3cd9c72184582306e550f686b2f27e.tar.gz
Qt-c65262cf3e3cd9c72184582306e550f686b2f27e.tar.bz2
Fixed bugs in QPainterPath::united().
Change from a relative to an absolute fuzzy compare as was the case pre-4.4. With a relative fuzzy compare points that have an x or y coordinate of 0 will never be merged with points that are very close to 0, for example (1e-15, 0). Task-number: 251909 Reviewed-by: Trond
-rw-r--r--src/gui/painting/qpathclipper.cpp69
-rw-r--r--tests/auto/qpathclipper/tst_qpathclipper.cpp20
2 files changed, 62 insertions, 27 deletions
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index 544b838..d4c92cc 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -45,9 +45,6 @@
#include <private/qdatabuffer_p.h>
#include <qmath.h>
-#include <QImage>
-#include <QPainter>
-
/**
The algorithm is as follows:
@@ -68,6 +65,20 @@
QT_BEGIN_NAMESPACE
+static inline bool fuzzyIsNull(qreal d)
+{
+ if (sizeof(qreal) == sizeof(double))
+ return qAbs(d) <= 1e-12;
+ else
+ return qAbs(d) <= 1e-5f;
+}
+
+static inline bool comparePoints(const QPointF &a, const QPointF &b)
+{
+ return fuzzyIsNull(a.x() - b.x())
+ && fuzzyIsNull(a.y() - b.y());
+}
+
//#define QDEBUG_CLIPPER
static qreal dot(const QPointF &a, const QPointF &b)
{
@@ -105,8 +116,10 @@ private:
bool QIntersectionFinder::beziersIntersect(const QBezier &one, const QBezier &two) const
{
- return (one.pt1() == two.pt1() && one.pt2() == two.pt2() && one.pt3() == two.pt3() && one.pt4() == two.pt4())
- || (one.pt1() == two.pt4() && one.pt2() == two.pt3() && one.pt3() == two.pt2() && one.pt4() == two.pt1())
+ return (comparePoints(one.pt1(), two.pt1()) && comparePoints(one.pt2(), two.pt2())
+ && comparePoints(one.pt3(), two.pt3()) && comparePoints(one.pt4(), two.pt4()))
+ || (comparePoints(one.pt1(), two.pt4()) && comparePoints(one.pt2(), two.pt3())
+ && comparePoints(one.pt3(), two.pt2()) && comparePoints(one.pt4(), two.pt1()))
|| QBezier::findIntersections(one, two, 0);
}
@@ -118,17 +131,17 @@ bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const
const QPointF q1 = b.p1();
const QPointF q2 = b.p2();
- if (p1 == p2 || q1 == q2)
+ if (comparePoints(p1, p2) || comparePoints(q1, q2))
return false;
- const bool p1_equals_q1 = (p1 == q1);
- const bool p2_equals_q2 = (p2 == q2);
+ const bool p1_equals_q1 = comparePoints(p1, q1);
+ const bool p2_equals_q2 = comparePoints(p2, q2);
if (p1_equals_q1 && p2_equals_q2)
return true;
- const bool p1_equals_q2 = (p1 == q2);
- const bool p2_equals_q1 = (p2 == q1);
+ const bool p1_equals_q2 = comparePoints(p1, q2);
+ const bool p2_equals_q1 = comparePoints(p2, q1);
if (p1_equals_q2 && p2_equals_q1)
return true;
@@ -184,8 +197,10 @@ bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const
void QIntersectionFinder::intersectBeziers(const QBezier &one, const QBezier &two, QVector<QPair<qreal, qreal> > &t, QDataBuffer<QIntersection> &intersections)
{
- if ((one.pt1() == two.pt1() && one.pt2() == two.pt2() && one.pt3() == two.pt3() && one.pt4() == two.pt4())
- || (one.pt1() == two.pt4() && one.pt2() == two.pt3() && one.pt3() == two.pt2() && one.pt4() == two.pt1())) {
+ if ((comparePoints(one.pt1(), two.pt1()) && comparePoints(one.pt2(), two.pt2())
+ && comparePoints(one.pt3(), two.pt3()) && comparePoints(one.pt4(), two.pt4()))
+ || (comparePoints(one.pt1(), two.pt4()) && comparePoints(one.pt2(), two.pt3())
+ && comparePoints(one.pt3(), two.pt2()) && comparePoints(one.pt4(), two.pt1()))) {
return;
}
@@ -230,17 +245,17 @@ void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QData
const QPointF q1 = b.p1();
const QPointF q2 = b.p2();
- if (p1 == p2 || q1 == q2)
+ if (comparePoints(p1, p2) || comparePoints(q1, q2))
return;
- const bool p1_equals_q1 = (p1 == q1);
- const bool p2_equals_q2 = (p2 == q2);
+ const bool p1_equals_q1 = comparePoints(p1, q1);
+ const bool p2_equals_q2 = comparePoints(p2, q2);
if (p1_equals_q1 && p2_equals_q2)
return;
- const bool p1_equals_q2 = (p1 == q2);
- const bool p2_equals_q1 = (p2 == q1);
+ const bool p1_equals_q2 = comparePoints(p1, q2);
+ const bool p2_equals_q1 = comparePoints(p2, q1);
if (p1_equals_q2 && p2_equals_q1)
return;
@@ -624,11 +639,11 @@ public:
const qreal pivot = pivotComponents[depth & 1];
const qreal value = pointComponents[depth & 1];
- if (qFuzzyCompare(pivot, value)) {
+ if (fuzzyIsNull(pivot - value)) {
const qreal pivot2 = pivotComponents[(depth + 1) & 1];
const qreal value2 = pointComponents[(depth + 1) & 1];
- if (qFuzzyCompare(pivot2, value2)) {
+ if (fuzzyIsNull(pivot2 - value2)) {
if (node.id < 0)
node.id = m_tree->nextId();
@@ -802,15 +817,15 @@ QWingedEdge::TraversalStatus QWingedEdge::next(const QWingedEdge::TraversalStatu
static bool isLine(const QBezier &bezier)
{
- const bool equal_1_2 = bezier.pt1() == bezier.pt2();
- const bool equal_2_3 = bezier.pt2() == bezier.pt3();
- const bool equal_3_4 = bezier.pt3() == bezier.pt4();
+ const bool equal_1_2 = comparePoints(bezier.pt1(), bezier.pt2());
+ const bool equal_2_3 = comparePoints(bezier.pt2(), bezier.pt3());
+ const bool equal_3_4 = comparePoints(bezier.pt3(), bezier.pt4());
// point?
if (equal_1_2 && equal_2_3 && equal_3_4)
return true;
- if (bezier.pt1() == bezier.pt4())
+ if (comparePoints(bezier.pt1(), bezier.pt4()))
return equal_1_2 || equal_3_4;
return (equal_1_2 && equal_3_4) || (equal_1_2 && equal_2_3) || (equal_2_3 && equal_3_4);
@@ -844,14 +859,14 @@ void QPathSegments::addPath(const QPainterPath &path)
else
currentPoint = path.elementAt(i);
- if (i > 0 && m_points.at(lastMoveTo) == currentPoint)
+ if (i > 0 && comparePoints(m_points.at(lastMoveTo), currentPoint))
current = lastMoveTo;
else
m_points << currentPoint;
switch (path.elementAt(i).type) {
case QPainterPath::MoveToElement:
- if (hasMoveTo && last != lastMoveTo && m_points.at(last) != m_points.at(lastMoveTo))
+ if (hasMoveTo && last != lastMoveTo && !comparePoints(m_points.at(last), m_points.at(lastMoveTo)))
m_segments << Segment(m_pathId, last, lastMoveTo);
hasMoveTo = true;
last = lastMoveTo = current;
@@ -879,7 +894,7 @@ void QPathSegments::addPath(const QPainterPath &path)
}
}
- if (hasMoveTo && last != lastMoveTo && m_points.at(last) != m_points.at(lastMoveTo))
+ if (hasMoveTo && last != lastMoveTo && !comparePoints(m_points.at(last), m_points.at(lastMoveTo)))
m_segments << Segment(m_pathId, last, lastMoveTo);
for (int i = firstSegment; i < m_segments.size(); ++i) {
@@ -1357,7 +1372,7 @@ void QWingedEdge::addBezierEdge(const QBezier *bezier, const QPointF &a, const Q
if (qFuzzyCompare(alphaA, alphaB))
return;
- if (a == b) {
+ if (comparePoints(a, b)) {
int v = insert(a);
addBezierEdge(bezier, v, v, alphaA, alphaB, path);
diff --git a/tests/auto/qpathclipper/tst_qpathclipper.cpp b/tests/auto/qpathclipper/tst_qpathclipper.cpp
index f3077ee..6e6b632 100644
--- a/tests/auto/qpathclipper/tst_qpathclipper.cpp
+++ b/tests/auto/qpathclipper/tst_qpathclipper.cpp
@@ -93,6 +93,7 @@ private slots:
void task204301();
void task209056();
+ void task251909();
};
Q_DECLARE_METATYPE(QPainterPath)
@@ -1397,6 +1398,25 @@ void tst_QPathClipper::task209056()
QVERIFY(p3 != QPainterPath());
}
+void tst_QPathClipper::task251909()
+{
+ QPainterPath p1;
+ p1.moveTo(0, -10);
+ p1.lineTo(10, -10);
+ p1.lineTo(10, 0);
+ p1.lineTo(0, 0);
+
+ QPainterPath p2;
+ p2.moveTo(0, 8e-14);
+ p2.lineTo(10, -8e-14);
+ p2.lineTo(10, 10);
+ p2.lineTo(0, 10);
+
+ QPainterPath result = p1.united(p2);
+
+ QVERIFY(result.elementCount() <= 5);
+}
+
QTEST_APPLESS_MAIN(tst_QPathClipper)