27 #include <QtConcurrentRun> 33 , mRenderSynchronously( false )
41 Q_ASSERT( !mFutureWatcher.isRunning() );
68 QPaintDevice *paintDevice = mPainter->device();
69 QString errMsg = QStringLiteral(
"pre-set DPI not equal to painter's DPI (%1 vs %2)" ).arg( paintDevice->logicalDpiX() ).arg(
mSettings.
outputDpi() );
73 mLabelingEngineV2.reset();
78 mLabelingEngineV2->setMapSettings(
mSettings );
82 mLayerJobs =
prepareJobs( mPainter, mLabelingEngineV2.get() );
85 QgsDebugMsgLevel(
"Rendering prepared in (seconds): " + QString(
"%1" ).arg( prepareTime.elapsed() / 1000.0 ), 4 );
87 if ( mRenderSynchronously )
95 connect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererCustomPainterJob::futureFinished );
97 mFuture = QtConcurrent::run( staticRender,
this );
98 mFutureWatcher.setFuture( mFuture );
111 disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererCustomPainterJob::futureFinished );
117 mFutureWatcher.waitForFinished();
119 QgsDebugMsgLevel( QString(
"QPAINER cancel waited %1 ms" ).arg( t.elapsed() / 1000.0 ), 5 );
134 mLabelJob.context.setRenderingStopped(
true );
135 for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
137 it->context.setRenderingStopped(
true );
138 if ( it->renderer && it->renderer->feedback() )
139 it->renderer->feedback()->cancel();
148 disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererCustomPainterJob::futureFinished );
153 mFutureWatcher.waitForFinished();
155 QgsDebugMsgLevel( QString(
"waitForFinished: %1 ms" ).arg( t.elapsed() / 1000.0 ), 4 );
167 return mLabelJob.cached;
172 if ( mLabelingEngineV2 )
173 return mLabelingEngineV2->takeResults();
182 connect( &mFutureWatcher, &QFutureWatcher<void>::finished, &loop, &QEventLoop::quit );
189 mRenderSynchronously =
true;
192 mRenderSynchronously =
false;
196 void QgsMapRendererCustomPainterJob::futureFinished()
223 catch ( std::exception &e )
226 QgsDebugMsg(
"Caught unhandled std::exception: " + QString::fromLatin1( e.what() ) );
230 QgsDebugMsg(
"Caught unhandled unknown exception" );
234 void QgsMapRendererCustomPainterJob::doRender()
240 for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
242 LayerRenderJob &job = *it;
244 if ( job.context.renderingStopped() )
247 if ( job.context.useAdvancedEffects() )
251 mPainter->setCompositionMode( job.blendMode );
262 job.imageInitialized =
true;
265 job.renderer->render();
267 job.renderingTime += layerTime.elapsed();
273 mPainter->setOpacity( job.opacity );
274 mPainter->drawImage( 0, 0, *job.img );
275 mPainter->setOpacity( 1.0 );
284 if ( !mLabelJob.cached )
292 mLabelJob.img->fill( 0 );
293 painter.begin( mLabelJob.img );
294 mLabelJob.context.setPainter( &painter );
303 mLabelJob.complete =
true;
304 mLabelJob.renderingTime = labelTime.elapsed();
305 mLabelJob.participatingLayers = _qgis_listRawToQPointer( mLabelingEngineV2->participatingLayers() );
308 if ( mLabelJob.img && mLabelJob.complete )
310 mPainter->setCompositionMode( QPainter::CompositionMode_SourceOver );
311 mPainter->setOpacity( 1.0 );
312 mPainter->drawImage( 0, 0, *mLabelJob.img );
315 QgsDebugMsg(
"Rendering completed in (seconds): " + QString(
"%1" ).arg( renderTime.elapsed() / 1000.0 ) );
327 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
333 if ( labelingEngine2 )
339 labelingEngine2->
run( renderContext );
342 QgsDebugMsg( QString(
"Draw labeling took (seconds): %1" ).arg( t.elapsed() / 1000. ) );
346 bool QgsMapRendererJob::needTemporaryImage(
QgsMapLayer *ml )
357 ( ( 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.
void cleanupJobs(LayerRenderJobs &jobs)
void setCoordinateTransform(const QgsCoordinateTransform &t)
Sets coordinate transformation.
static void drawLabeling(const QgsMapSettings &settings, QgsRenderContext &renderContext, QgsLabelingEngine *labelingEngine2, QPainter *painter)
QColor backgroundColor() const
Get 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.
QgsMapLayer::LayerType type() const
Returns the type of the layer.
void setExtent(const QgsRectangle &extent)
void waitForFinishedWithEventLoop(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
Wait for the job to be finished - and keep the thread's event loop running while waiting.
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
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()
Return renderer.
bool usedCachedLabels() const override
Returns true if the render job was able to use a cached labeling solution.
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 cancelation of the rendering job without blocking.
double outputDpi() const
Return 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)
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
~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
Get 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.
QSize outputSize() const
Return the size of the resulting map image.
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.