Fix painterpath rect intersections with points on the rect
QPainterPath could in certain cases where sub-path points were on the border of a rect fail to calculate intersects() correctly. The patch adds handling of such cases by looking if end points cross in or out of the rect. Other cases are already caught. Task-number: QTBUG-31551 Change-Id: I6284da8ff8646d4636702923a76362302dde5767 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
parent
13de0e5129
commit
07fd674740
@ -1981,6 +1981,17 @@ static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qr
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool pointOnEdge(const QRectF &rect, const QPointF &point)
|
||||
{
|
||||
if ((point.x() == rect.left() || point.x() == rect.right()) &&
|
||||
(point.y() >= rect.top() && point.y() <= rect.bottom()))
|
||||
return true;
|
||||
if ((point.y() == rect.top() || point.y() == rect.bottom()) &&
|
||||
(point.x() >= rect.left() && point.x() <= rect.right()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns \c true if any lines or curves cross the four edges in of rect
|
||||
*/
|
||||
@ -1988,6 +1999,7 @@ static bool qt_painterpath_check_crossing(const QPainterPath *path, const QRectF
|
||||
{
|
||||
QPointF last_pt;
|
||||
QPointF last_start;
|
||||
enum { OnRect, InsideRect, OutsideRect} edgeStatus = OnRect;
|
||||
for (int i=0; i<path->elementCount(); ++i) {
|
||||
const QPainterPath::Element &e = path->elementAt(i);
|
||||
|
||||
@ -2026,6 +2038,27 @@ static bool qt_painterpath_check_crossing(const QPainterPath *path, const QRectF
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Handle crossing the edges of the rect at the end-points of individual sub-paths.
|
||||
// A point on on the edge itself is considered neither inside nor outside for this purpose.
|
||||
if (!pointOnEdge(rect, last_pt)) {
|
||||
bool contained = rect.contains(last_pt);
|
||||
switch (edgeStatus) {
|
||||
case OutsideRect:
|
||||
if (contained)
|
||||
return true;
|
||||
break;
|
||||
case InsideRect:
|
||||
if (!contained)
|
||||
return true;
|
||||
break;
|
||||
case OnRect:
|
||||
edgeStatus = contained ? InsideRect : OutsideRect;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (last_pt == last_start)
|
||||
edgeStatus = OnRect;
|
||||
}
|
||||
}
|
||||
|
||||
// implicitly close last subpath
|
||||
|
@ -101,6 +101,7 @@ private slots:
|
||||
void lineWithinBounds();
|
||||
|
||||
void intersectionEquality();
|
||||
void intersectionPointOnEdge();
|
||||
};
|
||||
|
||||
void tst_QPainterPath::cleanupTestCase()
|
||||
@ -1363,6 +1364,17 @@ void tst_QPainterPath::intersectionEquality()
|
||||
QVERIFY(i1 == i2 || i1.toReversed() == i2);
|
||||
}
|
||||
|
||||
void tst_QPainterPath::intersectionPointOnEdge()
|
||||
{
|
||||
// From QTBUG-31551
|
||||
QPainterPath p; p.addRoundedRect(-10, 10, 40, 40, 10, 10);
|
||||
QRectF r(0, 0, 100, 100);
|
||||
QPainterPath rp; rp.addRect(r);
|
||||
QVERIFY(!p.intersected(rp).isEmpty());
|
||||
QVERIFY(p.intersects(rp));
|
||||
QVERIFY(p.intersects(r));
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QPainterPath)
|
||||
|
||||
#include "tst_qpainterpath.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user