1From 4fd852af39e1169d8d0a27b96b2d3b6bbfdb0cb4 Mon Sep 17 00:00:00 2001
2From: Dmitry Kazakov <dimula73@gmail.com>
3Date: Fri, 8 May 2020 16:06:42 +0300
4Subject: [PATCH] Fix artifacts when rendering multisubpath dashed QPainterPath
5 with openGL
6
7It might happen that the resulting subpath generated by the QDashStroker
8will have no lines at all. It happens when further LineToElement items
9compare as equal to the starting MoveToElement when compared in 'float'
10space. In such case QTriangulatingStroker::process() skips LineTo elements
11and the vertexBuffer ends up with unconnected vertices, which generate
12unwanted triangles.
13
14See related bugs:
15https://bugs.kde.org/show_bug.cgi?id=419240
16https://bugs.kde.org/show_bug.cgi?id=413220
17---
18 src/gui/painting/qtriangulatingstroker.cpp | 35 +++++++++++++++++-----
19 1 file changed, 27 insertions(+), 8 deletions(-)
20
21diff --git a/src/gui/painting/qtriangulatingstroker.cpp b/src/gui/painting/qtriangulatingstroker.cpp
22index b1b07f96..5b7d7ca3 100644
23--- a/src/gui/painting/qtriangulatingstroker.cpp
24+++ b/src/gui/painting/qtriangulatingstroker.cpp
25@@ -188,6 +188,31 @@ void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, co
26         while (pts < endPts) {
27             switch (*types) {
28             case QPainterPath::MoveToElement: {
29+                int end = (endPts - pts) / 2;
30+                int nextMoveElement = 1;
31+                bool hasValidLineSegments = false;
32+                while (nextMoveElement < end && types[nextMoveElement] != QPainterPath::MoveToElement) {
33+                    if (!hasValidLineSegments) {
34+                        hasValidLineSegments =
35+                            float(pts[0]) != float(pts[nextMoveElement * 2]) ||
36+                            float(pts[1]) != float(pts[nextMoveElement * 2 + 1]);
37+                    }
38+                    ++nextMoveElement;
39+                }
40+
41+                /**
42+                 * 'LineToElement' may be skipped if it doesn't move the center point
43+                 * of the line. We should make sure that we don't end up with a lost
44+                 * 'MoveToElement' in the vertex buffer, not connected to anything. Since
45+                 * the buffer uses degenerate triangles trick to split the primitives,
46+                 * this spurious MoveToElement will create artifacts when rendering.
47+                 */
48+                if (!hasValidLineSegments) {
49+                    pts += 2 * nextMoveElement;
50+                    types += nextMoveElement;
51+                    continue;
52+                }
53+
54                 if (previousType != QPainterPath::MoveToElement)
55                     endCapOrJoinClosed(startPts, previousPts, path.hasImplicitClose(), endsAtStart);
56
57@@ -196,13 +221,8 @@ void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, co
58                 if (startPts + 2 >= endPts)
59                     return; // Nothing to see here...
60
61-                int end = (endPts - pts) / 2;
62-                int i = 2; // Start looking to ahead since we never have two moveto's in a row
63-                while (i<end && types[i] != QPainterPath::MoveToElement) {
64-                    ++i;
65-                }
66-                endsAtStart = float(startPts[0]) == float(pts[i*2 - 2])
67-                        && float(startPts[1]) == float(pts[i*2 - 1]);
68+                endsAtStart = float(startPts[0]) == float(pts[nextMoveElement * 2 - 2])
69+                        && float(startPts[1]) == float(pts[nextMoveElement * 2 - 1]);
70                 if (endsAtStart || path.hasImplicitClose())
71                     m_cap_style = Qt::FlatCap;
72
73@@ -619,4 +639,3 @@ void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen, c
74 }
75
76 QT_END_NAMESPACE
77-
78--
792.20.1.windows.1
80
81