QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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"
23 #include "qgsmaplayerlistutils.h"
24 
27  , mFlags( flags )
28 {
29 }
30 
32 {
33  // final cleanup
34  cleanupJobs( mLayerJobs );
35  cleanupLabelJob( mLabelJob );
36 }
37 
38 
40 {
41  mRenderingStart.start();
42  mErrors.clear();
43 
44  QgsDebugMsgLevel( QStringLiteral( "Preparing list of layer jobs for rendering" ), 5 );
45  QTime prepareTime;
46  prepareTime.start();
47 
48  mLabelingEngineV2.reset();
49 
51  {
52  if ( mFlags & RenderLabelsByMapLayer )
53  mLabelingEngineV2.reset( new QgsStagedRenderLabelingEngine() );
54  else
55  mLabelingEngineV2.reset( new QgsDefaultLabelingEngine() );
56  mLabelingEngineV2->setMapSettings( mSettings );
57  }
58 
59  mLayerJobs = prepareJobs( nullptr, mLabelingEngineV2.get(), true );
60  mLabelJob = prepareLabelingJob( nullptr, mLabelingEngineV2.get(), false );
61 
62  mJobIt = mLayerJobs.begin();
63 }
64 
66 {
67 }
68 
70 {
71 }
72 
74 {
75 }
76 
78 {
79  return true;
80 }
81 
83 {
84  return false;
85 }
86 
88 {
89  if ( mLabelingEngineV2 )
90  return mLabelingEngineV2->takeResults();
91  else
92  return nullptr;
93 }
94 
96 {
97  if ( isFinished() )
98  return false;
99 
100  preparePainter( painter );
101 
102  if ( mJobIt != mLayerJobs.end() )
103  {
104  LayerRenderJob &job = *mJobIt;
105  job.renderer->renderContext()->setPainter( painter );
106 
107  if ( job.context.useAdvancedEffects() )
108  {
109  // Set the QPainter composition mode so that this layer is rendered using
110  // the desired blending mode
111  painter->setCompositionMode( job.blendMode );
112  }
113 
114  if ( job.img )
115  {
116  job.img->fill( 0 );
117  job.imageInitialized = true;
118  }
119 
120  job.renderer->render();
121 
122  if ( job.img )
123  {
124  // If we flattened this layer for alternate blend modes, composite it now
125  painter->setOpacity( job.opacity );
126  painter->drawImage( 0, 0, *job.img );
127  painter->setOpacity( 1.0 );
128  }
129  job.context.setPainter( nullptr );
130  }
131  else
132  {
133  if ( !mLabelingEngineV2 )
134  return false;
135 
136  if ( mFlags & RenderLabelsByMapLayer )
137  {
138  if ( !mPreparedStagedLabelJob || mLabelLayerIt == mLabelingLayers.end() )
139  return false;
140 
141  mLabelJob.context.setPainter( painter );
142 
143  // Reset the composition mode before rendering the labels
144  painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
145 
146  // render just the current layer's labels
147  static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->renderLabelsForLayer( mLabelJob.context, *mLabelLayerIt );
148 
149  mLabelJob.context.setPainter( nullptr );
150  }
151  else
152  {
153  mLabelJob.context.setPainter( painter );
154  drawLabeling( mLabelJob.context, mLabelingEngineV2.get(), painter );
155  mLabelJob.complete = true;
156  mLabelJob.participatingLayers = _qgis_listRawToQPointer( mLabelingEngineV2->participatingLayers() );
157  mLabelJob.context.setPainter( nullptr );
158  }
159  }
160  return true;
161 }
162 
164 {
165  if ( isFinished() )
166  return false;
167 
168  if ( mJobIt != mLayerJobs.end() )
169  {
170  mJobIt++;
171  if ( mJobIt != mLayerJobs.end() )
172  return true;
173  }
174 
175  if ( mLabelingEngineV2 )
176  {
177  if ( mFlags & RenderLabelsByMapLayer )
178  {
179  if ( !mPreparedStagedLabelJob )
180  {
181  mLabelingEngineV2->run( mLabelJob.context );
182  mPreparedStagedLabelJob = true;
183  mLabelingLayers = mLabelingEngineV2->participatingLayerIds();
184  mLabelLayerIt = mLabelingLayers.begin();
185  if ( mLabelLayerIt == mLabelingLayers.end() )
186  {
187  // no label layers to render!
188  static_cast< QgsStagedRenderLabelingEngine * >( mLabelingEngineV2.get() )->finalize();
189  return false;
190  }
191  return true;
192  }
193  else
194  {
195  if ( mLabelLayerIt != mLabelingLayers.end() )
196  {
197  mLabelLayerIt++;
198  if ( mLabelLayerIt != mLabelingLayers.end() )
199  return true;
200  }
201  }
202  return false;
203  }
204  else
205  {
206  if ( mNextIsLabel )
207  {
208  mExportedLabels = true;
209  }
210  else if ( !mExportedLabels )
211  {
212  mNextIsLabel = true;
213  return true;
214  }
215  }
216  }
217  return false;
218 }
219 
221 {
222  return currentStage() == Finished;
223 }
224 
226 {
227  if ( mJobIt != mLayerJobs.end() )
228  {
229  LayerRenderJob &job = *mJobIt;
230  return job.layerId;
231  }
232  else if ( mFlags & RenderLabelsByMapLayer && mPreparedStagedLabelJob )
233  {
234  if ( mLabelLayerIt != mLabelingLayers.end() )
235  return *mLabelLayerIt;
236  }
237  return QString();
238 }
239 
241 {
242  if ( mJobIt != mLayerJobs.end() )
243  return Symbology;
244  else if ( mLabelingEngineV2 && mFlags & RenderLabelsByMapLayer )
245  {
246  if ( !mPreparedStagedLabelJob )
247  return Labels;
248  if ( mLabelLayerIt != mLabelingLayers.end() )
249  return Labels;
250  }
251  else if ( mNextIsLabel && !mExportedLabels )
252  return Labels;
253 
254  return Finished;
255 }
QgsMapRendererStagedRenderJob(const QgsMapSettings &settings, Flags flags=nullptr)
Constructor for QgsMapRendererStagedRenderJob, using the given map settings.
QString currentLayerId()
Returns the ID of the current layer about to be rendered in the next render operation.
void cleanupJobs(LayerRenderJobs &jobs)
static Q_DECL_DEPRECATED void drawLabeling(const QgsMapSettings &settings, QgsRenderContext &renderContext, QgsLabelingEngine *labelingEngine2, QPainter *painter)
void preparePainter(QPainter *painter, const QColor &backgroundColor=Qt::transparent)
Prepares the given painter ready for a map render.
Default QgsLabelingEngine implementation, which completes the whole labeling operation (including lab...
Enable drawing of labels on top of the map.
void cancel() override
Stop the rendering job - does not return until the job has terminated.
The QgsMapSettings class contains configuration for rendering of the map.
LabelRenderJob prepareLabelingJob(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool canUseLabelCache=true)
Prepares a labeling job.
LayerRenderJobs prepareJobs(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool deferredPainterSet=false)
Creates a list of layer rendering jobs and prepares them for later render.
bool nextPart()
Iterates to the next part to render.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
Abstract base class for map renderer jobs which use custom painters.
RenderStage
Represents the stages of a rendering job.
QgsMapSettings mSettings
void cleanupLabelJob(LabelRenderJob &job)
Handles clean up tasks for a label job, including deletion of images and storing cached label results...
void start() override
Start the rendering job and immediately return.
QgsLabelingResults * takeLabelingResults() override
Gets pointer to internal labeling engine (in order to get access to the results). ...
bool renderCurrentPart(QPainter *painter)
Renders the current part of the map to the specified painter.
A QgsLabelingEngine implementation, which only calculates the labeling solution during its run() meth...
bool isFinished()
Returns true if the job is finished, and nothing remains to render.
Class that stores computed placement from labeling engine.
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
bool isActive() const override
Tell whether the rendering job is currently running in background.
RenderStage currentStage() const
Returns the current stage which will be rendered in the next render operation.
bool usedCachedLabels() const override
Returns true if the render job was able to use a cached labeling solution.
void waitForFinished() override
Block until the job has finished.
void cancelWithoutBlocking() override
Triggers cancellation of the rendering job without blocking.
Labels should be rendered in individual stages by map layer. This allows separation of labels belongi...