summaryrefslogtreecommitdiffstats
path: root/src/gui/opengl/qtriangulatingstroker.cpp
diff options
context:
space:
mode:
authorKim Motoyoshi Kalland <kim.kalland@nokia.com>2012-07-05 14:52:53 +0200
committerQt by Nokia <qt-info@nokia.com>2012-07-06 13:58:34 +0200
commitd13e3441a9a3f11c7f9c9ebb21a514526987f56e (patch)
tree6c2494acd66c2b3598787fd41114b421369b548a /src/gui/opengl/qtriangulatingstroker.cpp
parent16f8afa5b1c906ae60f98619d17c34b40c21804e (diff)
Fix division by zero in triangulating stroker.
Task-number: QTBUG-15621 Change-Id: I10e0e39e57078507a01e1c2edb59fa52fd932f6c Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
Diffstat (limited to 'src/gui/opengl/qtriangulatingstroker.cpp')
-rw-r--r--src/gui/opengl/qtriangulatingstroker.cpp68
1 files changed, 48 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<end && types[i] != QPainterPath::MoveToElement) {
++i;
}
- endsAtStart = startPts[0] == pts[i*2 - 2] && startPts[1] == pts[i*2 - 1];
+ endsAtStart = float(startPts[0]) == float(pts[i*2 - 2])
+ && float(startPts[1]) == float(pts[i*2 - 1]);
if (endsAtStart || path.hasImplicitClose())
m_cap_style = Qt::FlatCap;
- moveTo(pts);
+ moveTo(startPts);
m_cap_style = cap;
+ previousType = QPainterPath::MoveToElement;
+ previousPts = pts;
pts+=2;
++types;
break; }
case QPainterPath::LineToElement:
- if (*(types - 1) != QPainterPath::MoveToElement)
- join(pts);
- lineTo(pts);
+ if (float(m_cx) != float(pts[0]) || float(m_cy) != float(pts[1])) {
+ if (previousType != QPainterPath::MoveToElement)
+ join(pts);
+ lineTo(pts);
+ previousType = QPainterPath::LineToElement;
+ previousPts = pts;
+ }
pts+=2;
++types;
break;
case QPainterPath::CurveToElement:
- if (*(types - 1) != QPainterPath::MoveToElement)
- join(pts);
- cubicTo(pts);
+ if (float(m_cx) != float(pts[0]) || float(m_cy) != float(pts[1])
+ || float(pts[0]) != float(pts[2]) || float(pts[1]) != float(pts[3])
+ || float(pts[2]) != float(pts[4]) || float(pts[3]) != float(pts[5]))
+ {
+ if (previousType != QPainterPath::MoveToElement)
+ join(pts);
+ cubicTo(pts);
+ previousType = QPainterPath::CurveToElement;
+ previousPts = pts + 4;
+ }
pts+=6;
types+=3;
break;
@@ -219,7 +246,8 @@ void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, co
}
}
- endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart);
+ if (previousType != QPainterPath::MoveToElement)
+ endCapOrJoinClosed(startPts, previousPts, path.hasImplicitClose(), endsAtStart);
}
}