Skip to content

Commit

Permalink
Merge pull request #52015 from signedav/legend_fix
Browse files Browse the repository at this point in the history
Fix inconcequent use of DPI at generating the WMS legend
  • Loading branch information
signedav committed Mar 6, 2023
2 parents 4d78e34 + a850194 commit 632edab
Show file tree
Hide file tree
Showing 103 changed files with 2,235 additions and 54 deletions.
53 changes: 44 additions & 9 deletions src/server/services/wms/qgswmsrenderer.cpp
Expand Up @@ -127,27 +127,44 @@ namespace QgsWms
QgsLegendSettings settings = legendSettings();
QgsLegendRenderer renderer( &model, settings );

// create image
// create context
QgsRenderContext context;
if ( !mWmsParameters.bbox().isEmpty() )
{
QgsMapSettings mapSettings;
mapSettings.setFlag( Qgis::MapSettingsFlag::RenderBlocking );
std::unique_ptr<QImage> tmp( createImage( mContext.mapSize( false ) ) );
configureMapSettings( tmp.get(), mapSettings );
context = QgsRenderContext::fromMapSettings( mapSettings );
}
else
{
//use default scale settings
context = configureDefaultRenderContext();
}

// create image according to context
std::unique_ptr<QImage> image;
const qreal dpmm = mContext.dotsPerMm();
const QSizeF minSize = renderer.minimumSize();
const QSizeF minSize = renderer.minimumSize( &context );
const QSize size( static_cast<int>( minSize.width() * dpmm ), static_cast<int>( minSize.height() * dpmm ) );
if ( !mContext.isValidWidthHeight( size.width(), size.height() ) )
{
throw QgsServerException( QStringLiteral( "Legend image is too large" ) );
}
image.reset( createImage( size ) );

// configure painter
// configure painter and addapt to the context
QPainter painter( image.get() );
QgsRenderContext context = QgsRenderContext::fromQPainter( &painter );

context.setPainter( &painter );
if ( painter.renderHints() & QPainter::SmoothPixmapTransform )
context.setFlag( Qgis::RenderContextFlag::HighQualityImageTransforms, true );
if ( painter.renderHints() & QPainter::LosslessImageRendering )
context.setFlag( Qgis::RenderContextFlag::LosslessImageRendering, true );

context.setFlag( Qgis::RenderContextFlag::Antialiasing, true );
QgsScopedRenderContextScaleToMm scaleContext( context );
// QGIS 4.0 -- take from real render context instead
Q_NOWARN_DEPRECATED_PUSH
context.setRendererScale( settings.mapScale() );
context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) );
Q_NOWARN_DEPRECATED_POP

// rendering
renderer.drawLegend( context );
Expand Down Expand Up @@ -186,6 +203,11 @@ namespace QgsWms
QgsLegendSettings settings = legendSettings();
QgsLayerTreeModelLegendNode::ItemContext ctx;
ctx.painter = painter.get();

// create context
QgsRenderContext context = configureDefaultRenderContext( painter.get() );
ctx.context = &context;

nodeModel.drawSymbol( settings, &ctx, size.height() / dpmm );
painter->end();

Expand Down Expand Up @@ -1353,6 +1375,19 @@ namespace QgsWms
}
}

QgsRenderContext QgsRenderer::configureDefaultRenderContext( QPainter *painter )
{
QgsRenderContext context = QgsRenderContext::fromQPainter( painter );
context.setScaleFactor( mContext.dotsPerMm() );
const double mmPerMapUnit = 1 / QgsServerProjectUtils::wmsDefaultMapUnitsPerMm( *mProject );
context.setMapToPixel( QgsMapToPixel( 1 / ( mmPerMapUnit * context.scaleFactor() ) ) );
QgsDistanceArea distanceArea = QgsDistanceArea();
distanceArea.setSourceCrs( QgsCoordinateReferenceSystem( mWmsParameters.crs() ), mProject->transformContext() );
distanceArea.setEllipsoid( geoNone() );
context.setDistanceArea( distanceArea );
return context;
}

QDomDocument QgsRenderer::featureInfoDocument( QList<QgsMapLayer *> &layers, const QgsMapSettings &mapSettings,
const QImage *outputImage, const QString &version ) const
{
Expand Down
8 changes: 8 additions & 0 deletions src/server/services/wms/qgswmsrenderer.h
Expand Up @@ -195,6 +195,14 @@ namespace QgsWms
*/
void configureMapSettings( const QPaintDevice *paintDevice, QgsMapSettings &mapSettings, bool mandatoryCrsParam = true );

/**
* Configures QgsRenderContext according to the WMS parameters and default settings as well as the passed painter.
* Used, for example, when no mapSettings are available.
* \param painter to create the context from
* \returns the renderer context with default parameters and settings of the passed painter
*/
QgsRenderContext configureDefaultRenderContext( QPainter *painter = nullptr );

QDomDocument featureInfoDocument( QList<QgsMapLayer *> &layers, const QgsMapSettings &mapSettings,
const QImage *outputImage, const QString &version ) const;

Expand Down

0 comments on commit 632edab

Please sign in to comment.