QGIS API Documentation 3.41.0-Master (45a0abf3bec)
Loading...
Searching...
No Matches
qgsmaprendererstagedrenderjob.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaprendererstagedrenderjob.cpp
3 --------------------------------------
4 Date : August 2019
5 Copyright : (C) 2019 by Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17#include "moc_qgsmaprendererstagedrenderjob.cpp"
18
19#include "qgsfeedback.h"
20#include "qgslabelingengine.h"
21#include "qgslogger.h"
22#include "qgsproject.h"
23#include "qgsmaplayerrenderer.h"
26
32
34{
35 // final cleanup
36 cleanupJobs( mLayerJobs );
37 cleanupLabelJob( mLabelJob );
38}
39
40
41void QgsMapRendererStagedRenderJob::startPrivate()
42{
43 mRenderingStart.start();
44 mErrors.clear();
45
46 QgsDebugMsgLevel( QStringLiteral( "Preparing list of layer jobs for rendering" ), 5 );
47 QElapsedTimer prepareTime;
48 prepareTime.start();
49
50 mLabelingEngineV2.reset();
51
53 {
54 if ( mFlags & RenderLabelsByMapLayer )
55 mLabelingEngineV2.reset( new QgsStagedRenderLabelingEngine() );
56 else
57 mLabelingEngineV2.reset( new QgsDefaultLabelingEngine() );
58 mLabelingEngineV2->setMapSettings( mSettings );
59 }
60
61 mLayerJobs = prepareJobs( nullptr, mLabelingEngineV2.get(), true );
62 mLabelJob = prepareLabelingJob( nullptr, mLabelingEngineV2.get(), false );
63
64 mJobIt = mLayerJobs.begin();
65}
66
70
74
78
80{
81 return true;
82}
83
85{
86 return false;
87}
88
90{
91 if ( mLabelingEngineV2 )
92 return mLabelingEngineV2->takeResults();
93 else
94 return nullptr;
95}
96
98{
99 if ( isFinished() )
100 return false;
101
102 preparePainter( painter );
103
104 if ( mJobIt != mLayerJobs.end() )
105 {
106 LayerRenderJob &job = *mJobIt;
107 emit layerRenderingStarted( job.layerId );
108 job.renderer->renderContext()->setPainter( painter );
109
110 if ( job.context()->useAdvancedEffects() )
111 {
112 // Set the QPainter composition mode so that this layer is rendered using
113 // the desired blending mode
114 painter->setCompositionMode( job.blendMode );
115 }
116
117 if ( job.previewRenderImage && !job.previewRenderImageInitialized )
118 {
119 job.previewRenderImage->fill( 0 );
120 job.previewRenderImageInitialized = true;
121 }
122
123 if ( job.img )
124 {
125 job.img->fill( 0 );
126 job.imageInitialized = true;
127 }
128
129 job.completed = job.renderer->render();
130
131 if ( job.img )
132 {
133 // If we flattened this layer for alternate blend modes, composite it now
134 painter->setOpacity( job.opacity );
135 painter->drawImage( 0, 0, *job.img );
136 painter->setOpacity( 1.0 );
137 }
138 job.context()->setPainter( nullptr );
139
140 emit layerRendered( job.layerId );
141 }
142 else
143 {
144 if ( !mLabelingEngineV2 )
145 return false;
146
147 if ( mFlags & RenderLabelsByMapLayer )
148 {
149 if ( !mPreparedStagedLabelJob || mLabelLayerIt == mLabelingLayers.end() )
150 return false;
151
152 mLabelJob.context.setPainter( painter );
153
154 // Reset the composition mode before rendering the labels
155 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
156
157 // render just the current layer's labels
158 static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->renderLabelsForLayer( mLabelJob.context, *mLabelLayerIt );
159
160 mLabelJob.context.setPainter( nullptr );
161 }
162 else
163 {
164 mLabelJob.context.setPainter( painter );
165 drawLabeling( mLabelJob.context, mLabelingEngineV2.get(), painter );
166 mLabelJob.complete = true;
167 mLabelJob.participatingLayers = participatingLabelLayers( mLabelingEngineV2.get() );
168 mLabelJob.context.setPainter( nullptr );
169 }
170 }
171 return true;
172}
173
175{
176 if ( isFinished() )
177 return false;
178
179 if ( mJobIt != mLayerJobs.end() )
180 {
181 ++mJobIt;
182 if ( mJobIt != mLayerJobs.end() )
183 return true;
184 }
185
186 if ( mLabelingEngineV2 )
187 {
188 if ( mFlags & RenderLabelsByMapLayer )
189 {
190 if ( !mPreparedStagedLabelJob )
191 {
192 mLabelingEngineV2->run( mLabelJob.context );
193 mPreparedStagedLabelJob = true;
194 mLabelingLayers = mLabelingEngineV2->participatingLayerIds();
195 mLabelLayerIt = mLabelingLayers.begin();
196 if ( mLabelLayerIt == mLabelingLayers.end() )
197 {
198 // no label layers to render!
199 static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->finalize();
200 return false;
201 }
202 return true;
203 }
204 else
205 {
206 if ( mLabelLayerIt != mLabelingLayers.end() )
207 {
208 ++mLabelLayerIt;
209 if ( mLabelLayerIt != mLabelingLayers.end() )
210 return true;
211 }
212 }
213 return false;
214 }
215 else
216 {
217 if ( mNextIsLabel )
218 {
219 mExportedLabels = true;
220 }
221 else if ( !mExportedLabels )
222 {
223 mNextIsLabel = true;
224 return true;
225 }
226 }
227 }
228 return false;
229}
230
235
237{
238 if ( mJobIt != mLayerJobs.end() )
239 {
240 const LayerRenderJob &job = *mJobIt;
241 return job.layerId;
242 }
243 else if ( mFlags & RenderLabelsByMapLayer && mPreparedStagedLabelJob )
244 {
245 if ( mLabelLayerIt != mLabelingLayers.end() )
246 return *mLabelLayerIt;
247 }
248 return QString();
249}
250
252{
253 if ( mJobIt != mLayerJobs.end() )
254 {
255 const LayerRenderJob &job = *mJobIt;
256 return job.opacity;
257 }
258 return 1.0;
259}
260
262{
263 if ( mJobIt != mLayerJobs.end() )
264 {
265 const LayerRenderJob &job = *mJobIt;
266 return job.blendMode;
267 }
268 return QPainter::CompositionMode_SourceOver;
269}
270
272{
273 if ( mJobIt != mLayerJobs.end() )
274 return Symbology;
275 else if ( mLabelingEngineV2 && mFlags & RenderLabelsByMapLayer )
276 {
277 if ( !mPreparedStagedLabelJob )
278 return Labels;
279 if ( mLabelLayerIt != mLabelingLayers.end() )
280 return Labels;
281 }
282 else if ( mNextIsLabel && !mExportedLabels )
283 return Labels;
284
285 return Finished;
286}
@ DrawLabeling
Enable drawing of labels on top of the map.
Default QgsLabelingEngine implementation, which completes the whole labeling operation (including lab...
Class that stores computed placement from labeling engine.
Abstract base class for map renderer jobs which use custom painters.
void preparePainter(QPainter *painter, const QColor &backgroundColor=Qt::transparent)
Prepares the given painter ready for a map render.
QList< QPointer< QgsMapLayer > > participatingLabelLayers(QgsLabelingEngine *engine)
Returns a list of the layers participating in the map labeling.
static Q_DECL_DEPRECATED void drawLabeling(const QgsMapSettings &settings, QgsRenderContext &renderContext, QgsLabelingEngine *labelingEngine2, QPainter *painter)
void layerRendered(const QString &layerId)
Emitted when a layer has completed rendering.
std::vector< LayerRenderJob > prepareJobs(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool deferredPainterSet=false)
Creates a list of layer rendering jobs and prepares them for later render.
void cleanupJobs(std::vector< LayerRenderJob > &jobs)
QElapsedTimer mRenderingStart
QgsMapSettings mSettings
void layerRenderingStarted(const QString &layerId)
Emitted just before rendering starts for a particular layer.
LabelRenderJob prepareLabelingJob(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool canUseLabelCache=true)
Prepares a labeling job.
void cleanupLabelJob(LabelRenderJob &job)
Handles clean up tasks for a label job, including deletion of images and storing cached label results...
double currentLayerOpacity() const
Returns the opacity for the current layer about to be rendered in the next render operation.
void cancel() override
Stop the rendering job - does not return until the job has terminated.
@ RenderLabelsByMapLayer
Labels should be rendered in individual stages by map layer. This allows separation of labels belongi...
bool usedCachedLabels() const override
Returns true if the render job was able to use a cached labeling solution.
RenderStage currentStage() const
Returns the current stage which will be rendered in the next render operation.
void waitForFinished() override
Block until the job has finished.
QPainter::CompositionMode currentLayerCompositionMode() const
Returns the composition mode for the current layer about to be rendered in the next render operation.
QString currentLayerId() const
Returns the ID of the current layer about to be rendered in the next render operation.
QgsLabelingResults * takeLabelingResults() override
Gets pointer to internal labeling engine (in order to get access to the results).
bool isActive() const override
Tell whether the rendering job is currently running in background.
QgsMapRendererStagedRenderJob(const QgsMapSettings &settings, Flags flags=Flags())
Constructor for QgsMapRendererStagedRenderJob, using the given map settings.
bool isFinished() const
Returns true if the job is finished, and nothing remains to render.
RenderStage
Represents the stages of a rendering job.
bool nextPart()
Iterates to the next part to render.
bool renderCurrentPart(QPainter *painter)
Renders the current part of the map to the specified painter.
void cancelWithoutBlocking() override
Triggers cancellation of the rendering job without blocking.
The QgsMapSettings class contains configuration for rendering of the map.
bool testFlag(Qgis::MapSettingsFlag flag) const
Check whether a particular flag is enabled.
A QgsLabelingEngine implementation, which only calculates the labeling solution during its run() meth...
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39