27 #include <QtConcurrentRun> 33 , mRenderSynchronously( false )
41 Q_ASSERT( !mFutureWatcher.isRunning() );
58 QgsDebugMsgLevel( QStringLiteral(
"Preparing list of layer jobs for rendering" ), 5 );
68 QPaintDevice *paintDevice = mPainter->device();
69 QString errMsg = QStringLiteral(
"pre-set DPI not equal to painter's DPI (%1 vs %2)" )
70 .arg( paintDevice->logicalDpiX() )
73 "Job::startRender()", errMsg.toLatin1().data() );
76 mLabelingEngineV2.reset();
81 mLabelingEngineV2->setMapSettings(
mSettings );
85 mLayerJobs =
prepareJobs( mPainter, mLabelingEngineV2.get() );
88 QgsDebugMsgLevel(
"Rendering prepared in (seconds): " + QString(
"%1" ).arg( prepareTime.elapsed() / 1000.0 ), 4 );
90 if ( mRenderSynchronously )
98 connect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererCustomPainterJob::futureFinished );
100 mFuture = QtConcurrent::run( staticRender,
this );
101 mFutureWatcher.setFuture( mFuture );
114 disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererCustomPainterJob::futureFinished );
120 mFutureWatcher.waitForFinished();
122 QgsDebugMsgLevel( QStringLiteral(
"QPAINER cancel waited %1 ms" ).arg( t.elapsed() / 1000.0 ), 5 );
133 QgsDebugMsg( QStringLiteral(
"QPAINTER not running!" ) );
137 mLabelJob.context.setRenderingStopped(
true );
138 for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
140 it->context.setRenderingStopped(
true );
141 if ( it->renderer && it->renderer->feedback() )
142 it->renderer->feedback()->cancel();
151 disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererCustomPainterJob::futureFinished );
156 mFutureWatcher.waitForFinished();
158 QgsDebugMsgLevel( QStringLiteral(
"waitForFinished: %1 ms" ).arg( t.elapsed() / 1000.0 ), 4 );
170 return mLabelJob.cached;
175 if ( mLabelingEngineV2 )
176 return mLabelingEngineV2->takeResults();
185 connect( &mFutureWatcher, &QFutureWatcher<void>::finished, &loop, &QEventLoop::quit );
192 mRenderSynchronously =
true;
195 mRenderSynchronously =
false;
199 void QgsMapRendererCustomPainterJob::futureFinished()
226 catch ( std::exception &e )
229 QgsDebugMsg(
"Caught unhandled std::exception: " + QString::fromLatin1( e.what() ) );
233 QgsDebugMsg( QStringLiteral(
"Caught unhandled unknown exception" ) );
237 void QgsMapRendererCustomPainterJob::doRender()
243 for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
245 LayerRenderJob &job = *it;
247 if ( job.context.renderingStopped() )
250 if ( job.context.useAdvancedEffects() )
254 mPainter->setCompositionMode( job.blendMode );
265 job.imageInitialized =
true;
268 job.renderer->render();
270 job.renderingTime += layerTime.elapsed();
276 mPainter->setOpacity( job.opacity );
277 mPainter->drawImage( 0, 0, *job.img );
278 mPainter->setOpacity( 1.0 );
287 if ( !mLabelJob.cached )
295 mLabelJob.img->fill( 0 );
296 painter.begin( mLabelJob.img );
297 mLabelJob.context.setPainter( &painter );
298 drawLabeling( mLabelJob.context, mLabelingEngineV2.get(), &painter );
303 drawLabeling( mLabelJob.context, mLabelingEngineV2.get(), mPainter );
306 mLabelJob.complete =
true;
307 mLabelJob.renderingTime = labelTime.elapsed();
308 mLabelJob.participatingLayers = _qgis_listRawToQPointer( mLabelingEngineV2->participatingLayers() );
311 if ( mLabelJob.img && mLabelJob.complete )
313 mPainter->setCompositionMode( QPainter::CompositionMode_SourceOver );
314 mPainter->setOpacity( 1.0 );
315 mPainter->drawImage( 0, 0, *mLabelJob.img );
318 QgsDebugMsgLevel(
"Rendering completed in (seconds): " + QString(
"%1" ).arg( renderTime.elapsed() / 1000.0 ), 2 );
329 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
333 if ( labelingEngine2 )
335 labelingEngine2->
run( renderContext );
338 QgsDebugMsg( QStringLiteral(
"Draw labeling took (seconds): %1" ).arg( t.elapsed() / 1000. ) );
345 drawLabeling( renderContext, labelingEngine2, painter );
348 bool QgsMapRendererJob::needTemporaryImage(
QgsMapLayer *ml )
350 switch ( ml->
type() )
361 ( ( vl->
blendMode() != QPainter::CompositionMode_SourceOver )
QgsMapRendererCustomPainterJob(const QgsMapSettings &settings, QPainter *painter)
void finished()
emitted when asynchronous rendering is finished (or canceled).
Base class for all map layer types.
Job implementation that renders everything sequentially using a custom painter.
Abstract base class for map rendering implementations.
QgsMapLayerType type() const
Returns the type of the layer.
void cleanupJobs(LayerRenderJobs &jobs)
QSize deviceOutputSize() const
Returns the device output size of the map canvas This is equivalent to the output size multiplicated ...
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
static Q_DECL_DEPRECATED void drawLabeling(const QgsMapSettings &settings, QgsRenderContext &renderContext, QgsLabelingEngine *labelingEngine2, QPainter *painter)
QColor backgroundColor() const
Gets the background color of the map.
Whether to make extra effort to update map image with partially rendered layers (better for interacti...
bool forceRasterRender() const
Returns whether the renderer must render as a raster.
void cancel() override
Stop the rendering job - does not return until the job has terminated.
Enable layer opacity and blending effects.
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.
void start() override
Start the rendering job and immediately return.
#define QgsDebugMsgLevel(str, level)
Enable anti-aliasing for map rendering.
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
QgsFeatureRenderer * renderer()
Returns renderer.
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...
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
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.
The QgsLabelingEngine class provides map labeling functionality.
void run(QgsRenderContext &context)
compute the labeling with given map settings and providers
Contains information about the context of a rendering operation.
LayerRenderJobs prepareJobs(QPainter *painter, QgsLabelingEngine *labelingEngine2)
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). ...
void waitForFinished() override
Block until the job has finished.
Represents a vector layer which manages a vector based data sets.
Defines a QGIS exception class.
void renderSynchronously()
Render the map synchronously in this thread.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
bool isActive() const override
Tell whether the rendering job is currently running in background.