Commit d6185420 authored by Agata Cacko's avatar Agata Cacko Committed by Halla Rempt
Browse files

Draw reference images in high res on 4k display

Before this commit, reference images would be stored in a buffer
which size was not determined by the actual size of the area in pixels
which was available for the QPainter, but that size scaled down by
devicePixelRatioF(). Hence on high resolution displays all
reference images would look blurry and low-res.

This commit fixes this behaviour by introducing high-res buffer
and making sure that it takes the reference image from the mipmap
which size is the closest to the actual new size instead of the
one that is scaled down because of the UI scaling
(devicePixelRatioF()).

I also changed the way the pixel art images (or any images that are being enlarged)
are drawn: now they use FastTransformation instead of SmoothTransformation.

BUG:411118
(cherry picked from commit 1d8b94e3)
parent 7829a85f
......@@ -28,7 +28,7 @@
#define QPAINTER_WORKAROUND_BORDER 1
KisQImagePyramid::KisQImagePyramid(const QImage &baseImage)
KisQImagePyramid::KisQImagePyramid(const QImage &baseImage, bool useSmoothingForEnlarging)
{
KIS_SAFE_ASSERT_RECOVER_RETURN(!baseImage.isNull());
......@@ -47,7 +47,11 @@ KisQImagePyramid::KisQImagePyramid(const QImage &baseImage)
m_baseScale = scale;
}
appendPyramidLevel(baseImage.scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
if (useSmoothingForEnlarging) {
appendPyramidLevel(baseImage.scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
} else {
appendPyramidLevel(baseImage.scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::FastTransformation));
}
}
scale *= 0.5;
......
......@@ -29,7 +29,7 @@ class BRUSH_EXPORT KisQImagePyramid
{
public:
KisQImagePyramid() = default;
KisQImagePyramid(const QImage &baseImage);
KisQImagePyramid(const QImage &baseImage, bool useSmoothingForEnlarging = true);
~KisQImagePyramid();
static QSize imageSize(const QSize &originalSize,
......
......@@ -120,7 +120,7 @@ struct KisReferenceImage::Private : public QSharedData
cachedImage = image;
}
mipmap = KisQImagePyramid(cachedImage);
mipmap = KisQImagePyramid(cachedImage, false);
}
};
......@@ -221,6 +221,7 @@ void KisReferenceImage::paint(QPainter &gc, KoShapePaintingContext &/*paintconte
gc.save();
QSizeF shapeSize = size();
// scale and rotation done by the user (excluding zoom)
QTransform transform = QTransform::fromScale(shapeSize.width() / d->image.width(), shapeSize.height() / d->image.height());
if (d->cachedImage.isNull()) {
......@@ -229,10 +230,20 @@ void KisReferenceImage::paint(QPainter &gc, KoShapePaintingContext &/*paintconte
}
qreal scale;
QImage prescaled = d->mipmap.getClosest(transform * gc.transform(), &scale);
// scale from the highDPI display
QTransform devicePixelRatioFTransform = QTransform::fromScale(gc.device()->devicePixelRatioF(), gc.device()->devicePixelRatioF());
// all three transformations: scale and rotation done by the user, scale from highDPI display, and zoom + rotation of the view
// order: zoom/rotation of the view; scale to high res; scale and rotation done by the user
QImage prescaled = d->mipmap.getClosest(transform * devicePixelRatioFTransform * gc.transform(), &scale);
transform.scale(1.0 / scale, 1.0 / scale);
gc.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
if (scale > 1.0) {
// enlarging should be done without smooth transformation
// so the user can see pixels just as they are painted
gc.setRenderHints(QPainter::Antialiasing);
} else {
gc.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
}
gc.setClipRect(QRectF(QPointF(), shapeSize), Qt::IntersectClip);
gc.setTransform(transform, true);
gc.drawImage(QPoint(), prescaled);
......
......@@ -67,6 +67,7 @@ private:
KisCoordinatesConverter *viewConverter = q->view()->viewConverter();
QTransform transform = viewConverter->imageToWidgetTransform();
qreal devicePixelRatioF = q->view()->devicePixelRatioF();
if (buffer.image.isNull() || !buffer.bounds().contains(widgetRect)) {
const QRectF boundingImageRect = layer->boundingImageRect();
const QRectF boundingWidgetRect = q->view()->viewConverter()->imageToWidget(boundingImageRect);
......@@ -75,10 +76,13 @@ private:
if (widgetRect.isNull()) return;
buffer.position = widgetRect.topLeft();
buffer.image = QImage(widgetRect.size().toSize(), QImage::Format_ARGB32);
buffer.image.fill(Qt::transparent);
// to ensure that buffor is big enough for all the pixels on high dpi displays
// BUG 411118
buffer.image = QImage((widgetRect.size()*devicePixelRatioF).toSize(), QImage::Format_ARGB32);
buffer.image.setDevicePixelRatio(devicePixelRatioF);
imageRect = q->view()->viewConverter()->widgetToImage(widgetRect);
}
QPainter gc(&buffer.image);
......@@ -91,7 +95,9 @@ private:
gc.fillRect(imageRect, Qt::transparent);
gc.restore();
gc.setClipRect(imageRect);
// to ensure that clipping rect is also big enough for all the pixels
// BUG 411118
gc.setClipRect(QRectF(imageRect.topLeft(), imageRect.size()*devicePixelRatioF));
layer->paintReferences(gc);
}
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment