Refix for avoiding huge number of tiny dashes

Previous fix hit too widely so some valid horizontal and vertical
lines were affected; the root problem being that such lines have an
empty control point rect (width or height is 0). Fix by caculating in
the pen width.

Change-Id: I7a436e873f6d485028f6759d0e2c6456f07eebdc
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
(cherry picked from commit 84aba80944a2e1c3058d7a1372e0e66676411884)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Eirik Aavitsland 2021-07-30 13:03:49 +02:00 committed by Qt Cherry-pick Bot
parent 6f34bf0d67
commit 851ed7cd3f
2 changed files with 35 additions and 4 deletions

View File

@ -415,18 +415,18 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect));
}
// Check to avoid generating unwieldy amount of dashes that will not be visible anyway
QRectF extentRect = cpRect & clipRect;
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 QList<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));
if (pen.widthF())
patternLength *= pen.widthF();
patternLength *= pw;
if (qFuzzyIsNull(patternLength)) {
pen.setStyle(Qt::NoPen);
} else if (qFuzzyIsNull(extent) || extent / patternLength > 10000) {
} else if (extent / patternLength > 10000) {
// approximate stream of tiny dashes with semi-transparent solid line
pen.setStyle(Qt::SolidLine);
QColor color(pen.color());

View File

@ -300,6 +300,7 @@ private slots:
void fillPolygon();
void drawImageAtPointF();
void scaledDashes();
private:
void fillData();
@ -5359,6 +5360,36 @@ void tst_QPainter::drawImageAtPointF()
paint.end();
}
void tst_QPainter::scaledDashes()
{
// Test that we do not hit the limit-huge-number-of-dashes path
QRgb fore = qRgb(0, 0, 0xff);
QRgb back = qRgb(0xff, 0xff, 0);
QImage image(5, 32, QImage::Format_RGB32);
image.fill(back);
QPainter p(&image);
QPen pen(QColor(fore), 3, Qt::DotLine);
p.setPen(pen);
p.scale(1, 2);
p.drawLine(2, 0, 2, 16);
p.end();
bool foreFound = false;
bool backFound = false;
int i = 0;
while (i < 32 && (!foreFound || !backFound)) {
QRgb pix = image.pixel(3, i);
if (pix == fore)
foreFound = true;
else if (pix == back)
backFound = true;
i++;
}
QVERIFY(foreFound);
QVERIFY(backFound);
}
QTEST_MAIN(tst_QPainter)
#include "tst_qpainter.moc"