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=f4d791b330d02777
 https://code.qt.io/cgit/qt/qtbase.git/commit/?id=6b400e3147dcfd8c
 https://code.qt.io/cgit/qt/qtbase.git/commit/?id=84aba80944a2e1c3
 https://code.qt.io/cgit/qt/qtbase.git/commit/?id=cca8ed0547405b1c
Last-Update: 2021-11-27

Gbp-Pq: Name CVE-2021-38593.diff
This commit is contained in:
Debian Qt/KDE Maintainers 2022-05-14 17:41:00 +08:00 committed by openKylinBot
parent a982f33688
commit 0db85e1da1
1 changed files with 36 additions and 10 deletions

View File

@ -385,10 +385,10 @@ QPainterState *QPaintEngineEx::createState(QPainterState *orig) const
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 QVectorPath &path, const QPen &pen)
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 QVectorPath &path, const QPen &pen)
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);
if (d->activeStroker == &d->stroker)
d->stroker.setForceOpen(path.hasExplicitOpen());