QGIS API Documentation 3.99.0-Master (d270888f95f)
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 <QString>
29
30#include "moc_qgsmaprendererstagedrenderjob.cpp"
31
32using namespace Qt::StringLiterals;
33
39
41{
42 // final cleanup
43 cleanupJobs( mLayerJobs );
44 cleanupLabelJob( mLabelJob );
45}
46
47
48void QgsMapRendererStagedRenderJob::startPrivate()
49{
50 mRenderingStart.start();
51 mErrors.clear();
52
53 QgsDebugMsgLevel( u"Preparing list of layer jobs for rendering"_s, 5 );
54 QElapsedTimer prepareTime;
55 prepareTime.start();
56
57 mLabelingEngineV2.reset();
58
60 {
61 if ( mFlags & RenderLabelsByMapLayer )
62 mLabelingEngineV2 = std::make_unique<QgsStagedRenderLabelingEngine>( );
63 else
64 mLabelingEngineV2 = std::make_unique<QgsDefaultLabelingEngine>( );
65 mLabelingEngineV2->setMapSettings( mSettings );
66 }
67
68 mLayerJobs = prepareJobs( nullptr, mLabelingEngineV2.get(), true );
69 mLabelJob = prepareLabelingJob( nullptr, mLabelingEngineV2.get(), false );
70
71 mJobIt = mLayerJobs.begin();
72}
73
77
81
85
87{
88 return true;
89}
90
92{
93 return false;
94}
95
97{
98 if ( mLabelingEngineV2 )
99 return mLabelingEngineV2->takeResults();
100 else
101 return nullptr;
102}
103
105{
106 if ( isFinished() )
107 return false;
108
109 preparePainter( painter );
110
111 if ( mJobIt != mLayerJobs.end() )
112 {
113 LayerRenderJob &job = *mJobIt;
114 emit layerRenderingStarted( job.layerId );
115 job.renderer->renderContext()->setPainter( painter );
116
117 if ( job.context()->rasterizedRenderingPolicy() != Qgis::RasterizedRenderingPolicy::ForceVector )
118 {
119 // Set the QPainter composition mode so that this layer is rendered using
120 // the desired blending mode
121 painter->setCompositionMode( job.blendMode );
122 }
123
124 if ( job.previewRenderImage && !job.previewRenderImageInitialized )
125 {
126 job.previewRenderImage->fill( 0 );
127 job.previewRenderImageInitialized = true;
128 }
129
130 if ( job.img )
131 {
132 job.img->fill( 0 );
133 job.imageInitialized = true;
134 }
135
136 job.completed = job.renderer->render();
137
138 if ( job.img )
139 {
140 // If we flattened this layer for alternate blend modes, composite it now
141 painter->setOpacity( job.opacity );
142 painter->drawImage( 0, 0, *job.img );
143 painter->setOpacity( 1.0 );
144 }
145 job.context()->setPainter( nullptr );
146
147 emit layerRendered( job.layerId );
148 }
149 else
150 {
151 if ( !mLabelingEngineV2 )
152 return false;
153
154 if ( mFlags & RenderLabelsByMapLayer )
155 {
156 if ( !mPreparedStagedLabelJob || mLabelLayerIt == mLabelingLayers.end() )
157 return false;
158
159 mLabelJob.context.setPainter( painter );
160
161 // Reset the composition mode before rendering the labels
162 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
163
164 // render just the current layer's labels
165 static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->renderLabelsForLayer( mLabelJob.context, *mLabelLayerIt );
166
167 mLabelJob.context.setPainter( nullptr );
168 }
169 else
170 {
171 mLabelJob.context.setPainter( painter );
172 drawLabeling( mLabelJob.context, mLabelingEngineV2.get(), painter );
173 mLabelJob.complete = true;
174 mLabelJob.participatingLayers = participatingLabelLayers( mLabelingEngineV2.get() );
175 mLabelJob.context.setPainter( nullptr );
176 }
177 }
178 return true;
179}
180
182{
183 if ( isFinished() )
184 return false;
185
186 if ( mJobIt != mLayerJobs.end() )
187 {
188 ++mJobIt;
189 if ( mJobIt != mLayerJobs.end() )
190 return true;
191 }
192
193 if ( mLabelingEngineV2 )
194 {
195 if ( mFlags & RenderLabelsByMapLayer )
196 {
197 if ( !mPreparedStagedLabelJob )
198 {
199 mLabelingEngineV2->run( mLabelJob.context );
200 mPreparedStagedLabelJob = true;
201 mLabelingLayers = mLabelingEngineV2->participatingLayerIds();
202 mLabelLayerIt = mLabelingLayers.begin();
203 if ( mLabelLayerIt == mLabelingLayers.end() )
204 {
205 // no label layers to render!
206 static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->finalize();
207 return false;
208 }
209 return true;
210 }
211 else
212 {
213 if ( mLabelLayerIt != mLabelingLayers.end() )
214 {
215 ++mLabelLayerIt;
216 if ( mLabelLayerIt != mLabelingLayers.end() )
217 return true;
218 }
219 }
220 return false;
221 }
222 else
223 {
224 if ( mNextIsLabel )
225 {
226 mExportedLabels = true;
227 }
228 else if ( !mExportedLabels )
229 {
230 mNextIsLabel = true;
231 return true;
232 }
233 }
234 }
235 return false;
236}
237
242
244{
245 if ( mJobIt != mLayerJobs.end() )
246 {
247 const LayerRenderJob &job = *mJobIt;
248 return job.layerId;
249 }
250 else if ( mFlags & RenderLabelsByMapLayer && mPreparedStagedLabelJob )
251 {
252 if ( mLabelLayerIt != mLabelingLayers.end() )
253 return *mLabelLayerIt;
254 }
255 return QString();
256}
257
259{
260 if ( mJobIt != mLayerJobs.end() )
261 {
262 const LayerRenderJob &job = *mJobIt;
263 return job.opacity;
264 }
265 return 1.0;
266}
267
269{
270 if ( mJobIt != mLayerJobs.end() )
271 {
272 const LayerRenderJob &job = *mJobIt;
273 return job.blendMode;
274 }
275 return QPainter::CompositionMode_SourceOver;
276}
277
279{
280 if ( mJobIt != mLayerJobs.end() )
281 return Symbology;
282 else if ( mLabelingEngineV2 && mFlags & RenderLabelsByMapLayer )
283 {
284 if ( !mPreparedStagedLabelJob )
285 return Labels;
286 if ( mLabelLayerIt != mLabelingLayers.end() )
287 return Labels;
288 }
289 else if ( mNextIsLabel && !mExportedLabels )
290 return Labels;
291
292 return Finished;
293}
@ ForceVector
Always force vector-based rendering, even when the result will be visually different to a raster-base...
Definition qgis.h:2764
@ DrawLabeling
Enable drawing of labels on top of the map.
Definition qgis.h:2779
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:63