24 #include <QtConcurrentRun> 44 QPaintDevice *paintDevice = painter->device();
45 QString errMsg = QStringLiteral(
"pre-set DPI not equal to painter's DPI (%1 vs %2)" )
46 .arg( paintDevice->logicalDpiX() )
49 "Job::startRender()", errMsg.toLatin1().data() );
62 , mRenderSynchronously( false )
70 Q_ASSERT( !mFutureWatcher.isRunning() );
88 QgsDebugMsgLevel( QStringLiteral(
"Preparing list of layer jobs for rendering" ), 5 );
94 mLabelingEngineV2.reset();
99 mLabelingEngineV2->setMapSettings(
mSettings );
103 mLayerJobs =
prepareJobs( mPainter, mLabelingEngineV2.get() );
104 mLabelJob =
prepareLabelingJob( mPainter, mLabelingEngineV2.get(), canUseLabelCache );
106 QgsDebugMsgLevel( QStringLiteral(
"Rendering prepared in (seconds): %1" ).arg( prepareTime.elapsed() / 1000.0 ), 4 );
108 if ( mRenderSynchronously )
119 connect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererCustomPainterJob::futureFinished );
121 mFuture = QtConcurrent::run( staticRender,
this );
122 mFutureWatcher.setFuture( mFuture );
135 disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererCustomPainterJob::futureFinished );
141 mFutureWatcher.waitForFinished();
143 QgsDebugMsgLevel( QStringLiteral(
"QPAINER cancel waited %1 ms" ).arg( t.elapsed() / 1000.0 ), 5 );
154 QgsDebugMsg( QStringLiteral(
"QPAINTER not running!" ) );
158 mLabelJob.context.setRenderingStopped(
true );
159 for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
161 it->context.setRenderingStopped(
true );
162 if ( it->renderer && it->renderer->feedback() )
163 it->renderer->feedback()->cancel();
172 disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererCustomPainterJob::futureFinished );
177 mFutureWatcher.waitForFinished();
179 QgsDebugMsgLevel( QStringLiteral(
"waitForFinished: %1 ms" ).arg( t.elapsed() / 1000.0 ), 4 );
191 return mLabelJob.cached;
196 if ( mLabelingEngineV2 )
197 return mLabelingEngineV2->takeResults();
206 connect( &mFutureWatcher, &QFutureWatcher<void>::finished, &loop, &QEventLoop::quit );
213 mRenderSynchronously =
true;
216 mRenderSynchronously =
false;
221 mRenderSynchronously =
true;
234 mRenderSynchronously =
false;
235 mPrepareOnly =
false;
239 void QgsMapRendererCustomPainterJob::futureFinished()
268 catch ( std::exception &e )
271 QgsDebugMsg(
"Caught unhandled std::exception: " + QString::fromLatin1( e.what() ) );
275 QgsDebugMsg( QStringLiteral(
"Caught unhandled unknown exception" ) );
279 void QgsMapRendererCustomPainterJob::doRender()
285 for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
287 LayerRenderJob &job = *it;
289 if ( job.context.renderingStopped() )
292 if ( job.context.useAdvancedEffects() )
296 mPainter->setCompositionMode( job.blendMode );
307 job.imageInitialized =
true;
310 job.renderer->render();
312 job.renderingTime += layerTime.elapsed();
318 mPainter->setOpacity( job.opacity );
319 mPainter->drawImage( 0, 0, *job.img );
320 mPainter->setOpacity( 1.0 );
329 if ( !mLabelJob.cached )
337 mLabelJob.img->fill( 0 );
338 painter.begin( mLabelJob.img );
339 mLabelJob.context.setPainter( &painter );
340 drawLabeling( mLabelJob.context, mLabelingEngineV2.get(), &painter );
345 drawLabeling( mLabelJob.context, mLabelingEngineV2.get(), mPainter );
348 mLabelJob.complete =
true;
349 mLabelJob.renderingTime = labelTime.elapsed();
350 mLabelJob.participatingLayers = _qgis_listRawToQPointer( mLabelingEngineV2->participatingLayers() );
353 if ( mLabelJob.img && mLabelJob.complete )
355 mPainter->setCompositionMode( QPainter::CompositionMode_SourceOver );
356 mPainter->setOpacity( 1.0 );
357 mPainter->drawImage( 0, 0, *mLabelJob.img );
360 QgsDebugMsgLevel( QStringLiteral(
"Rendering completed in (seconds): %1" ).arg( renderTime.elapsed() / 1000.0 ), 2 );
QgsMapRendererCustomPainterJob(const QgsMapSettings &settings, QPainter *painter)
void finished()
emitted when asynchronous rendering is finished (or canceled).
Job implementation that renders everything sequentially using a custom painter.
Abstract base class for map rendering implementations.
void cleanupJobs(LayerRenderJobs &jobs)
QSize deviceOutputSize() const
Returns the device output size of the map canvas This is equivalent to the output size multiplicated ...
static Q_DECL_DEPRECATED void drawLabeling(const QgsMapSettings &settings, QgsRenderContext &renderContext, QgsLabelingEngine *labelingEngine2, QPainter *painter)
void preparePainter(QPainter *painter, const QColor &backgroundColor=Qt::transparent)
Prepares the given painter ready for a map render.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QColor backgroundColor() const
Gets the background color of the map.
Default QgsLabelingEngine implementation, which completes the whole labeling operation (including lab...
void cancel() override
Stop the rendering job - does not return until the job has terminated.
void prepare()
Prepares the job for rendering synchronously in a background thread.
void waitForFinishedWithEventLoop(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
Wait for the job to be finished - and keep the thread's event loop running while waiting.
Enable drawing of labels on top of the map.
The QgsMapSettings class contains configuration for rendering of the map.
LabelRenderJob prepareLabelingJob(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool canUseLabelCache=true)
Prepares a labeling job.
bool prepareLabelCache() const
Prepares the cache for storing the result of labeling.
LayerRenderJobs prepareJobs(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool deferredPainterSet=false)
Creates a list of layer rendering jobs and prepares them for later render.
void start() override
Start the rendering job and immediately return.
void renderPrepared()
Render a pre-prepared job.
#define QgsDebugMsgLevel(str, level)
Abstract base class for map renderer jobs which use custom painters.
Enable anti-aliasing for map rendering.
bool usedCachedLabels() const override
Returns true if the render job was able to use a cached labeling solution.
float devicePixelRatio() const
Returns device pixel ratio Common values are 1 for normal-dpi displays and 2 for high-dpi "retina" di...
void cleanupLabelJob(LabelRenderJob &job)
Handles clean up tasks for a label job, including deletion of images and storing cached label results...
void cancelWithoutBlocking() override
Triggers cancellation of the rendering job without blocking.
double outputDpi() const
Returns DPI used for conversion between real world units (e.g.
void logRenderingTime(const LayerRenderJobs &jobs, const LabelRenderJob &labelJob)
~QgsMapRendererCustomPainterJob() override
Class that stores computed placement from labeling engine.
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
QgsLabelingResults * takeLabelingResults() override
Gets pointer to internal labeling engine (in order to get access to the results). ...
QgsMapRendererAbstractCustomPainterJob(const QgsMapSettings &settings)
Constructor for QgsMapRendererAbstractCustomPainterJob, using the given map settings.
void waitForFinished() override
Block until the job has finished.
Defines a QGIS exception class.
void renderSynchronously()
Render the map synchronously in this thread.
bool isActive() const override
Tell whether the rendering job is currently running in background.