Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix pixelated appearance of elevation profile chart on hidpi displays
  • Loading branch information
nyalldawson committed May 23, 2023
1 parent a382930 commit b99a349
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 8 deletions.
Expand Up @@ -137,7 +137,7 @@ Does nothing if the generation is already in progress.
Returns the limits of the retrieved elevation values.
%End

QImage renderToImage( int width, int height, double distanceMin, double distanceMax, double zMin, double zMax, const QString &sourceId = QString() );
QImage renderToImage( int width, int height, double distanceMin, double distanceMax, double zMin, double zMax, const QString &sourceId = QString(), double devicePixelRatio = 1.0 );
%Docstring
Renders a portion of the profile to an image with the given ``width`` and ``height``.

Expand Down
3 changes: 2 additions & 1 deletion src/core/elevation/qgsprofilerenderer.cpp
Expand Up @@ -293,7 +293,7 @@ QgsDoubleRange QgsProfilePlotRenderer::zRange() const
return QgsDoubleRange( min, max );
}

QImage QgsProfilePlotRenderer::renderToImage( int width, int height, double distanceMin, double distanceMax, double zMin, double zMax, const QString &sourceId )
QImage QgsProfilePlotRenderer::renderToImage( int width, int height, double distanceMin, double distanceMax, double zMin, double zMax, const QString &sourceId, double devicePixelRatio )
{
QImage res( width, height, QImage::Format_ARGB32_Premultiplied );
res.setDotsPerMeterX( 96 / 25.4 * 1000 );
Expand All @@ -305,6 +305,7 @@ QImage QgsProfilePlotRenderer::renderToImage( int width, int height, double dist
QgsRenderContext context = QgsRenderContext::fromQPainter( &p );
context.setFlag( Qgis::RenderContextFlag::Antialiasing, true );
context.setPainterFlagsUsingContext( &p );
context.setDevicePixelRatio( devicePixelRatio );
const double mapUnitsPerPixel = ( distanceMax - distanceMin ) / width;
context.setMapToPixel( QgsMapToPixel( mapUnitsPerPixel ) );

Expand Down
2 changes: 1 addition & 1 deletion src/core/elevation/qgsprofilerenderer.h
Expand Up @@ -163,7 +163,7 @@ class CORE_EXPORT QgsProfilePlotRenderer : public QObject
*
* If \a sourceId is empty then all sources will be rendered, otherwise only the matching source will be rendered.
*/
QImage renderToImage( int width, int height, double distanceMin, double distanceMax, double zMin, double zMax, const QString &sourceId = QString() );
QImage renderToImage( int width, int height, double distanceMin, double distanceMax, double zMin, double zMax, const QString &sourceId = QString(), double devicePixelRatio = 1.0 );

/**
* Renders a portion of the profile using the specified render \a context.
Expand Down
18 changes: 13 additions & 5 deletions src/gui/elevation/qgselevationprofilecanvas.cpp
Expand Up @@ -138,6 +138,8 @@ class QgsElevationProfilePlotItem : public Qgs2DPlot, public QgsPlotCanvasItem
if ( !mRenderer )
return;

const double pixelRatio = !scene()->views().empty() ? scene()->views().at( 0 )->devicePixelRatioF() : 1;

const QStringList sourceIds = mRenderer->sourceIds();
for ( const QString &source : sourceIds )
{
Expand All @@ -149,10 +151,13 @@ class QgsElevationProfilePlotItem : public Qgs2DPlot, public QgsPlotCanvasItem
}
else
{
plot = mRenderer->renderToImage( plotArea.width(), plotArea.height(), xMinimum(), xMaximum(), yMinimum(), yMaximum(), source );
plot = mRenderer->renderToImage( plotArea.width() * pixelRatio,
plotArea.height() * pixelRatio, xMinimum(), xMaximum(), yMinimum(), yMaximum(), source, pixelRatio );
plot.setDevicePixelRatio( pixelRatio );
mCachedImages.insert( source, plot );
}
rc.painter()->drawImage( plotArea.left(), plotArea.top(), plot );
rc.painter()->drawImage( QPointF( plotArea.left(),
plotArea.top() ), plot );
}
}

Expand All @@ -161,16 +166,19 @@ class QgsElevationProfilePlotItem : public Qgs2DPlot, public QgsPlotCanvasItem
// cache rendering to an image, so we don't need to redraw the plot
if ( !mImage.isNull() )
{
painter->drawImage( 0, 0, mImage );
painter->drawImage( QPointF( 0, 0 ), mImage );
}
else
{
mImage = QImage( mRect.width(), mRect.height(), QImage::Format_ARGB32_Premultiplied );
const double pixelRatio = !scene()->views().empty() ? scene()->views().at( 0 )->devicePixelRatioF() : 1;
mImage = QImage( mRect.width() * pixelRatio, mRect.height() * pixelRatio, QImage::Format_ARGB32_Premultiplied );
mImage.setDevicePixelRatio( pixelRatio );
mImage.fill( Qt::transparent );

QPainter imagePainter( &mImage );
imagePainter.setRenderHint( QPainter::Antialiasing, true );
QgsRenderContext rc = QgsRenderContext::fromQPainter( &imagePainter );
rc.setDevicePixelRatio( pixelRatio );

const double mapUnitsPerPixel = ( xMaximum() - xMinimum() ) / plotArea().width();
rc.setMapToPixel( QgsMapToPixel( mapUnitsPerPixel ) );
Expand All @@ -182,7 +190,7 @@ class QgsElevationProfilePlotItem : public Qgs2DPlot, public QgsPlotCanvasItem
render( rc );
imagePainter.end();

painter->drawImage( 0, 0, mImage );
painter->drawImage( QPointF( 0, 0 ), mImage );
}
}

Expand Down

0 comments on commit b99a349

Please sign in to comment.