Fixed dashes being rendered differently depending on system clip.
We need to clip lines to the unclipped device rect in the case of dashing, since otherwise the dashes will be shifted and rendered differently when partial repaints are done. Task-number: QTBUG-24762 Change-Id: I3599b54baa552acc20bf8cc2e12f846b45f6019e Reviewed-by: Lars Knoll <lars.knoll@digia.com> Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
This commit is contained in:
parent
7128bcbbd5
commit
a12f6ba302
@ -290,11 +290,14 @@ void QCosmeticStroker::setup()
|
||||
ppl = buffer->bytesPerLine()>>2;
|
||||
}
|
||||
|
||||
// dashes are sensitive to clips, so we need to clip consistently when painting to the same device
|
||||
QRect clipRect = strokeSelection & Dashed ? deviceRect : clip;
|
||||
|
||||
// setup FP clip bounds
|
||||
xmin = clip.left() - 1;
|
||||
xmax = clip.right() + 2;
|
||||
ymin = clip.top() - 1;
|
||||
ymax = clip.bottom() + 2;
|
||||
xmin = clipRect.left() - 1;
|
||||
xmax = clipRect.right() + 2;
|
||||
ymin = clipRect.top() - 1;
|
||||
ymax = clipRect.bottom() + 2;
|
||||
|
||||
lastPixel.x = -1;
|
||||
}
|
||||
|
@ -85,8 +85,9 @@ public:
|
||||
HorizontalMask = 0xc
|
||||
};
|
||||
|
||||
QCosmeticStroker(QRasterPaintEngineState *s, const QRect &dr)
|
||||
QCosmeticStroker(QRasterPaintEngineState *s, const QRect &dr, const QRect &dr_unclipped)
|
||||
: state(s),
|
||||
deviceRect(dr_unclipped),
|
||||
clip(dr),
|
||||
pattern(0),
|
||||
reversePattern(0),
|
||||
@ -110,6 +111,7 @@ public:
|
||||
|
||||
|
||||
QRasterPaintEngineState *state;
|
||||
QRect deviceRect;
|
||||
QRect clip;
|
||||
// clip bounds in real
|
||||
qreal xmin, xmax;
|
||||
|
@ -1054,20 +1054,20 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
|
||||
|
||||
void QRasterPaintEnginePrivate::systemStateChanged()
|
||||
{
|
||||
QRect clipRect(0, 0,
|
||||
deviceRectUnclipped = QRect(0, 0,
|
||||
qMin(QT_RASTER_COORD_LIMIT, device->width()),
|
||||
qMin(QT_RASTER_COORD_LIMIT, device->height()));
|
||||
|
||||
if (!systemClip.isEmpty()) {
|
||||
QRegion clippedDeviceRgn = systemClip & clipRect;
|
||||
QRegion clippedDeviceRgn = systemClip & deviceRectUnclipped;
|
||||
deviceRect = clippedDeviceRgn.boundingRect();
|
||||
baseClip->setClipRegion(clippedDeviceRgn);
|
||||
} else {
|
||||
deviceRect = clipRect;
|
||||
deviceRect = deviceRectUnclipped;
|
||||
baseClip->setClipRect(deviceRect);
|
||||
}
|
||||
#ifdef QT_DEBUG_DRAW
|
||||
qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRect << systemClip;
|
||||
qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << deviceRectUnclipped << systemClip;
|
||||
#endif
|
||||
|
||||
exDeviceRect = deviceRect;
|
||||
@ -1529,7 +1529,7 @@ void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount)
|
||||
if (s->penData.blend) {
|
||||
QRectVectorPath path;
|
||||
if (s->flags.fast_pen) {
|
||||
QCosmeticStroker stroker(s, d->deviceRect);
|
||||
QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
|
||||
stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
|
||||
for (int i = 0; i < rectCount; ++i) {
|
||||
path.set(rects[i]);
|
||||
@ -1576,7 +1576,7 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount)
|
||||
if (s->penData.blend) {
|
||||
QRectVectorPath path;
|
||||
if (s->flags.fast_pen) {
|
||||
QCosmeticStroker stroker(s, d->deviceRect);
|
||||
QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
|
||||
stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
|
||||
for (int i = 0; i < rectCount; ++i) {
|
||||
path.set(rects[i]);
|
||||
@ -1610,7 +1610,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
|
||||
return;
|
||||
|
||||
if (s->flags.fast_pen) {
|
||||
QCosmeticStroker stroker(s, d->deviceRect);
|
||||
QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
|
||||
stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
|
||||
stroker.drawPath(path);
|
||||
} else if (s->flags.non_complex_pen && path.shape() == QVectorPath::LinesHint) {
|
||||
@ -1953,7 +1953,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly
|
||||
if (s->penData.blend) {
|
||||
QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode));
|
||||
if (s->flags.fast_pen) {
|
||||
QCosmeticStroker stroker(s, d->deviceRect);
|
||||
QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
|
||||
stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
|
||||
stroker.drawPath(vp);
|
||||
} else {
|
||||
@ -2018,7 +2018,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
|
||||
QVectorPath vp((qreal *) fpoints.data(), pointCount, 0, QVectorPath::polygonFlags(mode));
|
||||
|
||||
if (s->flags.fast_pen) {
|
||||
QCosmeticStroker stroker(s, d->deviceRect);
|
||||
QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
|
||||
stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
|
||||
stroker.drawPath(vp);
|
||||
} else {
|
||||
@ -3112,7 +3112,7 @@ void QRasterPaintEngine::drawPoints(const QPointF *points, int pointCount)
|
||||
return;
|
||||
}
|
||||
|
||||
QCosmeticStroker stroker(s, d->deviceRect);
|
||||
QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
|
||||
stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
|
||||
stroker.drawPoints(points, pointCount);
|
||||
}
|
||||
@ -3132,7 +3132,7 @@ void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount)
|
||||
return;
|
||||
}
|
||||
|
||||
QCosmeticStroker stroker(s, d->deviceRect);
|
||||
QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
|
||||
stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
|
||||
stroker.drawPoints(points, pointCount);
|
||||
}
|
||||
@ -3153,7 +3153,7 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount)
|
||||
return;
|
||||
|
||||
if (s->flags.fast_pen) {
|
||||
QCosmeticStroker stroker(s, d->deviceRect);
|
||||
QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
|
||||
stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
|
||||
for (int i=0; i<lineCount; ++i) {
|
||||
const QLine &l = lines[i];
|
||||
@ -3225,7 +3225,7 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount)
|
||||
if (!s->penData.blend)
|
||||
return;
|
||||
if (s->flags.fast_pen) {
|
||||
QCosmeticStroker stroker(s, d->deviceRect);
|
||||
QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
|
||||
stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
|
||||
for (int i=0; i<lineCount; ++i) {
|
||||
QLineF line = lines[i];
|
||||
|
@ -323,6 +323,7 @@ public:
|
||||
#endif
|
||||
|
||||
QRect deviceRect;
|
||||
QRect deviceRectUnclipped;
|
||||
|
||||
QStroker basicStroker;
|
||||
QScopedPointer<QDashStroker> dashStroker;
|
||||
|
@ -280,6 +280,7 @@ private slots:
|
||||
void drawTextWithComplexBrush();
|
||||
void QTBUG26013_squareCapStroke();
|
||||
void QTBUG25153_drawLine();
|
||||
void dashing_systemClip();
|
||||
|
||||
private:
|
||||
void fillData();
|
||||
@ -4461,6 +4462,43 @@ void tst_QPainter::QTBUG25153_drawLine()
|
||||
}
|
||||
}
|
||||
|
||||
static void dashing_systemClip_paint(QPainter *p)
|
||||
{
|
||||
p->setPen(QPen(Qt::black, 1, Qt::DashLine, Qt::RoundCap, Qt::MiterJoin));
|
||||
p->drawLine(8, 8, 42, 8);
|
||||
p->drawLine(42, 8, 42, 42);
|
||||
p->drawLine(42, 42, 8, 42);
|
||||
p->drawLine(8, 42, 8, 8);
|
||||
}
|
||||
|
||||
void tst_QPainter::dashing_systemClip()
|
||||
{
|
||||
QImage image(50, 50, QImage::Format_RGB32);
|
||||
image.fill(Qt::white);
|
||||
|
||||
QPainter p(&image);
|
||||
dashing_systemClip_paint(&p);
|
||||
p.end();
|
||||
|
||||
QImage old = image.copy();
|
||||
|
||||
image.paintEngine()->setSystemClip(QRect(10, 0, image.width() - 10, image.height()));
|
||||
|
||||
p.begin(&image);
|
||||
dashing_systemClip_paint(&p);
|
||||
|
||||
// doing same paint operation again with different system clip should not change the image
|
||||
QCOMPARE(old, image);
|
||||
|
||||
old = image;
|
||||
|
||||
p.setClipRect(QRect(20, 20, 30, 30));
|
||||
dashing_systemClip_paint(&p);
|
||||
|
||||
// ditto for regular clips
|
||||
QCOMPARE(old, image);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QPainter)
|
||||
|
||||
#include "tst_qpainter.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user