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