Commit e8505d99 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

Fix artifacts when rendering multisubpath dashed QPainterPath with openGL

It might happen that the resulting subpath generated by the QDashStroker
will have no lines at all. It happens when further LineToElement items
compare as equal to the starting MoveToElement when compared in 'float'
space. In such case QTriangulatingStroker::process() skips LineTo elements
and the vertexBuffer ends up with unconnected vertices, which generate
unwanted triangles.

See related bugs:
https://bugs.kde.org/show_bug.cgi?id=419240
https://bugs.kde.org/show_bug.cgi?id=413220



Change-Id: Ie70955287da47e9f7aa9cdeaea506e1c817b2317
Reviewed-by: default avatarLaszlo Agocs <laszlo.agocs@qt.io>
Reviewed-by: default avatarEirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit d26ee691)
parent 28f6bd38
......@@ -188,6 +188,31 @@ void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, co
while (pts < endPts) {
switch (*types) {
case QPainterPath::MoveToElement: {
int end = (endPts - pts) / 2;
int nextMoveElement = 1;
bool hasValidLineSegments = false;
while (nextMoveElement < end && types[nextMoveElement] != QPainterPath::MoveToElement) {
if (!hasValidLineSegments) {
hasValidLineSegments =
float(pts[0]) != float(pts[nextMoveElement * 2]) ||
float(pts[1]) != float(pts[nextMoveElement * 2 + 1]);
}
++nextMoveElement;
}
/**
* 'LineToElement' may be skipped if it doesn't move the center point
* of the line. We should make sure that we don't end up with a lost
* 'MoveToElement' in the vertex buffer, not connected to anything. Since
* the buffer uses degenerate triangles trick to split the primitives,
* this spurious MoveToElement will create artifacts when rendering.
*/
if (!hasValidLineSegments) {
pts += 2 * nextMoveElement;
types += nextMoveElement;
continue;
}
if (previousType != QPainterPath::MoveToElement)
endCapOrJoinClosed(startPts, previousPts, path.hasImplicitClose(), endsAtStart);
......@@ -196,13 +221,8 @@ void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, co
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 = float(startPts[0]) == float(pts[i*2 - 2])
&& float(startPts[1]) == float(pts[i*2 - 1]);
endsAtStart = float(startPts[0]) == float(pts[nextMoveElement * 2 - 2])
&& float(startPts[1]) == float(pts[nextMoveElement * 2 - 1]);
if (endsAtStart || path.hasImplicitClose())
m_cap_style = Qt::FlatCap;
......@@ -619,4 +639,3 @@ void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen, c
}
QT_END_NAMESPACE
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment