Skip to content

Commit 63a3037

Browse files
committed
[composer] Use last complete map render when previewing map items
until a new cached preview is ready Ensures that map items always show some content while a background cache update is rendering
1 parent ba46c87 commit 63a3037

File tree

2 files changed

+24
-16
lines changed

2 files changed

+24
-16
lines changed

src/core/composer/qgscomposermap.cpp

+15-14
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ QgsComposerMap::~QgsComposerMap()
124124
}
125125
}
126126

127-
/* This function is called by paint() and cache() to render the map. It does not override any functions
127+
/* This function is called by paint() to render the map. It does not override any functions
128128
from QGraphicsItem. */
129129
void QgsComposerMap::draw( QPainter *painter, const QgsRectangle &extent, QSizeF size, double dpi, double *forceWidthScale )
130130
{
@@ -218,7 +218,7 @@ void QgsComposerMap::cache()
218218
disconnect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsComposerMap::painterJobFinished );
219219
QgsMapRendererCustomPainterJob *oldJob = mPainterJob.release();
220220
QPainter *oldPainter = mPainter.release();
221-
QImage *oldImage = mCacheImage.release();
221+
QImage *oldImage = mCacheRenderingImage.release();
222222
connect( oldJob, &QgsMapRendererCustomPainterJob::finished, this, [oldPainter, oldJob, oldImage]
223223
{
224224
oldJob->deleteLater();
@@ -229,12 +229,12 @@ void QgsComposerMap::cache()
229229
}
230230
else
231231
{
232-
mCacheImage.reset( nullptr );
232+
mCacheRenderingImage.reset( nullptr );
233233
}
234234

235235
Q_ASSERT( !mPainterJob );
236236
Q_ASSERT( !mPainter );
237-
Q_ASSERT( !mCacheImage );
237+
Q_ASSERT( !mCacheRenderingImage );
238238

239239
double horizontalVScaleFactor = horizontalViewScaleFactor();
240240
if ( horizontalVScaleFactor < 0 )
@@ -265,26 +265,26 @@ void QgsComposerMap::cache()
265265
}
266266
}
267267

268-
mCacheImage.reset( new QImage( w, h, QImage::Format_ARGB32 ) );
268+
mCacheRenderingImage.reset( new QImage( w, h, QImage::Format_ARGB32 ) );
269269

270270
// set DPI of the image
271-
mCacheImage->setDotsPerMeterX( 1000 * w / widthMM );
272-
mCacheImage->setDotsPerMeterY( 1000 * h / heightMM );
271+
mCacheRenderingImage->setDotsPerMeterX( 1000 * w / widthMM );
272+
mCacheRenderingImage->setDotsPerMeterY( 1000 * h / heightMM );
273273

274274
if ( hasBackground() )
275275
{
276276
//Initially fill image with specified background color. This ensures that layers with blend modes will
277277
//preview correctly
278-
mCacheImage->fill( backgroundColor().rgba() );
278+
mCacheRenderingImage->fill( backgroundColor().rgba() );
279279
}
280280
else
281281
{
282282
//no background, but start with empty fill to avoid artifacts
283-
mCacheImage->fill( QColor( 255, 255, 255, 0 ).rgba() );
283+
mCacheRenderingImage->fill( QColor( 255, 255, 255, 0 ).rgba() );
284284
}
285285

286-
mPainter.reset( new QPainter( mCacheImage.get() ) );
287-
QgsMapSettings settings( mapSettings( ext, QSizeF( w, h ), mCacheImage->logicalDpiX() ) );
286+
mPainter.reset( new QPainter( mCacheRenderingImage.get() ) );
287+
QgsMapSettings settings( mapSettings( ext, QSizeF( w, h ), mCacheRenderingImage->logicalDpiX() ) );
288288
mPainterJob.reset( new QgsMapRendererCustomPainterJob( settings, mPainter.get() ) );
289289
connect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsComposerMap::painterJobFinished );
290290
mPainterJob->start();
@@ -296,6 +296,7 @@ void QgsComposerMap::painterJobFinished()
296296
mPainterJob.reset( nullptr );
297297
mPainter.reset( nullptr );
298298
mCacheUpdated = true;
299+
mCacheFinalImage = std::move( mCacheRenderingImage );
299300
updateItem();
300301
}
301302

@@ -327,22 +328,22 @@ void QgsComposerMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *,
327328
}
328329
else if ( mComposition->plotStyle() == QgsComposition::Preview )
329330
{
330-
if ( !mCacheImage || mCacheImage->isNull() )
331+
if ( !mCacheFinalImage || mCacheFinalImage->isNull() )
331332
{
332333
cache();
333334
return;
334335
}
335336

336337
//Background color is already included in cached image, so no need to draw
337338

338-
double imagePixelWidth = mCacheImage->width(); //how many pixels of the image are for the map extent?
339+
double imagePixelWidth = mCacheFinalImage->width(); //how many pixels of the image are for the map extent?
339340
double scale = rect().width() / imagePixelWidth;
340341

341342
painter->save();
342343

343344
painter->translate( mXOffset, mYOffset );
344345
painter->scale( scale, scale );
345-
painter->drawImage( 0, 0, *mCacheImage );
346+
painter->drawImage( 0, 0, *mCacheFinalImage );
346347

347348
//restore rotation
348349
painter->restore();

src/core/composer/qgscomposermap.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -516,8 +516,15 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
516516
// to manually tweak each atlas preview page without affecting the actual original map extent.
517517
QgsRectangle mAtlasFeatureExtent;
518518

519-
// Cache used in composer preview
520-
std::unique_ptr< QImage > mCacheImage;
519+
// We have two images used for rendering/storing cached map images.
520+
// the first (mCacheFinalImage) is used ONLY for storing the most recent completed map render. It's always
521+
// used when drawing map item previews. The second (mCacheRenderingImage) is used temporarily while
522+
// rendering a new preview image in the background. If (and only if) the background render completes, then
523+
// mCacheRenderingImage is pushed into mCacheFinalImage, and used from then on when drawing the item preview.
524+
// This ensures that something is always shown in the map item, even while refreshing the preview image in the
525+
// background
526+
std::unique_ptr< QImage > mCacheFinalImage;
527+
std::unique_ptr< QImage > mCacheRenderingImage;
521528

522529
// Is cache up to date
523530
bool mCacheUpdated = false;

0 commit comments

Comments
 (0)