QGIS API Documentation  2.99.0-Master (5169e0d)
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.imageInitialized = true;
305  job.img = new QImage( mCache->cacheImage( ml->id() ) );
306  job.renderer = nullptr;
307  job.context.setPainter( nullptr );
308  continue;
309  }
310 
311  // If we are drawing with an alternative blending mode then we need to render to a separate image
312  // before compositing this on the map. This effectively flattens the layer and prevents
313  // blending occurring between objects on the layer
314  if ( mCache || !painter || needTemporaryImage( ml ) )
315  {
316  // Flattened image for drawing when a blending mode is set
317  QImage *mypFlattenedImage = nullptr;
318  mypFlattenedImage = new QImage( mSettings.outputSize().width(),
319  mSettings.outputSize().height(),
321  if ( mypFlattenedImage->isNull() )
322  {
323  mErrors.append( Error( ml->id(), tr( "Insufficient memory for image %1x%2" ).arg( mSettings.outputSize().width() ).arg( mSettings.outputSize().height() ) ) );
324  delete mypFlattenedImage;
325  layerJobs.removeLast();
326  continue;
327  }
328 
329  job.img = mypFlattenedImage;
330  QPainter *mypPainter = new QPainter( job.img );
331  mypPainter->setRenderHint( QPainter::Antialiasing, mSettings.testFlag( QgsMapSettings::Antialiasing ) );
332  job.context.setPainter( mypPainter );
333  }
334 
335  bool hasStyleOverride = mSettings.layerStyleOverrides().contains( ml->id() );
336  if ( hasStyleOverride )
337  ml->styleManager()->setOverrideStyle( mSettings.layerStyleOverrides().value( ml->id() ) );
338 
339  job.renderer = ml->createMapRenderer( job.context );
340 
341  if ( hasStyleOverride )
343 
344  if ( mRequestedGeomCacheForLayers.contains( ml->id() ) )
345  {
346  if ( QgsVectorLayerRenderer *vlr = dynamic_cast<QgsVectorLayerRenderer *>( job.renderer ) )
347  {
348  vlr->setGeometryCachePointer( &mGeometryCaches[ ml->id()] );
349  }
350  }
351 
352  } // while (li.hasPrevious())
353 
354  return layerJobs;
355 }
356 
357 LabelRenderJob QgsMapRendererJob::prepareLabelingJob( QPainter *painter, QgsLabelingEngine *labelingEngine2, bool canUseLabelCache )
358 {
359  LabelRenderJob job;
361  job.context.setPainter( painter );
362  job.context.setLabelingEngine( labelingEngine2 );
363  job.context.setExtent( mSettings.visibleExtent() );
364 
365  // if we can use the cache, let's do it and avoid rendering!
366  bool hasCache = canUseLabelCache && mCache && mCache->hasCacheImage( LABEL_CACHE_ID );
367  if ( hasCache )
368  {
369  job.cached = true;
370  job.complete = true;
371  job.img = new QImage( mCache->cacheImage( LABEL_CACHE_ID ) );
372  job.context.setPainter( nullptr );
373  }
374  else
375  {
376  if ( canUseLabelCache && ( mCache || !painter ) )
377  {
378  // Flattened image for drawing labels
379  QImage *mypFlattenedImage = nullptr;
380  mypFlattenedImage = new QImage( mSettings.outputSize().width(),
381  mSettings.outputSize().height(),
383  if ( mypFlattenedImage->isNull() )
384  {
385  mErrors.append( Error( QStringLiteral( "labels" ), tr( "Insufficient memory for label image %1x%2" ).arg( mSettings.outputSize().width() ).arg( mSettings.outputSize().height() ) ) );
386  delete mypFlattenedImage;
387  }
388  else
389  {
390  job.img = mypFlattenedImage;
391  }
392  }
393  }
394 
395  return job;
396 }
397 
398 
399 void QgsMapRendererJob::cleanupJobs( LayerRenderJobs &jobs )
400 {
401  for ( LayerRenderJobs::iterator it = jobs.begin(); it != jobs.end(); ++it )
402  {
403  LayerRenderJob &job = *it;
404  if ( job.img )
405  {
406  delete job.context.painter();
407  job.context.setPainter( nullptr );
408 
409  if ( mCache && !job.cached && !job.context.renderingStopped() && job.layer )
410  {
411  QgsDebugMsg( "caching image for " + ( job.layer ? job.layer->id() : QString() ) );
412  mCache->setCacheImage( job.layer->id(), *job.img, QList< QgsMapLayer * >() << job.layer );
413  }
414 
415  delete job.img;
416  job.img = nullptr;
417  }
418 
419  if ( job.renderer )
420  {
421  Q_FOREACH ( const QString &message, job.renderer->errors() )
422  mErrors.append( Error( job.renderer->layerId(), message ) );
423 
424  delete job.renderer;
425  job.renderer = nullptr;
426  }
427  }
428 
429 
430  jobs.clear();
431 
432  updateLayerGeometryCaches();
433 }
434 
435 void QgsMapRendererJob::cleanupLabelJob( LabelRenderJob &job )
436 {
437  if ( job.img )
438  {
439  if ( mCache && !job.cached && !job.context.renderingStopped() )
440  {
441  QgsDebugMsg( "caching label result image" );
442  mCache->setCacheImage( LABEL_CACHE_ID, *job.img, _qgis_listQPointerToRaw( job.participatingLayers ) );
443  }
444 
445  delete job.img;
446  job.img = nullptr;
447  }
448 }
449 
450 
451 QImage QgsMapRendererJob::composeImage( const QgsMapSettings &settings, const LayerRenderJobs &jobs, const LabelRenderJob &labelJob )
452 {
453  QImage image( settings.outputSize(), settings.outputImageFormat() );
454  image.fill( settings.backgroundColor().rgba() );
455 
456  QPainter painter( &image );
457 
458 
459  for ( LayerRenderJobs::const_iterator it = jobs.constBegin(); it != jobs.constEnd(); ++it )
460  {
461  const LayerRenderJob &job = *it;
462 
463  if ( job.layer && job.layer->customProperty( QStringLiteral( "rendering/renderAboveLabels" ) ).toBool() )
464  continue; // skip layer for now, it will be rendered after labels
465 
466  if ( !job.imageInitialized )
467  continue; // img not safe to compose
468 
469  painter.setCompositionMode( job.blendMode );
470  painter.setOpacity( job.opacity );
471 
472  Q_ASSERT( job.img );
473 
474  painter.drawImage( 0, 0, *job.img );
475  }
476 
477  // IMPORTANT - don't draw labelJob img before the label job is complete,
478  // as the image is uninitialized and full of garbage before the label job
479  // commences
480  if ( labelJob.img && labelJob.complete )
481  {
482  painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
483  painter.setOpacity( 1.0 );
484  painter.drawImage( 0, 0, *labelJob.img );
485  }
486 
487  // render any layers with the renderAboveLabels flag now
488  for ( LayerRenderJobs::const_iterator it = jobs.constBegin(); it != jobs.constEnd(); ++it )
489  {
490  const LayerRenderJob &job = *it;
491 
492  if ( !job.layer || !job.layer->customProperty( QStringLiteral( "rendering/renderAboveLabels" ) ).toBool() )
493  continue;
494 
495  if ( !job.imageInitialized )
496  continue; // img not safe to compose
497 
498  painter.setCompositionMode( job.blendMode );
499  painter.setOpacity( job.opacity );
500 
501  Q_ASSERT( job.img );
502 
503  painter.drawImage( 0, 0, *job.img );
504  }
505 
506  painter.end();
507  return image;
508 }
509 
510 void QgsMapRendererJob::logRenderingTime( const LayerRenderJobs &jobs, const LabelRenderJob &labelJob )
511 {
512  QgsSettings settings;
513  if ( !settings.value( QStringLiteral( "Map/logCanvasRefreshEvent" ), false ).toBool() )
514  return;
515 
516  QMultiMap<int, QString> elapsed;
517  Q_FOREACH ( const LayerRenderJob &job, jobs )
518  elapsed.insert( job.renderingTime, job.layer ? job.layer->id() : QString() );
519 
520  elapsed.insert( labelJob.renderingTime, tr( "Labeling" ) );
521 
522  QList<int> tt( elapsed.uniqueKeys() );
523  std::sort( tt.begin(), tt.end(), std::greater<int>() );
524  Q_FOREACH ( int t, tt )
525  {
526  QgsMessageLog::logMessage( tr( "%1 ms: %2" ).arg( t ).arg( QStringList( elapsed.values( t ) ).join( QStringLiteral( ", " ) ) ), tr( "Rendering" ) );
527  }
528  QgsMessageLog::logMessage( QStringLiteral( "---" ), tr( "Rendering" ) );
529 }
530 
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:38
Base class for all map layer types.
Definition: qgsmaplayer.h:53
const LayerRenderJobs & jobs() const
Abstract base class for map rendering implementations.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:70
This class is a composition of two QSettings instances:
Definition: qgssettings.h:54
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...
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
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
Returns the width of the rectangle.
Definition: qgsrectangle.h:118
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...
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
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:106
Implementation of threaded rendering for vector layers.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:91
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.
static void logMessage(const QString &message, const QString &tag=QString(), MessageLevel level=QgsMessageLog::WARNING)
add a message to the instance (and create it if necessary)
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.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
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.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:96
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
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:101
QString name
Definition: qgsmaplayer.h:57
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:65
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:125
double x
Definition: qgspoint.h:41