From c4818a0de7fab258a4ebfd72094b7d17ee27305b Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 27 Jan 2021 13:20:12 +1000 Subject: [PATCH] Unlock composition using transformed previewed cache image of labeling results as well as map layers This extends the recent addition of smooth map updates for raster layers to also apply to map labels. Now you'll see a scaled/transformed version of the previous map render's labels while the new labeling results are being generated in the background. Avoids "flashy" redraws of map labels --- python/core/auto_generated/qgsmaprendererjob.sip.in | 1 + src/core/qgsmaprendererjob.cpp | 9 +++++++++ src/core/qgsmaprendererjob.h | 7 +++++++ src/core/qgsmaprendererparalleljob.cpp | 2 +- 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/python/core/auto_generated/qgsmaprendererjob.sip.in b/python/core/auto_generated/qgsmaprendererjob.sip.in index ddf3dd605ee..289c8ba24cf 100644 --- a/python/core/auto_generated/qgsmaprendererjob.sip.in +++ b/python/core/auto_generated/qgsmaprendererjob.sip.in @@ -156,6 +156,7 @@ Returns map settings with which this job was started. %End + signals: void renderingLayersFinished(); diff --git a/src/core/qgsmaprendererjob.cpp b/src/core/qgsmaprendererjob.cpp index e01852be7b0..91b1cf708be 100644 --- a/src/core/qgsmaprendererjob.cpp +++ b/src/core/qgsmaprendererjob.cpp @@ -47,6 +47,7 @@ ///@cond PRIVATE const QString QgsMapRendererJob::LABEL_CACHE_ID = QStringLiteral( "_labels_" ); +const QString QgsMapRendererJob::LABEL_PREVIEW_CACHE_ID = QStringLiteral( "_preview_labels_" ); bool LayerRenderJob::imageCanBeComposed() const { @@ -750,6 +751,7 @@ void QgsMapRendererJob::cleanupLabelJob( LabelRenderJob &job ) { QgsDebugMsgLevel( QStringLiteral( "caching label result image" ), 2 ); mCache->setCacheImage( LABEL_CACHE_ID, *job.img, _qgis_listQPointerToRaw( job.participatingLayers ) ); + mCache->setCacheImage( LABEL_PREVIEW_CACHE_ID, *job.img, _qgis_listQPointerToRaw( job.participatingLayers ) ); } delete job.img; @@ -816,6 +818,13 @@ QImage QgsMapRendererJob::composeImage( painter.setOpacity( 1.0 ); painter.drawImage( 0, 0, *labelJob.img ); } + else if ( cache && cache->hasAnyCacheImage( LABEL_PREVIEW_CACHE_ID ) ) + { + const QImage labelCacheImage = cache->transformedCacheImage( LABEL_PREVIEW_CACHE_ID, settings.mapToPixel() ); + painter.setCompositionMode( QPainter::CompositionMode_SourceOver ); + painter.setOpacity( 1.0 ); + painter.drawImage( 0, 0, labelCacheImage ); + } // render any layers with the renderAboveLabels flag now for ( LayerRenderJobs::const_iterator it = jobs.constBegin(); it != jobs.constEnd(); ++it ) diff --git a/src/core/qgsmaprendererjob.h b/src/core/qgsmaprendererjob.h index 693307f741f..85ebd1c726b 100644 --- a/src/core/qgsmaprendererjob.h +++ b/src/core/qgsmaprendererjob.h @@ -325,6 +325,13 @@ class CORE_EXPORT QgsMapRendererJob : public QObject */ static const QString LABEL_CACHE_ID SIP_SKIP; + /** + * QgsMapRendererCache ID string for cached label image during preview compositions only. + * \note not available in Python bindings + * \since QGIS 3.18 + */ + static const QString LABEL_PREVIEW_CACHE_ID SIP_SKIP; + signals: /** diff --git a/src/core/qgsmaprendererparalleljob.cpp b/src/core/qgsmaprendererparalleljob.cpp index 33141a01e6b..33842870e0b 100644 --- a/src/core/qgsmaprendererparalleljob.cpp +++ b/src/core/qgsmaprendererparalleljob.cpp @@ -231,7 +231,7 @@ void QgsMapRendererParallelJob::renderLayersFinished() // compose final image for labeling if ( mSecondPassLayerJobs.isEmpty() ) { - mFinalImage = composeImage( mSettings, mLayerJobs, mLabelJob ); + mFinalImage = composeImage( mSettings, mLayerJobs, mLabelJob, mCache ); } QgsDebugMsgLevel( QStringLiteral( "PARALLEL layers finished" ), 2 );