19#include <QElapsedTimer>
21#include <QtConcurrentMap>
61LayerRenderJob &LayerRenderJob::operator=( LayerRenderJob &&other )
63 mContext = std::move( other.mContext );
68 renderer = other.renderer;
69 other.renderer =
nullptr;
71 imageInitialized = other.imageInitialized;
72 blendMode = other.blendMode;
73 opacity = other.opacity;
74 cached = other.cached;
76 renderAboveLabels = other.renderAboveLabels;
77 completed = other.completed;
78 renderingTime = other.renderingTime;
79 estimatedRenderingTime = other.estimatedRenderingTime ;
80 errors = other.errors;
81 layerId = other.layerId;
83 maskPaintDevice = std::move( other.maskPaintDevice );
85 firstPassJob = other.firstPassJob;
86 other.firstPassJob =
nullptr;
88 picture = std::move( other.picture );
90 maskJobs = other.maskJobs;
92 maskRequiresLayerRasterization = other.maskRequiresLayerRasterization;
94 elevationMap = other.elevationMap;
95 maskPainter = std::move( other.maskPainter );
100LayerRenderJob::LayerRenderJob( LayerRenderJob &&other )
101 : imageInitialized( other.imageInitialized )
102 , blendMode( other.blendMode )
103 , opacity( other.opacity )
104 , cached( other.cached )
105 , renderAboveLabels( other.renderAboveLabels )
106 , layer( other.layer )
107 , completed( other.completed )
108 , renderingTime( other.renderingTime )
109 , estimatedRenderingTime( other.estimatedRenderingTime )
110 , errors( other.errors )
111 , layerId( other.layerId )
112 , maskPainter( nullptr )
113 , maskRequiresLayerRasterization( other.maskRequiresLayerRasterization )
114 , maskJobs( other.maskJobs )
116 mContext = std::move( other.mContext );
121 renderer = other.renderer;
122 other.renderer =
nullptr;
124 elevationMap = other.elevationMap;
125 other.elevationMap =
nullptr;
127 maskPaintDevice = std::move( other.maskPaintDevice );
129 firstPassJob = other.firstPassJob;
130 other.firstPassJob =
nullptr;
132 picture = std::move( other.picture );
135bool LayerRenderJob::imageCanBeComposed()
const
137 if ( imageInitialized )
141 return renderer->isReadyToCompose();
155 : mSettings( settings )
201 return mLabelingEngineFeedback;
206 QHash<QgsMapLayer *, int> result;
209 if (
auto &&lKey = it.key() )
210 result.insert( lKey, it.value() );
230 QSet< QgsMapLayer * > labeledLayers;
237 switch ( ml->type() )
239 case Qgis::LayerType::Vector:
249 case Qgis::LayerType::VectorTile:
255 case Qgis::LayerType::Raster:
256 case Qgis::LayerType::Annotation:
257 case Qgis::LayerType::Plugin:
258 case Qgis::LayerType::Mesh:
259 case Qgis::LayerType::PointCloud:
260 case Qgis::LayerType::Group:
275 bool canUseCache = canCache && QSet< QgsMapLayer * >( labelDependentLayers.begin(), labelDependentLayers.end() ) == labeledLayers;
304 static const double SPLIT_COORD = 180.0;
316 QgsDebugMsgLevel( QStringLiteral(
"\n0:%1 %2x%3\n1:%4\n2:%5 %6x%7 (w:%8 h:%9)" )
319 .arg( std::fabs( 1.0 - extent2.
width() / extent.
width() ) )
320 .arg( std::fabs( 1.0 - extent2.
height() / extent.
height() ) )
342 Qgis::TransformDirection::Reverse );
346 Qgis::TransformDirection::Reverse );
354 if ( ll.
x() > ur.
x() )
383 extent =
QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
393 extent =
QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
394 r2 =
QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
401QImage *QgsMapRendererJob::allocateImage( QString layerId )
408 if ( image->isNull() )
417QgsElevationMap *QgsMapRendererJob::allocateElevationMap( QString layerId )
420 if ( !elevationMap->isValid() )
425 return elevationMap.release();
428QPainter *QgsMapRendererJob::allocateImageAndPainter( QString layerId, QImage *&image,
const QgsRenderContext *context )
430 QPainter *painter =
nullptr;
431 image = allocateImage( layerId );
434 painter =
new QPainter( image );
440QgsMapRendererJob::PictureAndPainter QgsMapRendererJob::allocatePictureAndPainter(
const QgsRenderContext *context )
442 std::unique_ptr<QPicture> picture = std::make_unique<QPicture>();
443 QPainter *painter =
new QPainter( picture.get() );
445 return { std::move( picture ), painter };
450 std::vector< LayerRenderJob > layerJobs;
459 Q_UNUSED( cacheValid )
460 QgsDebugMsgLevel( QStringLiteral(
"CACHE VALID: %1" ).arg( cacheValid ), 4 );
465 while ( li.hasPrevious() )
469 QgsDebugMsgLevel( QStringLiteral(
"layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 blendmode:%5 isValid:%6" )
486 QgsDebugMsgLevel( QStringLiteral(
"Layer not rendered because it is not within the defined visibility scale range" ), 3 );
492 QgsDebugMsgLevel( QStringLiteral(
"Layer not rendered because it is not visible within the map's time range" ), 3 );
498 QgsDebugMsgLevel( QStringLiteral(
"Layer not rendered because it is not visible within the map's z range" ), 3 );
507 bool haveExtentInLayerCrs =
true;
510 haveExtentInLayerCrs = reprojectToLayerExtent( ml, ct, r1, r2 );
515 mErrors.append( Error( ml->
id(), tr(
"There was a problem transforming the layer's extent. Layer skipped." ) ) );
526 if ( ( vl && vl->
isEditable() ) || requiresLabeling )
532 layerJobs.emplace_back( LayerRenderJob() );
533 LayerRenderJob &job = layerJobs.back();
535 job.layerId = ml->
id();
536 job.renderAboveLabels = ml->
customProperty( QStringLiteral(
"rendering/renderAboveLabels" ) ).toBool();
540 if ( !ml->
customProperty( QStringLiteral(
"_noset_layer_expression_context" ) ).toBool() )
542 job.context()->setPainter( painter );
543 job.context()->setLabelingEngine( labelingEngine2 );
544 job.context()->setLabelSink(
labelSink() );
545 job.context()->setCoordinateTransform( ct );
546 job.context()->setExtent( r1 );
552 if ( mFeatureFilterProvider )
553 job.context()->setFeatureFilterProvider( mFeatureFilterProvider );
561 if ( ml->
type() == Qgis::LayerType::Raster )
586 job.imageInitialized =
true;
594 job.renderer =
nullptr;
595 job.context()->setPainter(
nullptr );
600 QElapsedTimer layerTime;
606 job.context()->setFeedback( job.renderer->feedback() );
612 if (
mCache || ( !painter && !deferredPainterSet ) || ( job.renderer && job.renderer->forceRasterRender() ) )
615 job.context()->setPainter( allocateImageAndPainter( ml->
id(), job.img, job.context() ) );
619 job.renderer =
nullptr;
620 layerJobs.pop_back();
629 job.elevationMap = allocateElevationMap( ml->
id() );
630 job.context()->setElevationMap( job.elevationMap );
633 job.renderingTime = layerTime.elapsed();
641 std::vector< LayerRenderJob > secondPassJobs;
644 QHash<QString, LayerRenderJob *> layerJobMapping;
647 QMap<QString, bool> maskLayerHasEffects;
648 QMap<int, bool> labelHasEffects;
656 MaskSource(
const QString &layerId_,
const QString &labelRuleId_,
int labelMaskId_,
bool hasEffects_ ):
657 layerId( layerId_ ), labelRuleId( labelRuleId_ ), labelMaskId( labelMaskId_ ), hasEffects( hasEffects_ ) {}
662 QHash<QString, QPair<QSet<QString>, QList<MaskSource>>> maskedSymbolLayers;
669 for ( LayerRenderJob &job : firstPassJobs )
671 layerJobMapping[job.layerId] = &job;
676 for ( LayerRenderJob &job : firstPassJobs )
683 auto collectMasks = [&](
QgsMaskedLayers * masks, QString sourceLayerId, QString ruleId = QString(),
int labelMaskId = -1 )
685 bool hasEffects =
false;
686 for (
auto it = masks->begin(); it != masks->end(); ++it )
688 auto lit = maskedSymbolLayers.find( it.key() );
689 if ( lit == maskedSymbolLayers.end() )
691 maskedSymbolLayers[it.key()] = qMakePair( it.value().symbolLayerIds, QList<MaskSource>() << MaskSource( sourceLayerId, ruleId, labelMaskId, it.value().hasEffects ) );
695 if ( lit->first != it.value().symbolLayerIds )
697 QgsLogger::warning( QStringLiteral(
"Layer %1 : Different sets of symbol layers are masked by different sources ! Only one (arbitrary) set will be retained !" ).arg( it.key() ) );
700 lit->second.push_back( MaskSource( sourceLayerId, ruleId, labelMaskId, hasEffects ) );
702 hasEffects |= it.value().hasEffects;
704 if ( ! masks->isEmpty() && labelMaskId == -1 )
705 maskLayerHasEffects[ sourceLayerId ] = hasEffects;
710 for (
auto it = labelMasks.begin(); it != labelMasks.end(); it++ )
712 QString labelRule = it.key();
718 for (
auto mit = masks.begin(); mit != masks.end(); mit++ )
720 const QString sourceLayerId = mit.key();
722 if ( !layerJobMapping.contains( sourceLayerId ) )
725 usableMasks.insert( sourceLayerId, mit.value() );
728 if ( usableMasks.empty() )
732 QSet<QgsSymbolLayerReference> slRefs;
733 bool hasEffects =
false;
734 for (
auto mit = usableMasks.begin(); mit != usableMasks.end(); mit++ )
736 const QString sourceLayerId = mit.key();
738 if ( !layerJobMapping.contains( sourceLayerId ) )
741 for (
const QString &symbolLayerId : mit.value().symbolLayerIds )
744 hasEffects |= mit.value().hasEffects;
747 int labelMaskId = labelJob.maskIdProvider.insertLabelLayer( vl->
id(), it.key(), slRefs );
748 labelHasEffects[ labelMaskId ] = hasEffects;
751 collectMasks( &usableMasks, vl->
id(), labelRule, labelMaskId );
756 collectMasks( &symbolLayerMasks, vl->
id() );
759 if ( maskedSymbolLayers.isEmpty() )
760 return secondPassJobs;
763 for (
int maskId = 0; maskId < labelJob.maskIdProvider.size(); maskId++ )
765 QPaintDevice *maskPaintDevice =
nullptr;
766 QPainter *maskPainter =
nullptr;
767 if ( forceVector && !labelHasEffects[ maskId ] )
771 maskPainter =
new QPainter( maskPaintDevice );
776 QImage *maskImage =
nullptr;
777 maskPainter = allocateImageAndPainter( QStringLiteral(
"label mask" ), maskImage, &labelJob.context );
778 maskImage->fill( 0 );
779 maskPaintDevice = maskImage;
782 labelJob.context.setMaskPainter( maskPainter, maskId );
783 labelJob.maskPainters.push_back( std::unique_ptr<QPainter>( maskPainter ) );
784 labelJob.maskPaintDevices.push_back( std::unique_ptr<QPaintDevice>( maskPaintDevice ) );
786 labelJob.context.setMaskIdProvider( &labelJob.maskIdProvider );
797 if ( !labelJob.img && !forceVector )
799 labelJob.img = allocateImage( QStringLiteral(
"labels" ) );
801 else if ( !labelJob.picture && forceVector )
803 labelJob.picture.reset(
new QPicture() );
807 for ( LayerRenderJob &job : firstPassJobs )
809 job.maskRequiresLayerRasterization =
false;
811 auto it = maskedSymbolLayers.find( job.layerId );
812 if ( it != maskedSymbolLayers.end() )
814 const QList<MaskSource> &sourceList = it->second;
815 for (
const MaskSource &source : sourceList )
817 job.maskRequiresLayerRasterization |= source.hasEffects;
822 const bool isRasterRendering = !forceVector || job.maskRequiresLayerRasterization || ( job.renderer && job.renderer->forceRasterRender() );
823 if ( isRasterRendering && !job.img )
825 job.context()->setPainter( allocateImageAndPainter( job.layerId, job.img, job.context() ) );
827 else if ( !isRasterRendering && !job.picture )
829 PictureAndPainter pictureAndPainter = allocatePictureAndPainter( job.context() );
830 job.picture = std::move( pictureAndPainter.first );
831 job.context()->setPainter( pictureAndPainter.second );
834 job.renderer = job.layer->createMapRenderer( *( job.context() ) );
838 if ( maskLayerHasEffects.contains( job.layerId ) )
840 QPaintDevice *maskPaintDevice =
nullptr;
841 QPainter *maskPainter =
nullptr;
842 if ( forceVector && !maskLayerHasEffects[ job.layerId ] )
846 maskPainter =
new QPainter( maskPaintDevice );
851 QImage *maskImage =
nullptr;
852 maskPainter = allocateImageAndPainter( job.layerId, maskImage, job.context() );
853 maskImage->fill( 0 );
854 maskPaintDevice = maskImage;
857 job.context()->setMaskPainter( maskPainter );
858 job.maskPainter.reset( maskPainter );
859 job.maskPaintDevice.reset( maskPaintDevice );
863 for ( LayerRenderJob &job : firstPassJobs )
867 auto it = maskedSymbolLayers.find( job.layerId );
868 if ( it == maskedSymbolLayers.end() )
871 QList<MaskSource> &sourceList = it->second;
872 const QSet<QString> symbolList = it->first;
874 secondPassJobs.emplace_back( LayerRenderJob() );
875 LayerRenderJob &job2 = secondPassJobs.back();
877 job2.maskRequiresLayerRasterization = job.maskRequiresLayerRasterization;
880 for ( MaskSource &source : sourceList )
882 if ( source.labelMaskId != -1 )
883 job2.maskJobs.push_back( qMakePair(
nullptr, source.labelMaskId ) );
885 job2.maskJobs.push_back( qMakePair( layerJobMapping[source.layerId], -1 ) );
889 job2.setContext( std::make_unique< QgsRenderContext >( *job.context() ) );
891 job2.layer = job.layer;
892 job2.renderAboveLabels = job.renderAboveLabels;
893 job2.layerId = job.layerId;
896 job2.firstPassJob = &job;
898 if ( !forceVector || job2.maskRequiresLayerRasterization )
900 job2.context()->setPainter( allocateImageAndPainter( job.layerId, job2.img, job2.context() ) );
904 PictureAndPainter pictureAndPainter = allocatePictureAndPainter( job2.context() );
905 job2.picture = std::move( pictureAndPainter.first );
906 job2.context()->setPainter( pictureAndPainter.second );
909 if ( ! job2.img && ! job2.picture )
911 secondPassJobs.pop_back();
918 job2.renderer = mapRenderer;
921 job2.context()->setFeedback( job2.renderer->feedback() );
926 job2.context()->setDisabledSymbolLayersV2( symbolList );
929 return secondPassJobs;
937 for ( LayerRenderJob &job : secondPassJobs )
939 if ( job.maskRequiresLayerRasterization )
945 for (
const QPair<LayerRenderJob *, int> &p : std::as_const( job.maskJobs ) )
947 QPainter *maskPainter = p.first ? p.first->maskPainter.get() : labelJob.maskPainters[p.second].get();
948 QPainterPath path =
static_cast<QgsMaskPaintDevice *
>( maskPainter->device() )->maskPainterPath();
949 for (
const QString &symbolLayerId : job.context()->disabledSymbolLayersV2() )
951 job.context()->addSymbolLayerClipPath( symbolLayerId, path );
955 job.context()->setDisabledSymbolLayersV2( QSet<QString>() );
963 job.context.setPainter( painter );
964 job.context.setLabelingEngine( labelingEngine2 );
965 job.context.setFeedback( mLabelingEngineFeedback );
969 job.context.setExtent( r1 );
971 job.context.setFeatureFilterProvider( mFeatureFilterProvider );
974 job.context.setCoordinateTransform( ct );
988 job.context.setPainter(
nullptr );
992 if ( canUseLabelCache && (
mCache || !painter ) )
994 job.img = allocateImage( QStringLiteral(
"labels" ) );
1004 for ( LayerRenderJob &job : jobs )
1008 delete job.context()->painter();
1009 job.context()->setPainter(
nullptr );
1011 if (
mCache && !job.cached && job.completed && job.layer )
1013 QgsDebugMsgLevel( QStringLiteral(
"caching image for %1" ).arg( job.layerId ), 2 );
1022 if ( job.elevationMap )
1024 job.context()->setElevationMap(
nullptr );
1025 if (
mCache && !job.cached && job.completed && job.layer )
1027 QgsDebugMsgLevel( QStringLiteral(
"caching elevation map for %1" ).arg( job.layerId ), 2 );
1030 job.elevationMap->rawElevationImage(),
1033 QList< QgsMapLayer * >() << job.layer );
1036 job.elevationMap->rawElevationImage(),
1039 QList< QgsMapLayer * >() << job.layer );
1042 delete job.elevationMap;
1043 job.elevationMap =
nullptr;
1048 delete job.context()->painter();
1049 job.context()->setPainter(
nullptr );
1050 job.picture.reset(
nullptr );
1055 const QStringList
errors = job.renderer->errors();
1056 for (
const QString &message :
errors )
1057 mErrors.append( Error( job.renderer->layerId(), message ) );
1059 mRenderedItemResults->appendResults( job.renderer->takeRenderedItemDetails(), *job.context() );
1061 delete job.renderer;
1062 job.renderer =
nullptr;
1068 job.maskPainter.reset(
nullptr );
1069 job.maskPaintDevice.reset(
nullptr );
1077 for ( LayerRenderJob &job : jobs )
1081 delete job.context()->painter();
1082 job.context()->setPainter(
nullptr );
1090 delete job.context()->painter();
1091 job.context()->setPainter(
nullptr );
1096 delete job.renderer;
1097 job.renderer =
nullptr;
1111 if (
mCache && !job.cached && !job.context.renderingStopped() )
1122 job.picture.reset(
nullptr );
1123 job.maskPainters.clear();
1124 job.maskPaintDevices.clear();
1128#define DEBUG_RENDERING 0
1131 const std::vector<LayerRenderJob> &jobs,
1132 const LabelRenderJob &labelJob,
1138 image.setDotsPerMeterX(
static_cast<int>( settings.
outputDpi() * 39.37 ) );
1139 image.setDotsPerMeterY(
static_cast<int>( settings.
outputDpi() * 39.37 ) );
1143 std::unique_ptr<QgsElevationMap> mainElevationMap;
1144 if ( mapShadingRenderer.
isActive() )
1147 QPainter painter( &image );
1152 for (
const LayerRenderJob &job : jobs )
1154 if ( job.renderAboveLabels )
1161 painter.setCompositionMode( job.blendMode );
1162 painter.setOpacity( job.opacity );
1164 if ( mainElevationMap )
1167 if ( layerElevationMap.
isValid() )
1173 img.save( QString(
"/tmp/final_%1.png" ).arg( i ) );
1177 painter.drawImage( 0, 0, img );
1180 if ( mapShadingRenderer.
isActive() && mainElevationMap )
1188 if ( labelJob.img && labelJob.complete )
1190 painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
1191 painter.setOpacity( 1.0 );
1192 painter.drawImage( 0, 0, *labelJob.img );
1200 painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
1201 painter.setOpacity( 1.0 );
1202 painter.drawImage( 0, 0, labelCacheImage );
1206 for (
const LayerRenderJob &job : jobs )
1208 if ( !job.renderAboveLabels )
1215 painter.setCompositionMode( job.blendMode );
1216 painter.setOpacity( job.opacity );
1218 painter.drawImage( 0, 0, img );
1223 image.save(
"/tmp/final.png" );
1230 const LayerRenderJob &job,
1234 if ( job.imageCanBeComposed() )
1236 Q_ASSERT( job.img );
1241 if ( cache && cache->
hasAnyCacheImage( job.layerId + QStringLiteral(
"_preview" ) ) )
1252 if ( job.imageCanBeComposed() && job.elevationMap )
1254 return *job.elevationMap;
1268 for ( LayerRenderJob &job : secondPassJobs )
1270 const bool isRasterRendering = !forceVector || job.maskRequiresLayerRasterization;
1273 if ( isRasterRendering && job.maskJobs.size() > 1 )
1275 QPainter *maskPainter =
nullptr;
1276 for ( QPair<LayerRenderJob *, int> p : job.maskJobs )
1278 QImage *maskImage =
static_cast<QImage *
>( p.first ? p.first->maskPaintDevice.get() : labelJob.maskPaintDevices[p.second].get() );
1281 maskPainter = p.first ? p.first->maskPainter.get() : labelJob.maskPainters[ p.second ].get();
1285 maskPainter->drawImage( 0, 0, *maskImage );
1290 if ( ! job.maskJobs.isEmpty() )
1293 QPair<LayerRenderJob *, int> p = *job.maskJobs.begin();
1294 if ( isRasterRendering )
1296 QImage *maskImage =
static_cast<QImage *
>( p.first ? p.first->maskPaintDevice.get() : labelJob.maskPaintDevices[p.second].get() );
1299 QPainter *painter = job.context()->painter();
1301 painter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
1306 QImage maskBinAlpha = maskImage->createMaskFromColor( 0 );
1307 QVector<QRgb> mswTable;
1308 mswTable.push_back( qRgba( 0, 0, 0, 255 ) );
1309 mswTable.push_back( qRgba( 0, 0, 0, 0 ) );
1310 maskBinAlpha.setColorTable( mswTable );
1311 painter->drawImage( 0, 0, maskBinAlpha );
1315 QPainter tempPainter;
1318 QPainter *painter1 = job.firstPassJob->context()->painter();
1321 tempPainter.begin( job.firstPassJob->img );
1322 painter1 = &tempPainter;
1326 painter1->setCompositionMode( QPainter::CompositionMode_DestinationOut );
1327 painter1->drawImage( 0, 0, *maskImage );
1330 painter1->setCompositionMode( QPainter::CompositionMode_DestinationOver );
1331 painter1->drawImage( 0, 0, *job.img );
1336 job.firstPassJob->picture = std::move( job.picture );
1337 job.picture =
nullptr;
1348 QMultiMap<int, QString> elapsed;
1349 for (
const LayerRenderJob &job : jobs )
1350 elapsed.insert( job.renderingTime, job.layerId );
1351 for (
const LayerRenderJob &job : secondPassJobs )
1352 elapsed.insert( job.renderingTime, job.layerId + QString(
" (second pass)" ) );
1354 elapsed.insert( labelJob.renderingTime, tr(
"Labeling" ) );
1356 QList<int> tt( elapsed.uniqueKeys() );
1357 std::sort( tt.begin(), tt.end(), std::greater<int>() );
1358 for (
int t : std::as_const( tt ) )
1360 QgsMessageLog::logMessage( tr(
"%1 ms: %2" ).arg( t ).arg( QStringList( elapsed.values( t ) ).join( QLatin1String(
", " ) ) ), tr(
"Rendering" ) );
1373 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
1377 if ( labelingEngine2 )
1379 labelingEngine2->
run( renderContext );
1382 QgsDebugMsgLevel( QStringLiteral(
"Draw labeling took (seconds): %1" ).arg( t.elapsed() / 1000. ), 2 );
1387 Q_UNUSED( settings )
1389 drawLabeling( renderContext, labelingEngine2, painter );
@ InternalLayerOpacityHandling
The renderer internally handles the raster layer's opacity, so the default layer level opacity handli...
@ ApplyClipAfterReprojection
Feature geometry clipping to mapExtent() must be performed after the geometries are transformed using...
@ ForceVectorOutput
Vector graphics should not be cached and drawn as raster images.
@ ForceRasterMasks
Force symbol masking to be applied using a raster method. This is considerably faster when compared t...
virtual bool requiresAdvancedEffects() const =0
Returns true if drawing labels requires advanced effects like composition modes, which could prevent ...
Custom exception class for Coordinate Reference System related exceptions.
bool isInfinite() const
Returns true if the range consists of all possible values.
Stores digital elevation model in a raster image which may get updated as a part of map layer renderi...
bool isValid() const
Returns whether the elevation map is valid.
This class can render elevation shading on an image with different methods (eye dome lighting,...
Qgis::ElevationMapCombineMethod combinedElevationMethod() const
Returns the method used when conbining different elevation sources.
bool isActive() const
Returns whether this shading renderer is active.
void renderShading(const QgsElevationMap &elevation, QImage &image, const QgsRenderContext &context) const
Render shading on image condidering the elevation map elevation and the renderer context context If e...
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
QgsFeedback subclass for granular reporting of labeling engine progress.
The QgsLabelingEngine class provides map labeling functionality.
virtual void run(QgsRenderContext &context)=0
Runs the labeling job.
static void warning(const QString &msg)
Goes to qWarning.
virtual bool hasElevation() const
Returns true if the layer has an elevation or z component.
virtual bool isVisibleInZRange(const QgsDoubleRange &range) const
Returns true if the layer should be visible and rendered for the specified z range.
virtual void setLayerRenderingTimeHint(int time)
Sets approximate render time (in ms) for the layer to render.
Restore overridden layer style on destruction.
virtual bool isVisibleInTemporalRange(const QgsDateTimeRange &range) const
Returns true if the layer should be visible and rendered for the specified time range.
Base class for all map layer types.
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QgsCoordinateReferenceSystem crs
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
virtual QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext)=0
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context.
double minimumScale() const
Returns the minimum map scale (i.e.
virtual QgsMapLayerElevationProperties * elevationProperties()
Returns the layer's elevation properties.
double maximumScale() const
Returns the maximum map scale (i.e.
This class is responsible for keeping cache of rendered images resulting from a map rendering job.
bool updateParameters(const QgsRectangle &extent, const QgsMapToPixel &mtp)
Sets extent and scale parameters.
QList< QgsMapLayer * > dependentLayers(const QString &cacheKey) const
Returns a list of map layers on which an image in the cache depends.
bool hasCacheImage(const QString &cacheKey) const
Returns true if the cache contains an image with the specified cacheKey that has the same extent and ...
QImage cacheImage(const QString &cacheKey) const
Returns the cached image for the specified cacheKey.
bool hasAnyCacheImage(const QString &cacheKey, double minimumScaleThreshold=0, double maximumScaleThreshold=0) const
Returns true if the cache contains an image with the specified cacheKey with any cache's parameters (...
void setCacheImageWithParameters(const QString &cacheKey, const QImage &image, const QgsRectangle &extent, const QgsMapToPixel &mapToPixel, const QList< QgsMapLayer * > &dependentLayers=QList< QgsMapLayer * >())
Set the cached image for a particular cacheKey, using a specific extent and mapToPixel (which may dif...
void clearCacheImage(const QString &cacheKey)
Removes an image from the cache with matching cacheKey.
QImage transformedCacheImage(const QString &cacheKey, const QgsMapToPixel &mtp) const
Returns the cached image for the specified cacheKey transformed to the particular extent and scale.
Abstract base class for map rendering implementations.
void logRenderingTime(const std::vector< LayerRenderJob > &jobs, const std::vector< LayerRenderJob > &secondPassJobs, const LabelRenderJob &labelJob)
static QgsElevationMap layerElevationToBeComposed(const QgsMapSettings &settings, const LayerRenderJob &job, const QgsMapRendererCache *cache)
static QImage composeImage(const QgsMapSettings &settings, const std::vector< LayerRenderJob > &jobs, const LabelRenderJob &labelJob, const QgsMapRendererCache *cache=nullptr)
void cleanupSecondPassJobs(std::vector< LayerRenderJob > &jobs)
void setCache(QgsMapRendererCache *cache)
Assign a cache to be used for reading and storing rendered images of individual layers.
QHash< QgsMapLayer *, int > perLayerRenderingTime() const
Returns the render time (in ms) per layer.
void initSecondPassJobs(std::vector< LayerRenderJob > &secondPassJobs, LabelRenderJob &labelJob) const
Initialize secondPassJobs according to what have been rendered (mask clipping path e....
static QImage layerImageToBeComposed(const QgsMapSettings &settings, const LayerRenderJob &job, const QgsMapRendererCache *cache)
QHash< QString, int > mLayerRenderingTimeHints
Approximate expected layer rendering time per layer, by layer ID.
std::unique_ptr< QgsRenderedItemResults > mRenderedItemResults
Errors errors() const
List of errors that happened during the rendering job - available when the rendering has been finishe...
static Q_DECL_DEPRECATED void drawLabeling(const QgsMapSettings &settings, QgsRenderContext &renderContext, QgsLabelingEngine *labelingEngine2, QPainter *painter)
static const QString LABEL_PREVIEW_CACHE_ID
QgsMapRendererCache ID string for cached label image during preview compositions only.
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)
const QgsMapSettings & mapSettings() const
Returns map settings with which this job was started.
QgsMapRendererCache * mCache
void finished()
emitted when asynchronous rendering is finished (or canceled).
static const QgsSettingsEntryBool * settingsLogCanvasRefreshEvent
Settings entry log canvas refresh event.
QgsMapRendererJob(const QgsMapSettings &settings)
~QgsMapRendererJob() override
void start()
Start the rendering job and immediately return.
QStringList mLayersRedrawnFromCache
QStringList layersRedrawnFromCache() const
Returns a list of the layer IDs for all layers which were redrawn from cached images.
QList< QgsMapRendererJob::Error > Errors
static const QString LABEL_CACHE_ID
QgsMapRendererCache ID string for cached label image.
static const QString ELEVATION_MAP_CACHE_PREFIX
QgsMapRendererCache prefix string for cached elevation map image.
QHash< QgsWeakMapLayerPointer, int > mPerLayerRenderingTime
Render time (in ms) per layer, by layer ID.
QgsRenderedItemResults * takeRenderedItemResults()
Takes the rendered item results from the map render job and returns them.
QgsLabelingEngineFeedback * labelingEngineFeedback()
Returns the associated labeling engine feedback object.
static void composeSecondPass(std::vector< LayerRenderJob > &secondPassJobs, LabelRenderJob &labelJob, bool forceVector=false)
Compose second pass images into first pass images.
std::vector< LayerRenderJob > prepareSecondPassJobs(std::vector< LayerRenderJob > &firstPassJobs, LabelRenderJob &labelJob)
Prepares jobs for a second pass, if selective masks exist (from labels or symbol layers).
LabelRenderJob prepareLabelingJob(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool canUseLabelCache=true)
Prepares a labeling job.
void setLayerRenderingTimeHints(const QHash< QString, int > &hints)
Sets approximate render times (in ms) for map layers.
void cleanupLabelJob(LabelRenderJob &job)
Handles clean up tasks for a label job, including deletion of images and storing cached label results...
QgsLabelSink * labelSink() const
Returns the label sink associated to this rendering job.
bool prepareLabelCache() const
Prepares the cache for storing the result of labeling.
QgsMapRendererQImageJob(const QgsMapSettings &settings)
The QgsMapSettings class contains configuration for rendering of the map.
QSize deviceOutputSize() const
Returns the device output size of the map render.
QList< QgsMapLayer * > layers(bool expandGroupLayers=false) const
Returns the list of layers which will be rendered in the map.
double scale() const
Returns the calculated map scale.
QgsCoordinateTransform layerTransform(const QgsMapLayer *layer) const
Returns the coordinate transform from layer's CRS to destination CRS.
QgsDoubleRange zRange() const
Returns the range of z-values which will be visible in the map.
QColor backgroundColor() const
Returns the background color of the map.
const QgsMapToPixel & mapToPixel() const
float devicePixelRatio() const
Returns the device pixel ratio.
QSize outputSize() const
Returns the size of the resulting map image, in pixels.
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...
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
const QgsElevationShadingRenderer & elevationShadingRenderer() const
Returns the shading renderer used to render shading on the entire map.
double outputDpi() const
Returns the DPI (dots per inch) used for conversion between real world units (e.g.
bool testFlag(Qgis::MapSettingsFlag flag) const
Check whether a particular flag is enabled.
QMap< QString, QString > layerStyleOverrides() const
Returns the map of map layer style overrides (key: layer ID, value: style name) where a different sty...
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
Mask painter device that can be used to register everything painted into a QPainterPath used later as...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static bool staticWillUseLayer(const QgsMapLayer *layer)
Called to find out whether a specified layer is used for labeling.
A class to represent a 2D point.
QString toString(int precision=-1) const
Returns a string representation of the point (x, y) with a preset precision.
Represents a raster layer.
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
virtual Qgis::RasterRendererFlags flags() const
Returns flags which dictate renderer behavior.
A rectangle specified with double values.
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
void grow(double delta)
Grows the rectangle in place by the specified amount.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
bool isFinite() const
Returns true if the rectangle has finite boundaries.
Contains information about the context of a rendering operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
Stores collated details of rendered items during a map rendering operation.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
A boolean settings entry.
static QgsSettingsTreeNode * sTreeMap
Type used to refer to a specific symbol layer in a symbol of a layer.
const QgsDateTimeRange & temporalRange() const
Returns the datetime range for the object.
bool isTemporal() const
Returns true if the object's temporal range is enabled, and the object will be filtered when renderin...
Implementation of threaded rendering for vector layers.
static QgsMaskedLayers symbolLayerMasks(const QgsVectorLayer *)
Returns all masks that may be defined on symbol layers for a given vector layer.
static QHash< QString, QgsMaskedLayers > labelMasks(const QgsVectorLayer *)
Returns masks defined in labeling options of a layer.
Represents a vector layer which manages a vector based data sets.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QHash< QString, QgsMaskedLayer > QgsMaskedLayers
masked layers where key is the layer id