From d13e3441a9a3f11c7f9c9ebb21a514526987f56e Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Thu, 5 Jul 2012 14:52:53 +0200 Subject: Fix division by zero in triangulating stroker. Task-number: QTBUG-15621 Change-Id: I10e0e39e57078507a01e1c2edb59fa52fd932f6c Reviewed-by: Gunnar Sletta --- src/gui/opengl/qtriangulatingstroker.cpp | 68 ++++++++++++++++++++--------- src/gui/opengl/qtriangulatingstroker_p.h | 1 + tests/auto/gui/qopengl/tst_qopengl.cpp | 75 ++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 20 deletions(-) diff --git a/src/gui/opengl/qtriangulatingstroker.cpp b/src/gui/opengl/qtriangulatingstroker.cpp index c22b731ca0..8c054290dc 100644 --- a/src/gui/opengl/qtriangulatingstroker.cpp +++ b/src/gui/opengl/qtriangulatingstroker.cpp @@ -72,6 +72,14 @@ void QTriangulatingStroker::endCapOrJoinClosed(const qreal *start, const qreal * m_vertices.add(y); } +static inline void skipDuplicatePoints(const qreal **pts, const qreal *endPts) +{ + while ((*pts + 2) < endPts && float((*pts)[0]) == float((*pts)[2]) + && float((*pts)[1]) == float((*pts)[3])) + { + *pts += 2; + } +} void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, const QRectF &) { @@ -149,67 +157,86 @@ void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, co Qt::PenCapStyle cap = m_cap_style; if (!types) { - // skip duplicate points - while((pts + 2) < endPts && pts[0] == pts[2] && pts[1] == pts[3]) - pts += 2; + skipDuplicatePoints(&pts, endPts); if ((pts + 2) == endPts) return; startPts = pts; - bool endsAtStart = startPts[0] == *(endPts-2) && startPts[1] == *(endPts-1); + bool endsAtStart = float(startPts[0]) == float(endPts[-2]) + && float(startPts[1]) == float(endPts[-1]); if (endsAtStart || path.hasImplicitClose()) m_cap_style = Qt::FlatCap; moveTo(pts); m_cap_style = cap; pts += 2; + skipDuplicatePoints(&pts, endPts); lineTo(pts); pts += 2; + skipDuplicatePoints(&pts, endPts); while (pts < endPts) { - if (m_cx != pts[0] || m_cy != pts[1]) { - join(pts); - lineTo(pts); - } + join(pts); + lineTo(pts); pts += 2; + skipDuplicatePoints(&pts, endPts); } - endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart); } else { bool endsAtStart = false; + QPainterPath::ElementType previousType = QPainterPath::MoveToElement; + const qreal *previousPts = pts; while (pts < endPts) { switch (*types) { case QPainterPath::MoveToElement: { - if (pts != path.points()) - endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart); + if (previousType != QPainterPath::MoveToElement) + endCapOrJoinClosed(startPts, previousPts, path.hasImplicitClose(), endsAtStart); startPts = pts; + skipDuplicatePoints(&startPts, endPts); // Skip duplicates to find correct normal. + if (startPts + 2 >= endPts) + return; // Nothing to see here... + int end = (endPts - pts) / 2; int i = 2; // Start looking to ahead since we never have two moveto's in a row while (i