Description: avoid processing-intensive painting of high number of tiny dashes
 When stroking a dashed path, an unnecessary amount of processing would
 be spent if there is a huge number of dashes visible, e.g. because of
 scaling. Since the dashes are too small to be individually visible
 anyway, just replace with a semi-transparent solid line for such
 cases.
Origin: upstream, commits:
 https://code.qt.io/cgit/qt/qtbase.git/commit/?id=7f345f2a1c8d9f60
 https://code.qt.io/cgit/qt/qtbase.git/commit/?id=9378ba2ae857df7e
 https://code.qt.io/cgit/qt/qtbase.git/commit/?id=81998f50d039a631
 https://code.qt.io/cgit/qt/qtbase.git/commit/?id=cca8ed0547405b1c
Last-Update: 2021-12-12

--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -385,10 +385,10 @@ QPainterState *QPaintEngineEx::createSta
 
 Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
 
-void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
+void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
 {
 #ifdef QT_DEBUG_DRAW
-    qDebug() << "QPaintEngineEx::stroke()" << pen;
+    qDebug() << "QPaintEngineEx::stroke()" << inPen;
 #endif
 
     Q_D(QPaintEngineEx);
@@ -403,6 +403,38 @@ void QPaintEngineEx::stroke(const QVecto
         d->stroker.setCubicToHook(qpaintengineex_cubicTo);
     }
 
+    QRectF clipRect;
+    QPen pen = inPen;
+    if (pen.style() > Qt::SolidLine) {
+        QRectF cpRect = path.controlPointRect();
+        const QTransform &xf = state()->matrix;
+        if (qt_pen_is_cosmetic(pen, state()->renderHints)) {
+            clipRect = d->exDeviceRect;
+            cpRect.translate(xf.dx(), xf.dy());
+        } else {
+            clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect));
+        }
+        // Check to avoid generating unwieldy amount of dashes that will not be visible anyway
+        qreal pw = pen.widthF() ? pen.widthF() : 1;
+        QRectF extentRect = cpRect.adjusted(-pw, -pw, pw, pw) & clipRect;
+        qreal extent = qMax(extentRect.width(), extentRect.height());
+        qreal patternLength = 0;
+        const QVector<qreal> pattern = pen.dashPattern();
+        const int patternSize = qMin(pattern.size(), 32);
+        for (int i = 0; i < patternSize; i++)
+            patternLength += qMax(pattern.at(i), qreal(0));
+        patternLength *= pw;
+        if (qFuzzyIsNull(patternLength)) {
+            pen.setStyle(Qt::NoPen);
+        } else if (extent / patternLength > 10000) {
+            // approximate stream of tiny dashes with semi-transparent solid line
+            pen.setStyle(Qt::SolidLine);
+            QColor color(pen.color());
+            color.setAlpha(color.alpha() / 2);
+            pen.setColor(color);
+        }
+    }
+
     if (!qpen_fast_equals(pen, d->strokerPen)) {
         d->strokerPen = pen;
         d->stroker.setJoinStyle(pen.joinStyle());
@@ -430,14 +462,8 @@ void QPaintEngineEx::stroke(const QVecto
         return;
     }
 
-    if (pen.style() > Qt::SolidLine) {
-        if (qt_pen_is_cosmetic(pen, state()->renderHints)){
-            d->activeStroker->setClipRect(d->exDeviceRect);
-        } else {
-            QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect));
-            d->activeStroker->setClipRect(clipRect);
-        }
-    }
+    if (!clipRect.isNull())
+        d->activeStroker->setClipRect(clipRect);
 
     const QPainterPath::ElementType *types = path.elements();
     const qreal *points = path.points();
