21 #include <QtConcurrentMap> 47 : mSettings( settings )
71 QHash<QgsMapLayer *, int> result;
75 result.insert( it.key(), it.value() );
90 QSet< QgsMapLayer * > labeledLayers;
134 static const double SPLIT_COORD = 180.0;
146 QgsDebugMsgLevel( QStringLiteral(
"\n0:%1 %2x%3\n1:%4\n2:%5 %6x%7 (w:%8 h:%9)" )
149 .arg( std::fabs( 1.0 - extent2.
width() / extent.
width() ) )
150 .arg( std::fabs( 1.0 - extent2.
height() / extent.
height() ) )
153 if ( std::fabs( 1.0 - extent2.
width() / extent.
width() ) < 0.5 &&
154 std::fabs( 1.0 - extent2.
height() / extent.
height() ) < 0.5 )
179 if ( ll.
x() > ur.
x() )
206 extent =
QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
214 QgsDebugMsg( QStringLiteral(
"Transform error caught" ) );
215 extent =
QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
216 r2 =
QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
224 LayerRenderJobs layerJobs;
233 Q_UNUSED( cacheValid )
234 QgsDebugMsgLevel( QStringLiteral(
"CACHE VALID: %1" ).arg( cacheValid ), 4 );
239 while ( li.hasPrevious() )
243 QgsDebugMsgLevel( QStringLiteral(
"layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 blendmode:%5 isValid:%6" )
260 QgsDebugMsgLevel( QStringLiteral(
"Layer not rendered because it is not within the defined visibility scale range" ), 3 );
271 reprojectToLayerExtent( ml, ct, r1, r2 );
276 mErrors.append( Error( ml->
id(), tr(
"There was a problem transforming the layer's extent. Layer skipped." ) ) );
285 bool requiresLabeling =
false;
293 layerJobs.append( LayerRenderJob() );
294 LayerRenderJob &job = layerJobs.last();
298 job.layerId = ml->
id();
299 job.renderingTime = -1;
303 job.context.setPainter( painter );
304 job.context.setLabelingEngine( labelingEngine2 );
305 job.context.setCoordinateTransform( ct );
306 job.context.setExtent( r1 );
308 if ( mFeatureFilterProvider )
309 job.context.setFeatureFilterProvider( mFeatureFilterProvider );
326 job.imageInitialized =
true;
329 job.renderer =
nullptr;
330 job.context.setPainter(
nullptr );
337 if (
mCache || ( !painter && !deferredPainterSet ) || needTemporaryImage( ml ) )
343 if ( mypFlattenedImage->isNull() )
346 delete mypFlattenedImage;
347 layerJobs.removeLast();
351 job.img = mypFlattenedImage;
352 QPainter *mypPainter =
new QPainter( job.img );
354 job.context.setPainter( mypPainter );
360 job.renderingTime = layerTime.elapsed();
370 job.context.setPainter( painter );
371 job.context.setLabelingEngine( labelingEngine2 );
373 job.context.setFeatureFilterProvider( mFeatureFilterProvider );
383 job.context.setPainter(
nullptr );
387 if ( canUseLabelCache && (
mCache || !painter ) )
390 QImage *mypFlattenedImage =
nullptr;
394 if ( mypFlattenedImage->isNull() )
397 delete mypFlattenedImage;
401 job.img = mypFlattenedImage;
412 for ( LayerRenderJobs::iterator it = jobs.begin(); it != jobs.end(); ++it )
414 LayerRenderJob &job = *it;
417 delete job.context.painter();
418 job.context.setPainter(
nullptr );
420 if (
mCache && !job.cached && !job.context.renderingStopped() && job.layer )
422 QgsDebugMsgLevel( QStringLiteral(
"caching image for %1" ).arg( job.layerId ), 2 );
432 const auto constErrors = job.renderer->errors();
433 for (
const QString &message : constErrors )
434 mErrors.append( Error( job.renderer->layerId(), message ) );
437 job.renderer =
nullptr;
451 if (
mCache && !job.cached && !job.context.renderingStopped() )
469 QPainter painter( &image );
472 for ( LayerRenderJobs::const_iterator it = jobs.constBegin(); it != jobs.constEnd(); ++it )
474 const LayerRenderJob &job = *it;
476 if ( job.layer && job.layer->customProperty( QStringLiteral(
"rendering/renderAboveLabels" ) ).toBool() )
479 if ( !job.imageInitialized )
482 painter.setCompositionMode( job.blendMode );
483 painter.setOpacity( job.opacity );
487 painter.drawImage( 0, 0, *job.img );
493 if ( labelJob.img && labelJob.complete )
495 painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
496 painter.setOpacity( 1.0 );
497 painter.drawImage( 0, 0, *labelJob.img );
501 for ( LayerRenderJobs::const_iterator it = jobs.constBegin(); it != jobs.constEnd(); ++it )
503 const LayerRenderJob &job = *it;
505 if ( !job.layer || !job.layer->customProperty( QStringLiteral(
"rendering/renderAboveLabels" ) ).toBool() )
508 if ( !job.imageInitialized )
511 painter.setCompositionMode( job.blendMode );
512 painter.setOpacity( job.opacity );
516 painter.drawImage( 0, 0, *job.img );
526 if ( !settings.
value( QStringLiteral(
"Map/logCanvasRefreshEvent" ),
false ).toBool() )
529 QMultiMap<int, QString> elapsed;
530 const auto constJobs =
jobs;
531 for (
const LayerRenderJob &job : constJobs )
532 elapsed.insert( job.renderingTime, job.layerId );
534 elapsed.insert( labelJob.renderingTime, tr(
"Labeling" ) );
536 QList<int> tt( elapsed.uniqueKeys() );
537 std::sort( tt.begin(), tt.end(), std::greater<int>() );
538 const auto constTt = tt;
539 for (
int t : constTt )
541 QgsMessageLog::logMessage( tr(
"%1 ms: %2" ).arg( t ).arg( QStringList( elapsed.values( t ) ).join( QStringLiteral(
", " ) ) ), tr(
"Rendering" ) );
546 bool QgsMapRendererJob::needTemporaryImage(
QgsMapLayer *ml )
548 switch ( ml->
type() )
559 ( ( vl->
blendMode() != QPainter::CompositionMode_SourceOver )
592 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
596 if ( labelingEngine2 )
598 labelingEngine2->
run( renderContext );
601 QgsDebugMsgLevel( QStringLiteral(
"Draw labeling took (seconds): %1" ).arg( t.elapsed() / 1000. ), 2 );
608 drawLabeling( renderContext, labelingEngine2, painter );
QList< QgsMapLayer *> dependentLayers(const QString &cacheKey) const
Returns a list of map layers on which an image in the cache depends.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
A rectangle specified with double values.
Base class for all map layer types.
const LayerRenderJobs & jobs() const
Abstract base class for map rendering implementations.
QgsMapLayerType type() const
Returns the type of the layer.
void setXMaximum(double x)
Set the maximum x value.
This class is a composition of two QSettings instances:
void cleanupJobs(LayerRenderJobs &jobs)
Restore overridden layer style on destruction.
QSize deviceOutputSize() const
Returns the device output size of the map canvas This is equivalent to the output size multiplicated ...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static Q_DECL_DEPRECATED void drawLabeling(const QgsMapSettings &settings, QgsRenderContext &renderContext, QgsLabelingEngine *labelingEngine2, QPainter *painter)
A class to represent a 2D point.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QColor backgroundColor() const
Gets the background color of the map.
Whether to make extra effort to update map image with partially rendered layers (better for interacti...
bool forceRasterRender() const
Returns whether the renderer must render as a raster.
void setCacheImage(const QString &cacheKey, const QImage &image, const QList< QgsMapLayer * > &dependentLayers=QList< QgsMapLayer * >())
Set the cached image for a particular cacheKey.
Errors errors() const
List of errors that happened during the rendering job - available when the rendering has been finishe...
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
QString toString(int precision=-1) const
Returns a string representation of the point (x, y) with a preset precision.
QList< QgsMapLayer * > layers() const
Gets list of layers for map rendering The layers are stored in the reverse order of how they are rend...
static const QString LABEL_CACHE_ID
QgsMapRendererCache ID string for cached label image.
bool isValid() const
Returns the status of the layer.
Enable layer opacity and blending effects.
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes takes output image size into accou...
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.
static bool staticWillUseLayer(QgsVectorLayer *layer)
called to find out whether the layer is used for labeling
QgsCoordinateTransform layerTransform(const QgsMapLayer *layer) const
Returns the coordinate transform from layer'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 isEditable() const FINAL
Returns true if the provider is in editing mode.
bool prepareLabelCache() const
Prepares the cache for storing the result of labeling.
LayerRenderJobs prepareJobs(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool deferredPainterSet=false)
Creates a list of layer rendering jobs and prepares them for later render.
virtual bool requiresAdvancedEffects() const =0
Returns true if drawing labels requires advanced effects like composition modes, which could prevent ...
QHash< QgsWeakMapLayerPointer, int > mPerLayerRenderingTime
Render time (in ms) per layer, by layer ID.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
#define QgsDebugMsgLevel(str, level)
void grow(double delta)
Grows the rectangle in place by the specified amount.
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
Returns the calculated map scale.
virtual void run(QgsRenderContext &context)=0
Runs the labeling job.
double width() const
Returns the width of the rectangle.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
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
double extentBuffer() const
Returns the buffer in map units to use around the visible extent for rendering symbols whose correspo...
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
QImage cacheImage(const QString &cacheKey) const
Returns the cached image for the specified cacheKey.
QgsFeatureRenderer * renderer()
Returns renderer.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
double minimumScale() const
Returns the minimum map scale (i.e.
double maximumScale() const
Returns the maximum map scale (i.e.
QHash< QgsMapLayer *, int > perLayerRenderingTime() const
Returns the render time (in ms) per layer.
float devicePixelRatio() const
Returns device pixel ratio Common values are 1 for normal-dpi displays and 2 for high-dpi "retina" di...
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
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).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
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.
Contains information about the context of a rendering operation.
QMap< QString, QString > layerStyleOverrides() const
Gets map of map layer style overrides (key: layer ID, value: style name) where a different style shou...
QList< QgsMapRendererJob::Error > Errors
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.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
virtual QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext)=0
Returns 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).
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.
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
Returns map settings with which this job was started.
QgsMapRendererCache * mCache
QSize outputSize() const
Returns the size of the resulting map image.
QgsMapRendererJob(const QgsMapSettings &settings)
void setXMinimum(double x)
Set the minimum x value.
QgsCoordinateReferenceSystem crs
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.