summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qtriangulatingstroker.cpp
diff options
context:
space:
mode:
authorDmitry Kazakov <dimula73@gmail.com>2020-05-08 16:06:42 +0300
committerDmitry Kazakov <dimula73@gmail.com>2020-05-15 02:06:25 +0300
commitd26ee69140ac2658fcc5a7a516ad52c2b51a1774 (patch)
tree64a5f8b4e7ebfa282ae1c1d3d8a01d4c431691bf /src/gui/painting/qtriangulatingstroker.cpp
parent3b7f278d38582d100b8a5da6b790d765e52420eb (diff)
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: Laszlo Agocs <laszlo.agocs@qt.io> Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Diffstat (limited to 'src/gui/painting/qtriangulatingstroker.cpp')
-rw-r--r--src/gui/painting/qtriangulatingstroker.cpp35
1 files changed, 27 insertions, 8 deletions
diff --git a/src/gui/painting/qtriangulatingstroker.cpp b/src/gui/painting/qtriangulatingstroker.cpp
index 8e0308f268..14acc1a480 100644
--- a/src/gui/painting/qtriangulatingstroker.cpp
+++ b/src/gui/painting/qtriangulatingstroker.cpp
@@ -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
-