QGIS API Documentation 3.99.0-Master (26c88405ac0)
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
18#include <memory>
19
20#include "qgsfeedback.h"
21#include "qgslabelingengine.h"
22#include "qgslogger.h"
24#include "qgsmaplayerrenderer.h"
25#include "qgsproject.h"
27
28#include "moc_qgsmaprendererstagedrenderjob.cpp"
29
35
37{
38 // final cleanup
39 cleanupJobs( mLayerJobs );
40 cleanupLabelJob( mLabelJob );
41}
42
43
44void QgsMapRendererStagedRenderJob::startPrivate()
45{
46 mRenderingStart.start();
47 mErrors.clear();
48
49 QgsDebugMsgLevel( QStringLiteral( "Preparing list of layer jobs for rendering" ), 5 );
50 QElapsedTimer prepareTime;
51 prepareTime.start();
52
53 mLabelingEngineV2.reset();
54
56 {
57 if ( mFlags & RenderLabelsByMapLayer )
58 mLabelingEngineV2 = std::make_unique<QgsStagedRenderLabelingEngine>( );
59 else
60 mLabelingEngineV2 = std::make_unique<QgsDefaultLabelingEngine>( );
61 mLabelingEngineV2->setMapSettings( mSettings );
62 }
63
64 mLayerJobs = prepareJobs( nullptr, mLabelingEngineV2.get(), true );
65 mLabelJob = prepareLabelingJob( nullptr, mLabelingEngineV2.get(), false );
66
67 mJobIt = mLayerJobs.begin();
68}
69
73
77
81
83{
84 return true;
85}
86
88{
89 return false;
90}
91
93{
94 if ( mLabelingEngineV2 )
95 return mLabelingEngineV2->takeResults();
96 else
97 return nullptr;
98}
99
101{
102 if ( isFinished() )
103 return false;
104
105 preparePainter( painter );
106
107 if ( mJobIt != mLayerJobs.end() )
108 {
109 LayerRenderJob &job = *mJobIt;
110 emit layerRenderingStarted( job.layerId );
111 job.renderer->renderContext()->setPainter( painter );
112
113 if ( job.context()->rasterizedRenderingPolicy() != Qgis::RasterizedRenderingPolicy::ForceVector )
114 {
115 // Set the QPainter composition mode so that this layer is rendered using
116 // the desired blending mode
117 painter->setCompositionMode( job.blendMode );
118 }
119
120 if ( job.previewRenderImage && !job.previewRenderImageInitialized )
121 {
122 job.previewRenderImage->fill( 0 );
123 job.previewRenderImageInitialized = true;
124 }
125
126 if ( job.img )
127 {
128 job.img->fill( 0 );
129 job.imageInitialized = true;
130 }
131
132 job.completed = job.renderer->render();
133
134 if ( job.img )
135 {
136 // If we flattened this layer for alternate blend modes, composite it now
137 painter->setOpacity( job.opacity );
138 painter->drawImage( 0, 0, *job.img );
139 painter->setOpacity( 1.0 );
140 }
141 job.context()->setPainter( nullptr );
142
143 emit layerRendered( job.layerId );
144 }
145 else
146 {
147 if ( !mLabelingEngineV2 )
148 return false;
149
150 if ( mFlags & RenderLabelsByMapLayer )
151 {
152 if ( !mPreparedStagedLabelJob || mLabelLayerIt == mLabelingLayers.end() )
153 return false;
154
155 mLabelJob.context.setPainter( painter );
156
157 // Reset the composition mode before rendering the labels
158 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
159
160 // render just the current layer's labels
161 static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->renderLabelsForLayer( mLabelJob.context, *mLabelLayerIt );
162
163 mLabelJob.context.setPainter( nullptr );
164 }
165 else
166 {
167 mLabelJob.context.setPainter( painter );
168 drawLabeling( mLabelJob.context, mLabelingEngineV2.get(), painter );
169 mLabelJob.complete = true;
170 mLabelJob.participatingLayers = participatingLabelLayers( mLabelingEngineV2.get() );
171 mLabelJob.context.setPainter( nullptr );
172 }
173 }
174 return true;
175}
176
178{
179 if ( isFinished() )
180 return false;
181
182 if ( mJobIt != mLayerJobs.end() )
183 {
184 ++mJobIt;
185 if ( mJobIt != mLayerJobs.end() )
186 return true;
187 }
188
189 if ( mLabelingEngineV2 )
190 {
191 if ( mFlags & RenderLabelsByMapLayer )
192 {
193 if ( !mPreparedStagedLabelJob )
194 {
195 mLabelingEngineV2->run( mLabelJob.context );
196 mPreparedStagedLabelJob = true;
197 mLabelingLayers = mLabelingEngineV2->participatingLayerIds();
198 mLabelLayerIt = mLabelingLayers.begin();
199 if ( mLabelLayerIt == mLabelingLayers.end() )
200 {
201 // no label layers to render!
202 static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->finalize();
203 return false;
204 }
205 return true;
206 }
207 else
208 {
209 if ( mLabelLayerIt != mLabelingLayers.end() )
210 {
211 ++mLabelLayerIt;
212 if ( mLabelLayerIt != mLabelingLayers.end() )
213 return true;
214 }
215 }
216 return false;
217 }
218 else
219 {
220 if ( mNextIsLabel )
221 {
222 mExportedLabels = true;
223 }
224 else if ( !mExportedLabels )
225 {
226 mNextIsLabel = true;
227 return true;
228 }
229 }
230 }
231 return false;
232}
233
238
240{
241 if ( mJobIt != mLayerJobs.end() )
242 {
243 const LayerRenderJob &job = *mJobIt;
244 return job.layerId;
245 }
246 else if ( mFlags & RenderLabelsByMapLayer && mPreparedStagedLabelJob )
247 {
248 if ( mLabelLayerIt != mLabelingLayers.end() )
249 return *mLabelLayerIt;
250 }
251 return QString();
252}
253
255{
256 if ( mJobIt != mLayerJobs.end() )
257 {
258 const LayerRenderJob &job = *mJobIt;
259 return job.opacity;
260 }
261 return 1.0;
262}
263
265{
266 if ( mJobIt != mLayerJobs.end() )
267 {
268 const LayerRenderJob &job = *mJobIt;
269 return job.blendMode;
270 }
271 return QPainter::CompositionMode_SourceOver;
272}
273
275{
276 if ( mJobIt != mLayerJobs.end() )
277 return Symbology;
278 else if ( mLabelingEngineV2 && mFlags & RenderLabelsByMapLayer )
279 {
280 if ( !mPreparedStagedLabelJob )
281 return Labels;
282 if ( mLabelLayerIt != mLabelingLayers.end() )
283 return Labels;
284 }
285 else if ( mNextIsLabel && !mExportedLabels )
286 return Labels;
287
288 return Finished;
289}
@ ForceVector
Always force vector-based rendering, even when the result will be visually different to a raster-base...
Definition qgis.h:2706
@ DrawLabeling
Enable drawing of labels on top of the map.
Definition qgis.h:2721
Stores computed placement from labeling engine.
void preparePainter(QPainter *painter, const QColor &backgroundColor=Qt::transparent)
Prepares the given painter ready for a map render.
QgsMapRendererAbstractCustomPainterJob(const QgsMapSettings &settings)
Constructor for QgsMapRendererAbstractCustomPainterJob, using the given map settings.
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.
Contains configuration for rendering maps.
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...
void finalize()
Finalizes and cleans up the engine following the rendering of labels for the last layer to be labeled...
void renderLabelsForLayer(QgsRenderContext &context, const QString &layerId)
Renders all the labels which belong only to the layer with matching layerId to the specified render c...
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:61