QGIS API Documentation  2.99.0-Master (40f86b2)
qgsmaprendererjob.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaprendererjob.cpp
3  --------------------------------------
4  Date : December 2013
5  Copyright : (C) 2013 by Martin Dobias
6  Email : wonder dot sk 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 
16 #include "qgsmaprendererjob.h"
17 
18 #include <QPainter>
19 #include <QTime>
20 #include <QTimer>
21 #include <QtConcurrentMap>
22 
23 #include "qgslogger.h"
24 #include "qgsrendercontext.h"
25 #include "qgsmaplayer.h"
26 #include "qgsproject.h"
27 #include "qgsmaplayerrenderer.h"
29 #include "qgsmaprenderercache.h"
30 #include "qgsmessagelog.h"
31 #include "qgspallabeling.h"
32 #include "qgsvectorlayerrenderer.h"
33 #include "qgsvectorlayer.h"
34 #include "qgscsexception.h"
35 #include "qgslabelingengine.h"
36 #include "qgsmaplayerlistutils.h"
37 #include "qgsvectorlayerlabeling.h"
38 #include "qgssettings.h"
39 
41 
42 const QString QgsMapRendererJob::LABEL_CACHE_ID = QStringLiteral( "_labels_" );
43 
45  : mSettings( settings )
46  , mCache( nullptr )
47  , mRenderingTime( 0 )
48  , mFeatureFilterProvider( nullptr )
49 {
50 }
51 
52 
54  : QgsMapRendererJob( settings )
55 {
56 }
57 
58 
60 {
61  return mErrors;
62 }
63 
65 {
66  mCache = cache;
67 }
68 
70 {
71  return mSettings;
72 }
73 
75 {
76  bool canCache = mCache;
77 
78  // calculate which layers will be labeled
79  QSet< QgsMapLayer * > labeledLayers;
80  Q_FOREACH ( const QgsMapLayer *ml, mSettings.layers() )
81  {
82  QgsVectorLayer *vl = const_cast< QgsVectorLayer * >( qobject_cast<const QgsVectorLayer *>( ml ) );
83  if ( vl && QgsPalLabeling::staticWillUseLayer( vl ) )
84  labeledLayers << vl;
85  if ( vl && vl->labeling() && vl->labeling()->requiresAdvancedEffects( vl ) )
86  {
87  canCache = false;
88  break;
89  }
90  }
91 
93  {
94  // we may need to clear label cache and re-register labeled features - check for that here
95 
96  // can we reuse the cached label solution?
97  bool canUseCache = canCache && mCache->dependentLayers( LABEL_CACHE_ID ).toSet() == labeledLayers;
98  if ( !canUseCache )
99  {
100  // no - participating layers have changed
102  }
103  }
104  return canCache;
105 }
106 
107 
108 bool QgsMapRendererJob::reprojectToLayerExtent( const QgsMapLayer *ml, const QgsCoordinateTransform &ct, QgsRectangle &extent, QgsRectangle &r2 )
109 {
110  bool split = false;
111 
112  try
113  {
114 #ifdef QGISDEBUG
115  // QgsLogger::debug<QgsRectangle>("Getting extent of canvas in layers CS. Canvas is ", extent, __FILE__, __FUNCTION__, __LINE__);
116 #endif
117  // Split the extent into two if the source CRS is
118  // geographic and the extent crosses the split in
119  // geographic coordinates (usually +/- 180 degrees,
120  // and is assumed to be so here), and draw each
121  // extent separately.
122  static const double SPLIT_COORD = 180.0;
123 
124  if ( ml->crs().isGeographic() )
125  {
126  if ( ml->type() == QgsMapLayer::VectorLayer && !ct.destinationCrs().isGeographic() )
127  {
128  // if we transform from a projected coordinate system check
129  // check if transforming back roughly returns the input
130  // extend - otherwise render the world.
133 
134  QgsDebugMsgLevel( QString( "\n0:%1 %2x%3\n1:%4\n2:%5 %6x%7 (w:%8 h:%9)" )
135  .arg( extent.toString() ).arg( extent.width() ).arg( extent.height() )
136  .arg( extent1.toString(), extent2.toString() ).arg( extent2.width() ).arg( extent2.height() )
137  .arg( fabs( 1.0 - extent2.width() / extent.width() ) )
138  .arg( fabs( 1.0 - extent2.height() / extent.height() ) )
139  , 3 );
140 
141  if ( fabs( 1.0 - extent2.width() / extent.width() ) < 0.5 &&
142  fabs( 1.0 - extent2.height() / extent.height() ) < 0.5 )
143  {
144  extent = extent1;
145  }
146  else
147  {
148  extent = QgsRectangle( -180.0, -90.0, 180.0, 90.0 );
149  }
150  }
151  else
152  {
153  // Note: ll = lower left point
154  QgsPoint ll = ct.transform( extent.xMinimum(), extent.yMinimum(),
156 
157  // and ur = upper right point
158  QgsPoint ur = ct.transform( extent.xMaximum(), extent.yMaximum(),
160 
161  QgsDebugMsg( QString( "in:%1 (ll:%2 ur:%3)" ).arg( extent.toString(), ll.toString(), ur.toString() ) );
162 
164 
165  QgsDebugMsg( QString( "out:%1 (w:%2 h:%3)" ).arg( extent.toString() ).arg( extent.width() ).arg( extent.height() ) );
166 
167  if ( ll.x() > ur.x() )
168  {
169  // the coordinates projected in reverse order than what one would expect.
170  // we are probably looking at an area that includes longitude of 180 degrees.
171  // we need to take into account coordinates from two intervals: (-180,x1) and (x2,180)
172  // so let's use (-180,180). This hopefully does not add too much overhead. It is
173  // more straightforward than rendering with two separate extents and more consistent
174  // for rendering, labeling and caching as everything is rendered just in one go
175  extent.setXMinimum( -SPLIT_COORD );
176  extent.setXMaximum( SPLIT_COORD );
177  }
178  }
179 
180  // TODO: the above rule still does not help if using a projection that covers the whole
181  // world. E.g. with EPSG:3857 the longitude spectrum -180 to +180 is mapped to approx.
182  // -2e7 to +2e7. Converting extent from -5e7 to +5e7 is transformed as -90 to +90,
183  // but in fact the extent should cover the whole world.
184  }
185  else // can't cross 180
186  {
187  if ( ct.destinationCrs().isGeographic() &&
188  ( extent.xMinimum() <= -180 || extent.xMaximum() >= 180 ||
189  extent.yMinimum() <= -90 || extent.yMaximum() >= 90 ) )
190  // Use unlimited rectangle because otherwise we may end up transforming wrong coordinates.
191  // E.g. longitude -200 to +160 would be understood as +40 to +160 due to periodicity.
192  // We could try to clamp coords to (-180,180) for lon resp. (-90,90) for lat,
193  // but this seems like a safer choice.
194  extent = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
195  else
197  }
198  }
199  catch ( QgsCsException &cse )
200  {
201  Q_UNUSED( cse );
202  QgsDebugMsg( "Transform error caught" );
203  extent = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
204  r2 = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
205  }
206 
207  return split;
208 }
209 
210 
211 
212 LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter *painter, QgsLabelingEngine *labelingEngine2 )
213 {
214  LayerRenderJobs layerJobs;
215 
216  // render all layers in the stack, starting at the base
217  QListIterator<QgsMapLayer *> li( mSettings.layers() );
218  li.toBack();
219 
220  if ( mCache )
221  {
222  bool cacheValid = mCache->init( mSettings.visibleExtent(), mSettings.scale() );
223  Q_UNUSED( cacheValid );
224  QgsDebugMsg( QString( "CACHE VALID: %1" ).arg( cacheValid ) );
225  }
226 
227  bool requiresLabelRedraw = !( mCache && mCache->hasCacheImage( LABEL_CACHE_ID ) );
228 
229  mGeometryCaches.clear();
230 
231  while ( li.hasPrevious() )
232  {
233  QgsMapLayer *ml = li.previous();
234 
235  QgsDebugMsgLevel( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 blendmode:%5" )
236  .arg( ml->name() )
237  .arg( ml->minimumScale() )
238  .arg( ml->maximumScale() )
239  .arg( ml->hasScaleBasedVisibility() )
240  .arg( ml->blendMode() )
241  , 3 );
242 
243  if ( !ml->isInScaleRange( mSettings.scale() ) ) //|| mOverview )
244  {
245  QgsDebugMsgLevel( "Layer not rendered because it is not within the defined visibility scale range", 3 );
246  continue;
247  }
248 
251 
252  ct = mSettings.layerTransform( ml );
253  if ( ct.isValid() )
254  {
255  reprojectToLayerExtent( ml, ct, r1, r2 );
256  }
257  QgsDebugMsgLevel( "extent: " + r1.toString(), 3 );
258  if ( !r1.isFinite() || !r2.isFinite() )
259  {
260  mErrors.append( Error( ml->id(), tr( "There was a problem transforming the layer's extent. Layer skipped." ) ) );
261  continue;
262  }
263 
264  // Force render of layers that are being edited
265  // or if there's a labeling engine that needs the layer to register features
266  if ( mCache && ml->type() == QgsMapLayer::VectorLayer )
267  {
268  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
269  bool requiresLabeling = false;
270  requiresLabeling = ( labelingEngine2 && QgsPalLabeling::staticWillUseLayer( vl ) ) && requiresLabelRedraw;
271  if ( vl->isEditable() || requiresLabeling )
272  {
273  mCache->clearCacheImage( ml->id() );
274  }
275  }
276 
277  layerJobs.append( LayerRenderJob() );
278  LayerRenderJob &job = layerJobs.last();
279  job.cached = false;
280  job.img = nullptr;
281  job.blendMode = ml->blendMode();
282  job.opacity = 1.0;
283  if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml ) )
284  {
285  job.opacity = 1.0 - vl->layerTransparency() / 100.0;
286  }
287  job.layer = ml;
288  job.renderingTime = -1;
289 
291  job.context.expressionContext().appendScope( QgsExpressionContextUtils::layerScope( ml ) );
292  job.context.setPainter( painter );
293  job.context.setLabelingEngine( labelingEngine2 );
294  job.context.setCoordinateTransform( ct );
295  job.context.setExtent( r1 );
296 
297  if ( mFeatureFilterProvider )
298  job.context.setFeatureFilterProvider( mFeatureFilterProvider );
299 
300  // if we can use the cache, let's do it and avoid rendering!
301  if ( mCache && mCache->hasCacheImage( ml->id() ) )
302  {
303  job.cached = true;
304  job.img = new QImage( mCache->cacheImage( ml->id() ) );
305  job.renderer = nullptr;
306  job.context.setPainter( nullptr );
307  continue;
308  }
309 
310  // If we are drawing with an alternative blending mode then we need to render to a separate image
311  // before compositing this on the map. This effectively flattens the layer and prevents
312  // blending occurring between objects on the layer
313  if ( mCache || !painter || needTemporaryImage( ml ) )
314  {
315  // Flattened image for drawing when a blending mode is set
316  QImage *mypFlattenedImage = nullptr;
317  mypFlattenedImage = new QImage( mSettings.outputSize().width(),
318  mSettings.outputSize().height(),
320  if ( mypFlattenedImage->isNull() )
321  {
322  mErrors.append( Error( ml->id(), tr( "Insufficient memory for image %1x%2" ).arg( mSettings.outputSize().width() ).arg( mSettings.outputSize().height() ) ) );
323  delete mypFlattenedImage;
324  layerJobs.removeLast();
325  continue;
326  }
327 
328  job.img = mypFlattenedImage;
329  QPainter *mypPainter = new QPainter( job.img );
330  mypPainter->setRenderHint( QPainter::Antialiasing, mSettings.testFlag( QgsMapSettings::Antialiasing ) );
331  job.context.setPainter( mypPainter );
332  }
333 
334  bool hasStyleOverride = mSettings.layerStyleOverrides().contains( ml->id() );
335  if ( hasStyleOverride )
336  ml->styleManager()->setOverrideStyle( mSettings.layerStyleOverrides().value( ml->id() ) );
337 
338  job.renderer = ml->createMapRenderer( job.context );
339 
340  if ( hasStyleOverride )
342 
343  if ( mRequestedGeomCacheForLayers.contains( ml->id() ) )
344  {
345  if ( QgsVectorLayerRenderer *vlr = dynamic_cast<QgsVectorLayerRenderer *>( job.renderer ) )
346  {
347  vlr->setGeometryCachePointer( &mGeometryCaches[ ml->id()] );
348  }
349  }
350 
351  } // while (li.hasPrevious())
352 
353  return layerJobs;
354 }
355 
356 LabelRenderJob QgsMapRendererJob::prepareLabelingJob( QPainter *painter, QgsLabelingEngine *labelingEngine2, bool canUseLabelCache )
357 {
358  LabelRenderJob job;
360  job.context.setPainter( painter );
361  job.context.setLabelingEngine( labelingEngine2 );
362  job.context.setExtent( mSettings.visibleExtent() );
363 
364  // if we can use the cache, let's do it and avoid rendering!
365  bool hasCache = canUseLabelCache && mCache && mCache->hasCacheImage( LABEL_CACHE_ID );
366  if ( hasCache )
367  {
368  job.cached = true;
369  job.complete = true;
370  job.img = new QImage( mCache->cacheImage( LABEL_CACHE_ID ) );
371  job.context.setPainter( nullptr );
372  }
373  else
374  {
375  if ( canUseLabelCache && ( mCache || !painter ) )
376  {
377  // Flattened image for drawing labels
378  QImage *mypFlattenedImage = nullptr;
379  mypFlattenedImage = new QImage( mSettings.outputSize().width(),
380  mSettings.outputSize().height(),
382  if ( mypFlattenedImage->isNull() )
383  {
384  mErrors.append( Error( QStringLiteral( "labels" ), tr( "Insufficient memory for label image %1x%2" ).arg( mSettings.outputSize().width() ).arg( mSettings.outputSize().height() ) ) );
385  delete mypFlattenedImage;
386  }
387  else
388  {
389  job.img = mypFlattenedImage;
390  }
391  }
392  }
393 
394  return job;
395 }
396 
397 
398 void QgsMapRendererJob::cleanupJobs( LayerRenderJobs &jobs )
399 {
400  for ( LayerRenderJobs::iterator it = jobs.begin(); it != jobs.end(); ++it )
401  {
402  LayerRenderJob &job = *it;
403  if ( job.img )
404  {
405  delete job.context.painter();
406  job.context.setPainter( nullptr );
407 
408  if ( mCache && !job.cached && !job.context.renderingStopped() && job.layer )
409  {
410  QgsDebugMsg( "caching image for " + ( job.layer ? job.layer->id() : QString() ) );
411  mCache->setCacheImage( job.layer->id(), *job.img, QList< QgsMapLayer * >() << job.layer );
412  }
413 
414  delete job.img;
415  job.img = nullptr;
416  }
417 
418  if ( job.renderer )
419  {
420  Q_FOREACH ( const QString &message, job.renderer->errors() )
421  mErrors.append( Error( job.renderer->layerId(), message ) );
422 
423  delete job.renderer;
424  job.renderer = nullptr;
425  }
426  }
427 
428 
429  jobs.clear();
430 
431  updateLayerGeometryCaches();
432 }
433 
434 void QgsMapRendererJob::cleanupLabelJob( LabelRenderJob &job )
435 {
436  if ( job.img )
437  {
438  if ( mCache && !job.cached && !job.context.renderingStopped() )
439  {
440  QgsDebugMsg( "caching label result image" );
441  mCache->setCacheImage( LABEL_CACHE_ID, *job.img, _qgis_listQPointerToRaw( job.participatingLayers ) );
442  }
443 
444  delete job.img;
445  job.img = nullptr;
446  }
447 }
448 
449 
450 QImage QgsMapRendererJob::composeImage( const QgsMapSettings &settings, const LayerRenderJobs &jobs, const LabelRenderJob &labelJob )
451 {
452  QImage image( settings.outputSize(), settings.outputImageFormat() );
453  image.fill( settings.backgroundColor().rgba() );
454 
455  QPainter painter( &image );
456 
457 
458  for ( LayerRenderJobs::const_iterator it = jobs.constBegin(); it != jobs.constEnd(); ++it )
459  {
460  const LayerRenderJob &job = *it;
461 
462  if ( job.layer && job.layer->customProperty( QStringLiteral( "rendering/renderAboveLabels" ) ).toBool() )
463  continue; // skip layer for now, it will be rendered after labels
464 
465  painter.setCompositionMode( job.blendMode );
466  painter.setOpacity( job.opacity );
467 
468  Q_ASSERT( job.img );
469 
470  painter.drawImage( 0, 0, *job.img );
471  }
472 
473  // IMPORTANT - don't draw labelJob img before the label job is complete,
474  // as the image is uninitialized and full of garbage before the label job
475  // commences
476  if ( labelJob.img && labelJob.complete )
477  {
478  painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
479  painter.setOpacity( 1.0 );
480  painter.drawImage( 0, 0, *labelJob.img );
481  }
482 
483  // render any layers with the renderAboveLabels flag now
484  for ( LayerRenderJobs::const_iterator it = jobs.constBegin(); it != jobs.constEnd(); ++it )
485  {
486  const LayerRenderJob &job = *it;
487 
488  if ( !job.layer || !job.layer->customProperty( QStringLiteral( "rendering/renderAboveLabels" ) ).toBool() )
489  continue;
490 
491  painter.setCompositionMode( job.blendMode );
492  painter.setOpacity( job.opacity );
493 
494  Q_ASSERT( job.img );
495 
496  painter.drawImage( 0, 0, *job.img );
497  }
498 
499  painter.end();
500  return image;
501 }
502 
503 void QgsMapRendererJob::logRenderingTime( const LayerRenderJobs &jobs, const LabelRenderJob &labelJob )
504 {
505  QgsSettings settings;
506  if ( !settings.value( QStringLiteral( "Map/logCanvasRefreshEvent" ), false ).toBool() )
507  return;
508 
509  QMultiMap<int, QString> elapsed;
510  Q_FOREACH ( const LayerRenderJob &job, jobs )
511  elapsed.insert( job.renderingTime, job.layer ? job.layer->id() : QString() );
512 
513  elapsed.insert( labelJob.renderingTime, tr( "Labeling" ) );
514 
515  QList<int> tt( elapsed.uniqueKeys() );
516  std::sort( tt.begin(), tt.end(), std::greater<int>() );
517  Q_FOREACH ( int t, tt )
518  {
519  QgsMessageLog::logMessage( tr( "%1 ms: %2" ).arg( t ).arg( QStringList( elapsed.values( t ) ).join( QStringLiteral( ", " ) ) ), tr( "Rendering" ) );
520  }
521  QgsMessageLog::logMessage( QStringLiteral( "---" ), tr( "Rendering" ) );
522 }
523 
bool restoreOverrideStyle()
Restore the original store after a call to setOverrideStyle()
QList< QgsMapLayer *> dependentLayers(const QString &cacheKey) const
Returns a list of map layers on which an image in the cache depends.
A rectangle specified with double values.
Definition: qgsrectangle.h:36
Base class for all map layer types.
Definition: qgsmaplayer.h:52
const LayerRenderJobs & jobs() const
Abstract base class for map rendering implementations.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:180
This class is a composition of two QSettings instances:
Definition: qgssettings.h:51
void cleanupJobs(LayerRenderJobs &jobs)
QList< Error > Errors
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
QColor backgroundColor() const
Get the background color of the map.
void setCacheImage(const QString &cacheKey, const QImage &image, const QList< QgsMapLayer * > &dependentLayers=QList< QgsMapLayer * >())
Set the cached image for a particular cacheKey.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, TransformDirection direction=ForwardTransform, const bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
Errors errors() const
List of errors that happened during the rendering job - available when the rendering has been finishe...
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system, which the transform will transform coordinates t...
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
QList< QgsMapLayer * > layers() const
Get list of layers for map rendering The layers are stored in the reverse order of how they are rende...
static const QString LABEL_CACHE_ID
QgsMapRendererCache ID string for cached label image.
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
QgsMapLayer::LayerType type() const
Returns the type of the layer.
Definition: qgsmaplayer.cpp:96
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
void setCache(QgsMapRendererCache *cache)
Assign a cache to be used for reading and storing rendered images of individual layers.
The QgsMapSettings class contains configuration for rendering of the map.
QgsMapLayerStyleManager * styleManager() const
Get access to the layer&#39;s style manager.
static bool staticWillUseLayer(QgsVectorLayer *layer)
called to find out whether the layer is used for labeling
QgsCoordinateTransform layerTransform(const QgsMapLayer *layer) const
Return coordinate transform from layer&#39;s CRS to destination CRS.
static QImage composeImage(const QgsMapSettings &settings, const LayerRenderJobs &jobs, const LabelRenderJob &labelJob)
LabelRenderJob prepareLabelingJob(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool canUseLabelCache=true)
Prepares a labeling job.
bool prepareLabelCache() const
Prepares the cache for storing the result of labeling.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
QgsPoint transform(const QgsPoint &point, TransformDirection direction=ForwardTransform) const
Transform the point from the source CRS to the destination CRS.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:37
bool init(const QgsRectangle &extent, double scale)
Initialize cache: set new parameters and clears the cache if any parameters have changed since last i...
double scale() const
Return the calculated scale of the map.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:215
Enable anti-aliasing for map rendering.
QString toString(int precision=16) const
returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
QImage::Format outputImageFormat() const
format of internal QImage, default QImage::Format_ARGB32_Premultiplied
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
int layerTransparency() const
Returns the current transparency for the vector layer.
QImage cacheImage(const QString &cacheKey) const
Returns the cached image for the specified cacheKey.
bool isGeographic() const
Returns whether the CRS is a geographic CRS (using lat/lon coordinates)
const QgsAbstractVectorLayerLabeling * labeling() const
Access to labeling configuration.
double minimumScale() const
Returns the minimum scale denominator at which the layer is visible.
double maximumScale() const
Returns the maximum scale denominator at which the layer is visible.
virtual bool requiresAdvancedEffects(QgsVectorLayer *layer) const =0
Returns true if drawing labels requires advanced effects like composition modes, which could prevent ...
A class to represent a point.
Definition: qgspoint.h:37
QString toString() const
String representation of the point (x,y)
Definition: qgspoint.cpp:45
QgsMapSettings mSettings
bool isFinite() const
Returns true if the rectangle has finite boundaries.
void cleanupLabelJob(LabelRenderJob &job)
Handles clean up tasks for a label job, including deletion of images and storing cached label results...
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:210
Implementation of threaded rendering for vector layers.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:195
bool hasCacheImage(const QString &cacheKey) const
Returns true if the cache contains an image with the specified cacheKey.
The QgsLabelingEngine class provides map labeling functionality.
QMap< QString, QString > layerStyleOverrides() const
Get map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
LayerRenderJobs prepareJobs(QPainter *painter, QgsLabelingEngine *labelingEngine2)
Transform from destination to source CRS.
void logRenderingTime(const LayerRenderJobs &jobs, const LabelRenderJob &labelJob)
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
void clearCacheImage(const QString &cacheKey)
Removes an image from the cache with matching cacheKey.
Class for doing transforms between two map coordinate systems.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=Section::NoSection) const
Returns the value for setting key.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:200
virtual QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext)=0
Return new instance of QgsMapLayerRenderer that will be used for rendering of given context...
QgsMapRendererQImageJob(const QgsMapSettings &settings)
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:205
QString name
Read property of QString layerName.
Definition: qgsmaplayer.h:56
Transform from source to destination CRS.
This class is responsible for keeping cache of rendered images resulting from a map rendering job...
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
bool setOverrideStyle(const QString &styleDef)
Temporarily apply a different style to the layer.
Custom exception class for Coordinate Reference System related exceptions.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Represents a vector layer which manages a vector based data sets.
const QgsMapSettings & mapSettings() const
Return map settings with which this job was started.
QgsMapRendererCache * mCache
QSize outputSize() const
Return the size of the resulting map image.
QgsMapRendererJob(const QgsMapSettings &settings)
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:175
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:220
double x
Definition: qgspoint.h:41