QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
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 "qgsfeedback.h"
19#include "qgslabelingengine.h"
20#include "qgslogger.h"
21#include "qgsproject.h"
22#include "qgsmaplayerrenderer.h"
25
28 , mFlags( flags )
29{
30}
31
33{
34 // final cleanup
35 cleanupJobs( mLayerJobs );
36 cleanupLabelJob( mLabelJob );
37}
38
39
40void QgsMapRendererStagedRenderJob::startPrivate()
41{
42 mRenderingStart.start();
43 mErrors.clear();
44
45 QgsDebugMsgLevel( QStringLiteral( "Preparing list of layer jobs for rendering" ), 5 );
46 QElapsedTimer prepareTime;
47 prepareTime.start();
48
49 mLabelingEngineV2.reset();
50
52 {
53 if ( mFlags & RenderLabelsByMapLayer )
54 mLabelingEngineV2.reset( new QgsStagedRenderLabelingEngine() );
55 else
56 mLabelingEngineV2.reset( new QgsDefaultLabelingEngine() );
57 mLabelingEngineV2->setMapSettings( mSettings );
58 }
59
60 mLayerJobs = prepareJobs( nullptr, mLabelingEngineV2.get(), true );
61 mLabelJob = prepareLabelingJob( nullptr, mLabelingEngineV2.get(), false );
62
63 mJobIt = mLayerJobs.begin();
64}
65
67{
68}
69
71{
72}
73
75{
76}
77
79{
80 return true;
81}
82
84{
85 return false;
86}
87
89{
90 if ( mLabelingEngineV2 )
91 return mLabelingEngineV2->takeResults();
92 else
93 return nullptr;
94}
95
97{
98 if ( isFinished() )
99 return false;
100
101 preparePainter( painter );
102
103 if ( mJobIt != mLayerJobs.end() )
104 {
105 LayerRenderJob &job = *mJobIt;
106 emit layerRenderingStarted( job.layerId );
107 job.renderer->renderContext()->setPainter( painter );
108
109 if ( job.context()->useAdvancedEffects() )
110 {
111 // Set the QPainter composition mode so that this layer is rendered using
112 // the desired blending mode
113 painter->setCompositionMode( job.blendMode );
114 }
115
116 if ( job.img )
117 {
118 job.img->fill( 0 );
119 job.imageInitialized = true;
120 }
121
122 job.completed = job.renderer->render();
123
124 if ( job.img )
125 {
126 // If we flattened this layer for alternate blend modes, composite it now
127 painter->setOpacity( job.opacity );
128 painter->drawImage( 0, 0, *job.img );
129 painter->setOpacity( 1.0 );
130 }
131 job.context()->setPainter( nullptr );
132
133 emit layerRendered( job.layerId );
134 }
135 else
136 {
137 if ( !mLabelingEngineV2 )
138 return false;
139
140 if ( mFlags & RenderLabelsByMapLayer )
141 {
142 if ( !mPreparedStagedLabelJob || mLabelLayerIt == mLabelingLayers.end() )
143 return false;
144
145 mLabelJob.context.setPainter( painter );
146
147 // Reset the composition mode before rendering the labels
148 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
149
150 // render just the current layer's labels
151 static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->renderLabelsForLayer( mLabelJob.context, *mLabelLayerIt );
152
153 mLabelJob.context.setPainter( nullptr );
154 }
155 else
156 {
157 mLabelJob.context.setPainter( painter );
158 drawLabeling( mLabelJob.context, mLabelingEngineV2.get(), painter );
159 mLabelJob.complete = true;
160 mLabelJob.participatingLayers = _qgis_listRawToQPointer( mLabelingEngineV2->participatingLayers() );
161 mLabelJob.context.setPainter( nullptr );
162 }
163 }
164 return true;
165}
166
168{
169 if ( isFinished() )
170 return false;
171
172 if ( mJobIt != mLayerJobs.end() )
173 {
174 ++mJobIt;
175 if ( mJobIt != mLayerJobs.end() )
176 return true;
177 }
178
179 if ( mLabelingEngineV2 )
180 {
181 if ( mFlags & RenderLabelsByMapLayer )
182 {
183 if ( !mPreparedStagedLabelJob )
184 {
185 mLabelingEngineV2->run( mLabelJob.context );
186 mPreparedStagedLabelJob = true;
187 mLabelingLayers = mLabelingEngineV2->participatingLayerIds();
188 mLabelLayerIt = mLabelingLayers.begin();
189 if ( mLabelLayerIt == mLabelingLayers.end() )
190 {
191 // no label layers to render!
192 static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->finalize();
193 return false;
194 }
195 return true;
196 }
197 else
198 {
199 if ( mLabelLayerIt != mLabelingLayers.end() )
200 {
201 ++mLabelLayerIt;
202 if ( mLabelLayerIt != mLabelingLayers.end() )
203 return true;
204 }
205 }
206 return false;
207 }
208 else
209 {
210 if ( mNextIsLabel )
211 {
212 mExportedLabels = true;
213 }
214 else if ( !mExportedLabels )
215 {
216 mNextIsLabel = true;
217 return true;
218 }
219 }
220 }
221 return false;
222}
223
225{
226 return currentStage() == Finished;
227}
228
230{
231 if ( mJobIt != mLayerJobs.end() )
232 {
233 const LayerRenderJob &job = *mJobIt;
234 return job.layerId;
235 }
236 else if ( mFlags & RenderLabelsByMapLayer && mPreparedStagedLabelJob )
237 {
238 if ( mLabelLayerIt != mLabelingLayers.end() )
239 return *mLabelLayerIt;
240 }
241 return QString();
242}
243
245{
246 if ( mJobIt != mLayerJobs.end() )
247 {
248 const LayerRenderJob &job = *mJobIt;
249 return job.opacity;
250 }
251 return 1.0;
252}
253
255{
256 if ( mJobIt != mLayerJobs.end() )
257 {
258 const LayerRenderJob &job = *mJobIt;
259 return job.blendMode;
260 }
261 return QPainter::CompositionMode_SourceOver;
262}
263
265{
266 if ( mJobIt != mLayerJobs.end() )
267 return Symbology;
268 else if ( mLabelingEngineV2 && mFlags & RenderLabelsByMapLayer )
269 {
270 if ( !mPreparedStagedLabelJob )
271 return Labels;
272 if ( mLabelLayerIt != mLabelingLayers.end() )
273 return Labels;
274 }
275 else if ( mNextIsLabel && !mExportedLabels )
276 return Labels;
277
278 return Finished;
279}
@ 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.
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