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;
97LayerRenderJob::LayerRenderJob( LayerRenderJob &&other )
98 : imageInitialized( other.imageInitialized )
99 , blendMode( other.blendMode )
100 , opacity( other.opacity )
101 , cached( other.cached )
102 , renderAboveLabels( other.renderAboveLabels )
103 , layer( other.layer )
104 , completed( other.completed )
105 , renderingTime( other.renderingTime )
106 , estimatedRenderingTime( other.estimatedRenderingTime )
107 , errors( other.errors )
108 , layerId( other.layerId )
109 , maskRequiresLayerRasterization( other.maskRequiresLayerRasterization )
110 , maskJobs( other.maskJobs )
112 mContext = std::move( other.mContext );
117 renderer = other.renderer;
118 other.renderer =
nullptr;
120 elevationMap = other.elevationMap;
121 other.elevationMap =
nullptr;
123 maskPaintDevice = std::move( other.maskPaintDevice );
125 firstPassJob = other.firstPassJob;
126 other.firstPassJob =
nullptr;
128 picture = std::move( other.picture );
131bool LayerRenderJob::imageCanBeComposed()
const
133 if ( imageInitialized )
137 return renderer->isReadyToCompose();
151 : mSettings( settings )
197 return mLabelingEngineFeedback;
202 QHash<QgsMapLayer *, int> result;
205 if (
auto &&lKey = it.key() )
206 result.insert( lKey, it.value() );
226 QSet< QgsMapLayer * > labeledLayers;
233 switch ( ml->type() )
235 case Qgis::LayerType::Vector:
245 case Qgis::LayerType::VectorTile:
251 case Qgis::LayerType::Raster:
252 case Qgis::LayerType::Annotation:
253 case Qgis::LayerType::Plugin:
254 case Qgis::LayerType::Mesh:
255 case Qgis::LayerType::PointCloud:
256 case Qgis::LayerType::Group:
271 bool canUseCache = canCache && QSet< QgsMapLayer * >( labelDependentLayers.begin(), labelDependentLayers.end() ) == labeledLayers;
300 static const double SPLIT_COORD = 180.0;
312 QgsDebugMsgLevel( QStringLiteral(
"\n0:%1 %2x%3\n1:%4\n2:%5 %6x%7 (w:%8 h:%9)" )
315 .arg( std::fabs( 1.0 - extent2.
width() / extent.
width() ) )
316 .arg( std::fabs( 1.0 - extent2.
height() / extent.
height() ) )
338 Qgis::TransformDirection::Reverse );
342 Qgis::TransformDirection::Reverse );
350 if ( ll.
x() > ur.
x() )
379 extent =
QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
388 QgsDebugMsg( QStringLiteral(
"Transform error caught" ) );
389 extent =
QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
390 r2 =
QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
397QImage *QgsMapRendererJob::allocateImage( QString layerId )
404 if ( image->isNull() )
413QgsElevationMap *QgsMapRendererJob::allocateElevationMap( QString layerId )
416 if ( !elevationMap->isValid() )
421 return elevationMap.release();
424QPainter *QgsMapRendererJob::allocateImageAndPainter( QString layerId, QImage *&image,
const QgsRenderContext *context )
426 QPainter *painter =
nullptr;
427 image = allocateImage( layerId );
430 painter =
new QPainter( image );
436QgsMapRendererJob::PictureAndPainter QgsMapRendererJob::allocatePictureAndPainter(
const QgsRenderContext *context )
438 std::unique_ptr<QPicture> picture = std::make_unique<QPicture>();
439 QPainter *painter =
new QPainter( picture.get() );
441 return { std::move( picture ), painter };
446 std::vector< LayerRenderJob > layerJobs;
455 Q_UNUSED( cacheValid )
456 QgsDebugMsgLevel( QStringLiteral(
"CACHE VALID: %1" ).arg( cacheValid ), 4 );
461 while ( li.hasPrevious() )
465 QgsDebugMsgLevel( QStringLiteral(
"layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 blendmode:%5 isValid:%6" )
482 QgsDebugMsgLevel( QStringLiteral(
"Layer not rendered because it is not within the defined visibility scale range" ), 3 );
488 QgsDebugMsgLevel( QStringLiteral(
"Layer not rendered because it is not visible within the map's time range" ), 3 );
494 QgsDebugMsgLevel( QStringLiteral(
"Layer not rendered because it is not visible within the map's z range" ), 3 );
503 bool haveExtentInLayerCrs =
true;
506 haveExtentInLayerCrs = reprojectToLayerExtent( ml, ct, r1, r2 );
511 mErrors.append( Error( ml->
id(), tr(
"There was a problem transforming the layer's extent. Layer skipped." ) ) );
522 if ( ( vl && vl->
isEditable() ) || requiresLabeling )
528 layerJobs.emplace_back( LayerRenderJob() );
529 LayerRenderJob &job = layerJobs.back();
531 job.layerId = ml->
id();
532 job.renderAboveLabels = ml->
customProperty( QStringLiteral(
"rendering/renderAboveLabels" ) ).toBool();
536 if ( !ml->
customProperty( QStringLiteral(
"_noset_layer_expression_context" ) ).toBool() )
538 job.context()->setPainter( painter );
539 job.context()->setLabelingEngine( labelingEngine2 );
540 job.context()->setLabelSink(
labelSink() );
541 job.context()->setCoordinateTransform( ct );
542 job.context()->setExtent( r1 );
543 if ( !haveExtentInLayerCrs )
546 if ( mFeatureFilterProvider )
547 job.context()->setFeatureFilterProvider( mFeatureFilterProvider );
555 if ( ml->
type() == Qgis::LayerType::Raster )
580 job.imageInitialized =
true;
588 job.renderer =
nullptr;
589 job.context()->setPainter(
nullptr );
594 QElapsedTimer layerTime;
600 job.context()->setFeedback( job.renderer->feedback() );
606 if (
mCache || ( !painter && !deferredPainterSet ) || ( job.renderer && job.renderer->forceRasterRender() ) )
609 job.context()->setPainter( allocateImageAndPainter( ml->
id(), job.img, job.context() ) );
613 job.renderer =
nullptr;
614 layerJobs.pop_back();
623 job.elevationMap = allocateElevationMap( ml->
id() );
624 job.context()->setElevationMap( job.elevationMap );
627 job.renderingTime = layerTime.elapsed();
635 std::vector< LayerRenderJob > secondPassJobs;
638 QHash<QString, LayerRenderJob *> layerJobMapping;
641 QMap<QString, bool> maskLayerHasEffects;
642 QMap<int, bool> labelHasEffects;
650 MaskSource(
const QString &layerId_,
const QString &labelRuleId_,
int labelMaskId_,
bool hasEffects_ ):
651 layerId( layerId_ ), labelRuleId( labelRuleId_ ), labelMaskId( labelMaskId_ ), hasEffects( hasEffects_ ) {}
656 QHash<QString, QPair<QSet<QString>, QList<MaskSource>>> maskedSymbolLayers;
663 for ( LayerRenderJob &job : firstPassJobs )
665 layerJobMapping[job.layerId] = &job;
670 for ( LayerRenderJob &job : firstPassJobs )
677 auto collectMasks = [&](
QgsMaskedLayers * masks, QString sourceLayerId, QString ruleId = QString(),
int labelMaskId = -1 )
679 bool hasEffects =
false;
680 for (
auto it = masks->begin(); it != masks->end(); ++it )
682 auto lit = maskedSymbolLayers.find( it.key() );
683 if ( lit == maskedSymbolLayers.end() )
685 maskedSymbolLayers[it.key()] = qMakePair( it.value().symbolLayerIds, QList<MaskSource>() << MaskSource( sourceLayerId, ruleId, labelMaskId, it.value().hasEffects ) );
689 if ( lit->first != it.value().symbolLayerIds )
691 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() ) );
694 lit->second.push_back( MaskSource( sourceLayerId, ruleId, labelMaskId, hasEffects ) );
696 hasEffects |= it.value().hasEffects;
698 if ( ! masks->isEmpty() && labelMaskId == -1 )
699 maskLayerHasEffects[ sourceLayerId ] = hasEffects;
704 for (
auto it = labelMasks.begin(); it != labelMasks.end(); it++ )
706 QString labelRule = it.key();
712 for (
auto mit = masks.begin(); mit != masks.end(); mit++ )
714 const QString sourceLayerId = mit.key();
716 if ( !layerJobMapping.contains( sourceLayerId ) )
719 usableMasks.insert( sourceLayerId, mit.value() );
722 if ( usableMasks.empty() )
726 QSet<QgsSymbolLayerReference> slRefs;
727 bool hasEffects =
false;
728 for (
auto mit = usableMasks.begin(); mit != usableMasks.end(); mit++ )
730 const QString sourceLayerId = mit.key();
732 if ( !layerJobMapping.contains( sourceLayerId ) )
735 for (
const QString &symbolLayerId : mit.value().symbolLayerIds )
738 hasEffects |= mit.value().hasEffects;
741 int labelMaskId = labelJob.maskIdProvider.insertLabelLayer( vl->
id(), it.key(), slRefs );
742 labelHasEffects[ labelMaskId ] = hasEffects;
745 collectMasks( &usableMasks, vl->
id(), labelRule, labelMaskId );
750 collectMasks( &symbolLayerMasks, vl->
id() );
753 if ( maskedSymbolLayers.isEmpty() )
754 return secondPassJobs;
757 for (
int maskId = 0; maskId < labelJob.maskIdProvider.size(); maskId++ )
759 QPaintDevice *maskPaintDevice =
nullptr;
760 QPainter *maskPainter =
nullptr;
761 if ( forceVector && !labelHasEffects[ maskId ] )
765 maskPainter =
new QPainter( maskPaintDevice );
770 QImage *maskImage =
nullptr;
771 maskPainter = allocateImageAndPainter( QStringLiteral(
"label mask" ), maskImage, &labelJob.context );
772 maskImage->fill( 0 );
773 maskPaintDevice = maskImage;
776 labelJob.context.setMaskPainter( maskPainter, maskId );
777 labelJob.maskPainters.push_back( std::unique_ptr<QPainter>( maskPainter ) );
778 labelJob.maskPaintDevices.push_back( std::unique_ptr<QPaintDevice>( maskPaintDevice ) );
780 labelJob.context.setMaskIdProvider( &labelJob.maskIdProvider );
791 if ( !labelJob.img && !forceVector )
793 labelJob.img = allocateImage( QStringLiteral(
"labels" ) );
795 else if ( !labelJob.picture && forceVector )
797 labelJob.picture.reset(
new QPicture() );
801 for ( LayerRenderJob &job : firstPassJobs )
803 job.maskRequiresLayerRasterization =
false;
805 auto it = maskedSymbolLayers.find( job.layerId );
806 if ( it != maskedSymbolLayers.end() )
808 const QList<MaskSource> &sourceList = it->second;
809 for (
const MaskSource &source : sourceList )
811 job.maskRequiresLayerRasterization |= source.hasEffects;
816 const bool isRasterRendering = !forceVector || job.maskRequiresLayerRasterization || ( job.renderer && job.renderer->forceRasterRender() );
817 if ( isRasterRendering && !job.img )
819 job.context()->setPainter( allocateImageAndPainter( job.layerId, job.img, job.context() ) );
821 else if ( !isRasterRendering && !job.picture )
823 PictureAndPainter pictureAndPainter = allocatePictureAndPainter( job.context() );
824 job.picture = std::move( pictureAndPainter.first );
825 job.context()->setPainter( pictureAndPainter.second );
828 job.renderer = job.layer->createMapRenderer( *( job.context() ) );
832 if ( maskLayerHasEffects.contains( job.layerId ) )
834 QPaintDevice *maskPaintDevice =
nullptr;
835 QPainter *maskPainter =
nullptr;
836 if ( forceVector && !maskLayerHasEffects[ job.layerId ] )
840 maskPainter =
new QPainter( maskPaintDevice );
845 QImage *maskImage =
nullptr;
846 maskPainter = allocateImageAndPainter( job.layerId, maskImage, job.context() );
847 maskImage->fill( 0 );
848 maskPaintDevice = maskImage;
851 job.context()->setMaskPainter( maskPainter );
852 job.maskPainter.reset( maskPainter );
853 job.maskPaintDevice.reset( maskPaintDevice );
857 for ( LayerRenderJob &job : firstPassJobs )
861 auto it = maskedSymbolLayers.find( job.layerId );
862 if ( it == maskedSymbolLayers.end() )
865 QList<MaskSource> &sourceList = it->second;
866 const QSet<QString> symbolList = it->first;
868 secondPassJobs.emplace_back( LayerRenderJob() );
869 LayerRenderJob &job2 = secondPassJobs.back();
871 job2.maskRequiresLayerRasterization = job.maskRequiresLayerRasterization;
874 for ( MaskSource &source : sourceList )
876 if ( source.labelMaskId != -1 )
877 job2.maskJobs.push_back( qMakePair(
nullptr, source.labelMaskId ) );
879 job2.maskJobs.push_back( qMakePair( layerJobMapping[source.layerId], -1 ) );
883 job2.setContext( std::make_unique< QgsRenderContext >( *job.context() ) );
885 job2.layer = job.layer;
886 job2.renderAboveLabels = job.renderAboveLabels;
887 job2.layerId = job.layerId;
890 job2.firstPassJob = &job;
892 if ( !forceVector || job2.maskRequiresLayerRasterization )
894 job2.context()->setPainter( allocateImageAndPainter( job.layerId, job2.img, job2.context() ) );
898 PictureAndPainter pictureAndPainter = allocatePictureAndPainter( job2.context() );
899 job2.picture = std::move( pictureAndPainter.first );
900 job2.context()->setPainter( pictureAndPainter.second );
903 if ( ! job2.img && ! job2.picture )
905 secondPassJobs.pop_back();
912 job2.renderer = mapRenderer;
915 job2.context()->setFeedback( job2.renderer->feedback() );
920 job2.context()->setDisabledSymbolLayersV2( symbolList );
923 return secondPassJobs;
931 for ( LayerRenderJob &job : secondPassJobs )
933 if ( job.maskRequiresLayerRasterization )
939 for (
const QPair<LayerRenderJob *, int> &p : std::as_const( job.maskJobs ) )
941 QPainter *maskPainter = p.first ? p.first->maskPainter.get() : labelJob.maskPainters[p.second].get();
942 QPainterPath path =
static_cast<QgsMaskPaintDevice *
>( maskPainter->device() )->maskPainterPath();
943 for (
const QString &symbolLayerId : job.context()->disabledSymbolLayersV2() )
945 job.context()->addSymbolLayerClipPath( symbolLayerId, path );
949 job.context()->setDisabledSymbolLayersV2( QSet<QString>() );
957 job.context.setPainter( painter );
958 job.context.setLabelingEngine( labelingEngine2 );
959 job.context.setFeedback( mLabelingEngineFeedback );
963 job.context.setExtent( r1 );
965 job.context.setFeatureFilterProvider( mFeatureFilterProvider );
968 job.context.setCoordinateTransform( ct );
982 job.context.setPainter(
nullptr );
986 if ( canUseLabelCache && (
mCache || !painter ) )
988 job.img = allocateImage( QStringLiteral(
"labels" ) );
998 for ( LayerRenderJob &job : jobs )
1002 delete job.context()->painter();
1003 job.context()->setPainter(
nullptr );
1005 if (
mCache && !job.cached && job.completed && job.layer )
1007 QgsDebugMsgLevel( QStringLiteral(
"caching image for %1" ).arg( job.layerId ), 2 );
1016 if ( job.elevationMap )
1018 job.context()->setElevationMap(
nullptr );
1019 if (
mCache && !job.cached && job.completed && job.layer )
1021 QgsDebugMsgLevel( QStringLiteral(
"caching elevation map for %1" ).arg( job.layerId ), 2 );
1024 job.elevationMap->rawElevationImage(),
1027 QList< QgsMapLayer * >() << job.layer );
1030 job.elevationMap->rawElevationImage(),
1033 QList< QgsMapLayer * >() << job.layer );
1036 delete job.elevationMap;
1037 job.elevationMap =
nullptr;
1042 delete job.context()->painter();
1043 job.context()->setPainter(
nullptr );
1044 job.picture.reset(
nullptr );
1049 const QStringList
errors = job.renderer->errors();
1050 for (
const QString &message :
errors )
1051 mErrors.append( Error( job.renderer->layerId(), message ) );
1053 mRenderedItemResults->appendResults( job.renderer->takeRenderedItemDetails(), *job.context() );
1055 delete job.renderer;
1056 job.renderer =
nullptr;
1062 job.maskPainter.reset(
nullptr );
1063 job.maskPaintDevice.reset(
nullptr );
1071 for ( LayerRenderJob &job : jobs )
1075 delete job.context()->painter();
1076 job.context()->setPainter(
nullptr );
1084 delete job.context()->painter();
1085 job.context()->setPainter(
nullptr );
1090 delete job.renderer;
1091 job.renderer =
nullptr;
1105 if (
mCache && !job.cached && !job.context.renderingStopped() )
1116 job.picture.reset(
nullptr );
1117 job.maskPainters.clear();
1118 job.maskPaintDevices.clear();
1122#define DEBUG_RENDERING 0
1125 const std::vector<LayerRenderJob> &jobs,
1126 const LabelRenderJob &labelJob,
1132 image.setDotsPerMeterX(
static_cast<int>( settings.
outputDpi() * 39.37 ) );
1133 image.setDotsPerMeterY(
static_cast<int>( settings.
outputDpi() * 39.37 ) );
1137 std::unique_ptr<QgsElevationMap> mainElevationMap;
1138 if ( mapShadingRenderer.
isActive() )
1141 QPainter painter( &image );
1146 for (
const LayerRenderJob &job : jobs )
1148 if ( job.renderAboveLabels )
1155 painter.setCompositionMode( job.blendMode );
1156 painter.setOpacity( job.opacity );
1158 if ( mainElevationMap )
1161 if ( layerElevationMap.
isValid() )
1167 img.save( QString(
"/tmp/final_%1.png" ).arg( i ) );
1171 painter.drawImage( 0, 0, img );
1174 if ( mapShadingRenderer.
isActive() && mainElevationMap )
1182 if ( labelJob.img && labelJob.complete )
1184 painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
1185 painter.setOpacity( 1.0 );
1186 painter.drawImage( 0, 0, *labelJob.img );
1194 painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
1195 painter.setOpacity( 1.0 );
1196 painter.drawImage( 0, 0, labelCacheImage );
1200 for (
const LayerRenderJob &job : jobs )
1202 if ( !job.renderAboveLabels )
1209 painter.setCompositionMode( job.blendMode );
1210 painter.setOpacity( job.opacity );
1212 painter.drawImage( 0, 0, img );
1217 image.save(
"/tmp/final.png" );
1224 const LayerRenderJob &job,
1228 if ( job.imageCanBeComposed() )
1230 Q_ASSERT( job.img );
1235 if ( cache && cache->
hasAnyCacheImage( job.layerId + QStringLiteral(
"_preview" ) ) )
1246 if ( job.imageCanBeComposed() && job.elevationMap )
1248 return *job.elevationMap;
1262 for ( LayerRenderJob &job : secondPassJobs )
1264 const bool isRasterRendering = !forceVector || job.maskRequiresLayerRasterization;
1267 if ( isRasterRendering && job.maskJobs.size() > 1 )
1269 QPainter *maskPainter =
nullptr;
1270 for ( QPair<LayerRenderJob *, int> p : job.maskJobs )
1272 QImage *maskImage =
static_cast<QImage *
>( p.first ? p.first->maskPaintDevice.get() : labelJob.maskPaintDevices[p.second].get() );
1275 maskPainter = p.first ? p.first->maskPainter.get() : labelJob.maskPainters[ p.second ].get();
1279 maskPainter->drawImage( 0, 0, *maskImage );
1284 if ( ! job.maskJobs.isEmpty() )
1287 QPair<LayerRenderJob *, int> p = *job.maskJobs.begin();
1288 if ( isRasterRendering )
1290 QImage *maskImage =
static_cast<QImage *
>( p.first ? p.first->maskPaintDevice.get() : labelJob.maskPaintDevices[p.second].get() );
1293 QPainter *painter = job.context()->painter();
1295 painter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
1300 QImage maskBinAlpha = maskImage->createMaskFromColor( 0 );
1301 QVector<QRgb> mswTable;
1302 mswTable.push_back( qRgba( 0, 0, 0, 255 ) );
1303 mswTable.push_back( qRgba( 0, 0, 0, 0 ) );
1304 maskBinAlpha.setColorTable( mswTable );
1305 painter->drawImage( 0, 0, maskBinAlpha );
1309 QPainter tempPainter;
1312 QPainter *painter1 = job.firstPassJob->context()->painter();
1315 tempPainter.begin( job.firstPassJob->img );
1316 painter1 = &tempPainter;
1320 painter1->setCompositionMode( QPainter::CompositionMode_DestinationOut );
1321 painter1->drawImage( 0, 0, *maskImage );
1324 painter1->setCompositionMode( QPainter::CompositionMode_DestinationOver );
1325 painter1->drawImage( 0, 0, *job.img );
1330 job.firstPassJob->picture = std::move( job.picture );
1331 job.picture =
nullptr;
1342 QMultiMap<int, QString> elapsed;
1343 for (
const LayerRenderJob &job : jobs )
1344 elapsed.insert( job.renderingTime, job.layerId );
1345 for (
const LayerRenderJob &job : secondPassJobs )
1346 elapsed.insert( job.renderingTime, job.layerId + QString(
" (second pass)" ) );
1348 elapsed.insert( labelJob.renderingTime, tr(
"Labeling" ) );
1350 QList<int> tt( elapsed.uniqueKeys() );
1351 std::sort( tt.begin(), tt.end(), std::greater<int>() );
1352 for (
int t : std::as_const( tt ) )
1354 QgsMessageLog::logMessage( tr(
"%1 ms: %2" ).arg( t ).arg( QStringList( elapsed.values( t ) ).join( QLatin1String(
", " ) ) ), tr(
"Rendering" ) );
1367 painter->setCompositionMode( QPainter::CompositionMode_SourceOver );
1371 if ( labelingEngine2 )
1373 labelingEngine2->
run( renderContext );
1376 QgsDebugMsgLevel( QStringLiteral(
"Draw labeling took (seconds): %1" ).arg( t.elapsed() / 1000. ), 2 );
1381 Q_UNUSED( settings )
1383 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.
A boolean settings entry.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
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)
QHash< QString, QgsMaskedLayer > QgsMaskedLayers
masked layers where key is the layer id