QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsmaprenderertask.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaprenderertask.h
3 -------------------------
4 begin : Apr 2017
5 copyright : (C) 2017 by Mathieu Pellerin
6 email : nirvn dot asia at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgsannotation.h"
20#include "qgsmaprenderertask.h"
21#include "moc_qgsmaprenderertask.cpp"
22#include "qgsmapsettingsutils.h"
23#include "qgsogrutils.h"
24#include "qgslogger.h"
28#include "qgsfeaturerequest.h"
29#include "qgsvectorlayer.h"
30
31#include <QFile>
32#include <QImageWriter>
33#include <QTextStream>
34#include <QTimeZone>
35#include <QPdfWriter>
36
37#include "gdal.h"
38#include "cpl_conv.h"
39
41
42class QgsMapRendererTaskGeospatialPdfExporter : public QgsAbstractGeospatialPdfExporter
43{
44
45 public:
46
47 QgsMapRendererTaskGeospatialPdfExporter( const QgsMapSettings &ms )
48 {
49 // collect details upfront, while we are still in the main thread
50 const QList< QgsMapLayer * > layers = ms.layers();
51 for ( const QgsMapLayer *layer : layers )
52 {
53 VectorComponentDetail detail;
54 detail.name = layer->name();
55 detail.mapLayerId = layer->id();
56 if ( const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer * >( layer ) )
57 {
58 detail.displayAttribute = vl->displayField();
59 }
60 mLayerDetails[ layer->id() ] = detail;
61 }
62 }
63
64 private:
65
66 QgsAbstractGeospatialPdfExporter::VectorComponentDetail componentDetailForLayerId( const QString &layerId ) override
67 {
68 return mLayerDetails.value( layerId );
69 }
70
71 QMap< QString, VectorComponentDetail > mLayerDetails;
72};
73
74
75class QgsMapRendererTaskRenderedFeatureHandler : public QgsRenderedFeatureHandlerInterface
76{
77 public:
78
79 QgsMapRendererTaskRenderedFeatureHandler( QgsMapRendererTaskGeospatialPdfExporter *exporter, const QgsMapSettings &settings )
80 : mExporter( exporter )
81 , mMapSettings( settings )
82 {
83 // PDF coordinate space uses a hardcoded DPI of 72, also vertical dimension is flipped from QGIS dimension
84 const double pageHeightPdfUnits = settings.outputSize().height() * 72.0 / settings.outputDpi();
85 mTransform = QTransform::fromTranslate( 0, pageHeightPdfUnits ).scale( 72.0 / mMapSettings.outputDpi(), -72.0 / mMapSettings.outputDpi() );
86 }
87
88 void handleRenderedFeature( const QgsFeature &feature, const QgsGeometry &renderedBounds, const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext &context ) override
89 {
90 // is it a hack retrieving the layer ID from an expression context like this? possibly... BUT
91 // the alternative is adding a layer ID member to QgsRenderContext, and that's just asking for people to abuse it
92 // and use it to retrieve QgsMapLayers mid-way through a render operation. Lesser of two evils it is!
93 const QString layerId = context.renderContext.expressionContext().variable( QStringLiteral( "layer_id" ) ).toString();
94
95 QgsGeometry transformed = renderedBounds;
96 transformed.transform( mTransform );
97
98 // always convert to multitype, to make things consistent
99 transformed.convertToMultiType();
100
101 mExporter->pushRenderedFeature( layerId, QgsAbstractGeospatialPdfExporter::RenderedFeature( feature, transformed ) );
102 }
103
104 QSet<QString> usedAttributes( QgsVectorLayer *, const QgsRenderContext & ) const override
105 {
106 return QSet< QString >() << QgsFeatureRequest::ALL_ATTRIBUTES;
107 }
108
109 private:
110
111 QgsMapRendererTaskGeospatialPdfExporter *mExporter = nullptr;
112 QgsMapSettings mMapSettings;
114 QTransform mTransform;
115
116};
117
119
120QgsMapRendererTask::QgsMapRendererTask( const QgsMapSettings &ms, const QString &fileName, const QString &fileFormat, const bool forceRaster, QgsTask::Flags flags,
121 const bool geoPDF, const QgsAbstractGeospatialPdfExporter::ExportDetails &geospatialPdfExportDetails )
122 : QgsTask( fileFormat == QLatin1String( "PDF" ) ? tr( "Saving as PDF" ) : tr( "Saving as image" ), flags )
123 , mMapSettings( ms )
124 , mFileName( fileName )
125 , mFileFormat( fileFormat )
126 , mForceRaster( forceRaster )
127 , mGeospatialPDF( geoPDF && mFileFormat == QLatin1String( "PDF" ) && QgsAbstractGeospatialPdfExporter::geospatialPDFCreationAvailable() )
128 , mGeospatialPdfExportDetails( geospatialPdfExportDetails )
129{
130 if ( mFileFormat == QLatin1String( "PDF" ) && !qgsDoubleNear( mMapSettings.devicePixelRatio(), 1.0 ) )
131 {
132 mMapSettings.setOutputSize( mMapSettings.outputSize() * mMapSettings.devicePixelRatio() );
133 mMapSettings.setOutputDpi( mMapSettings.outputDpi() * mMapSettings.devicePixelRatio() );
134 mMapSettings.setDevicePixelRatio( 1.0 );
135 }
136 prepare();
137}
138
140 : QgsTask( tr( "Rendering to painter" ) )
141 , mMapSettings( ms )
142 , mPainter( p )
143{
144 prepare();
145}
146
148
149void QgsMapRendererTask::addAnnotations( const QList< QgsAnnotation * > &annotations )
150{
151 qDeleteAll( mAnnotations );
152 mAnnotations.clear();
153
154 const auto constAnnotations = annotations;
155 for ( const QgsAnnotation *a : constAnnotations )
156 {
157 mAnnotations << a->clone();
158 }
159}
160
161void QgsMapRendererTask::addDecorations( const QList< QgsMapDecoration * > &decorations )
162{
163 mDecorations = decorations;
164}
165
166
168{
169 mJobMutex.lock();
170 if ( mJob )
171 mJob->cancelWithoutBlocking();
172 mJobMutex.unlock();
173
175}
176
178{
179 if ( mErrored )
180 return false;
181
182 if ( mGeospatialPDF )
183 {
184 QList< QgsAbstractGeospatialPdfExporter::ComponentLayerDetail > pdfComponents;
185
186 QgsMapRendererStagedRenderJob *job = static_cast< QgsMapRendererStagedRenderJob * >( mJob.get() );
187 int outputLayer = 1;
188 while ( !job->isFinished() )
189 {
191
192 component.name = QStringLiteral( "layer_%1" ).arg( outputLayer );
193 component.mapLayerId = job->currentLayerId();
194 component.opacity = job->currentLayerOpacity();
196 component.sourcePdfPath = mGeospatialPdfExporter->generateTemporaryFilepath( QStringLiteral( "layer_%1.pdf" ).arg( outputLayer ) );
197 pdfComponents << component;
198
199 QPdfWriter pdfWriter( component.sourcePdfPath );
200 pdfWriter.setPageOrientation( QPageLayout::Orientation::Portrait );
201 // paper size needs to be given in millimeters in order to be able to set a resolution to pass onto the map renderer
202 const QSizeF outputSize = mMapSettings.outputSize();
203 const QPageSize pageSize( outputSize * 25.4 / mMapSettings.outputDpi(), QPageSize::Unit::Millimeter );
204 pdfWriter.setPageSize( pageSize );
205 pdfWriter.setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
206 pdfWriter.setResolution( static_cast<int>( mMapSettings.outputDpi() ) );
207
208 QPainter p( &pdfWriter );
209 job->renderCurrentPart( &p );
210 p.end();
211
212 outputLayer++;
213 job->nextPart();
214 }
215 QgsAbstractGeospatialPdfExporter::ExportDetails exportDetails = mGeospatialPdfExportDetails;
216 const double pageWidthMM = mMapSettings.outputSize().width() * 25.4 / mMapSettings.outputDpi();
217 const double pageHeightMM = mMapSettings.outputSize().height() * 25.4 / mMapSettings.outputDpi();
218 exportDetails.pageSizeMm = QSizeF( pageWidthMM, pageHeightMM );
219 exportDetails.dpi = mMapSettings.outputDpi();
220
221 exportDetails.layerIdToPdfLayerTreeNameMap = mLayerIdToLayerNameMap;
222 exportDetails.layerOrder = mMapLayerOrder;
223
224 if ( mSaveWorldFile )
225 {
226 // setup georeferencing
228 georef.crs = mMapSettings.destinationCrs();
229 georef.pageBoundsMm = QgsRectangle( 0, 0, pageWidthMM, pageHeightMM );
230 georef.controlPoints.reserve( 4 );
232 georef.controlPoints << QgsAbstractGeospatialPdfExporter::ControlPoint( QgsPointXY( pageWidthMM, 0 ), mMapSettings.mapToPixel().toMapCoordinates( mMapSettings.outputSize().width(), 0 ) );
233 georef.controlPoints << QgsAbstractGeospatialPdfExporter::ControlPoint( QgsPointXY( pageWidthMM, pageHeightMM ), mMapSettings.mapToPixel().toMapCoordinates( mMapSettings.outputSize().width(), mMapSettings.outputSize().height() ) );
234 georef.controlPoints << QgsAbstractGeospatialPdfExporter::ControlPoint( QgsPointXY( 0, pageHeightMM ), mMapSettings.mapToPixel().toMapCoordinates( 0, mMapSettings.outputSize().height() ) );
235 exportDetails.georeferencedSections << georef;
236 }
237
238 const bool res = mGeospatialPdfExporter->finalize( pdfComponents, mFileName, exportDetails );
239 mGeospatialPdfExporter.reset();
240 mTempPainter.reset();
241 mPdfWriter.reset();
242 return res;
243 }
244 else
245 static_cast< QgsMapRendererCustomPainterJob *>( mJob.get() )->renderPrepared();
246
247 mJobMutex.lock();
248 mJob.reset( nullptr );
249 mJobMutex.unlock();
250
251 if ( isCanceled() )
252 return false;
253
254 QgsRenderContext context = QgsRenderContext::fromMapSettings( mMapSettings );
255 context.setPainter( mDestPainter );
256
257 const auto constMDecorations = mDecorations;
258 for ( QgsMapDecoration *decoration : constMDecorations )
259 {
260 decoration->render( mMapSettings, context );
261 }
262
263 const auto constMAnnotations = mAnnotations;
264 for ( QgsAnnotation *annotation : constMAnnotations )
265 {
266 if ( isCanceled() )
267 return false;
268
269 if ( !annotation || !annotation->isVisible() )
270 {
271 continue;
272 }
273 if ( annotation->mapLayer() && !mMapSettings.layers().contains( annotation->mapLayer() ) )
274 {
275 continue;
276 }
277
278 const QgsScopedQPainterState painterState( context.painter() );
280
281 double itemX, itemY;
282 if ( annotation->hasFixedMapPosition() )
283 {
284 itemX = mMapSettings.outputSize().width() * ( annotation->mapPosition().x() - mMapSettings.extent().xMinimum() ) / mMapSettings.extent().width();
285 itemY = mMapSettings.outputSize().height() * ( 1 - ( annotation->mapPosition().y() - mMapSettings.extent().yMinimum() ) / mMapSettings.extent().height() );
286 }
287 else
288 {
289 itemX = annotation->relativePosition().x() * mMapSettings.outputSize().width();
290 itemY = annotation->relativePosition().y() * mMapSettings.outputSize().height();
291 }
292
293 context.painter()->translate( itemX, itemY );
294
295 annotation->render( context );
296 }
297
298 if ( !mFileName.isEmpty() )
299 {
300 mDestPainter->end();
301
302 if ( mFileFormat == QLatin1String( "PDF" ) )
303 {
304 if ( mForceRaster )
305 {
306 QPainter pp;
307 pp.begin( mPdfWriter.get() );
308 const QRectF rect( 0, 0, mImage.width(), mImage.height() );
309 pp.drawImage( rect, mImage, rect );
310 pp.end();
311 }
312
313 if ( mSaveWorldFile || mExportMetadata )
314 {
315 CPLSetThreadLocalConfigOption( "GDAL_PDF_DPI", QString::number( mMapSettings.outputDpi() ).toLocal8Bit().constData() );
316 const gdal::dataset_unique_ptr outputDS( GDALOpen( mFileName.toUtf8().constData(), GA_Update ) );
317 if ( outputDS )
318 {
319 if ( mSaveWorldFile )
320 {
321 double a, b, c, d, e, f;
322 QgsMapSettingsUtils::worldFileParameters( mMapSettings, a, b, c, d, e, f );
323 c -= 0.5 * a;
324 c -= 0.5 * b;
325 f -= 0.5 * d;
326 f -= 0.5 * e;
327 double geoTransform[6] = { c, a, b, f, d, e };
328 GDALSetGeoTransform( outputDS.get(), geoTransform );
329 GDALSetProjection( outputDS.get(), mMapSettings.destinationCrs().toWkt( Qgis::CrsWktVariant::PreferredGdal ).toLocal8Bit().constData() );
330 }
331
332 if ( mExportMetadata )
333 {
334 QString creationDateString;
335 const QDateTime creationDateTime = mGeospatialPdfExportDetails.creationDateTime;
336 if ( creationDateTime.isValid() )
337 {
338 creationDateString = QStringLiteral( "D:%1" ).arg( mGeospatialPdfExportDetails.creationDateTime.toString( QStringLiteral( "yyyyMMddHHmmss" ) ) );
339 if ( creationDateTime.timeZone().isValid() )
340 {
341 int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
342 creationDateString += ( offsetFromUtc >= 0 ) ? '+' : '-';
343 offsetFromUtc = std::abs( offsetFromUtc );
344 const int offsetHours = offsetFromUtc / 3600;
345 const int offsetMins = ( offsetFromUtc % 3600 ) / 60;
346 creationDateString += QStringLiteral( "%1'%2'" ).arg( offsetHours ).arg( offsetMins );
347 }
348 }
349 GDALSetMetadataItem( outputDS.get(), "CREATION_DATE", creationDateString.toUtf8().constData(), nullptr );
350
351 GDALSetMetadataItem( outputDS.get(), "AUTHOR", mGeospatialPdfExportDetails.author.toUtf8().constData(), nullptr );
352 const QString creator = QStringLiteral( "QGIS %1" ).arg( Qgis::version() );
353 GDALSetMetadataItem( outputDS.get(), "CREATOR", creator.toUtf8().constData(), nullptr );
354 GDALSetMetadataItem( outputDS.get(), "PRODUCER", creator.toUtf8().constData(), nullptr );
355 GDALSetMetadataItem( outputDS.get(), "SUBJECT", mGeospatialPdfExportDetails.subject.toUtf8().constData(), nullptr );
356 GDALSetMetadataItem( outputDS.get(), "TITLE", mGeospatialPdfExportDetails.title.toUtf8().constData(), nullptr );
357
358 const QgsAbstractMetadataBase::KeywordMap keywords = mGeospatialPdfExportDetails.keywords;
359 QStringList allKeywords;
360 for ( auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
361 {
362 allKeywords.append( QStringLiteral( "%1: %2" ).arg( it.key(), it.value().join( ',' ) ) );
363 }
364 const QString keywordString = allKeywords.join( ';' );
365 GDALSetMetadataItem( outputDS.get(), "KEYWORDS", keywordString.toUtf8().constData(), nullptr );
366 }
367 }
368 CPLSetThreadLocalConfigOption( "GDAL_PDF_DPI", nullptr );
369 }
370 }
371 else if ( mFileFormat != QLatin1String( "PDF" ) )
372 {
373 QImageWriter writer( mFileName, mFileFormat.toLocal8Bit().data() );
374 if ( mFileFormat.compare( QLatin1String( "TIF" ), Qt::CaseInsensitive ) == 0 || mFileFormat.compare( QLatin1String( "TIFF" ), Qt::CaseInsensitive ) == 0 )
375 {
376 // Enable LZW compression
377 writer.setCompression( 1 );
378 }
379 const bool success = writer.write( mImage );
380 if ( !success )
381 {
382 mError = ImageSaveFail;
383 return false;
384 }
385
386 if ( mSaveWorldFile )
387 {
388 const QFileInfo info = QFileInfo( mFileName );
389
390 // build the world file name
391 const QString outputSuffix = info.suffix();
392 bool skipWorldFile = false;
393 if ( outputSuffix.compare( QLatin1String( "TIF" ), Qt::CaseInsensitive ) == 0 || outputSuffix.compare( QLatin1String( "TIFF" ), Qt::CaseInsensitive ) == 0 )
394 {
395 const gdal::dataset_unique_ptr outputDS( GDALOpen( mFileName.toUtf8().constData(), GA_Update ) );
396 if ( outputDS )
397 {
398 skipWorldFile = true;
399 double a, b, c, d, e, f;
400 QgsMapSettingsUtils::worldFileParameters( mMapSettings, a, b, c, d, e, f );
401 c -= 0.5 * a;
402 c -= 0.5 * b;
403 f -= 0.5 * d;
404 f -= 0.5 * e;
405 double geoTransform[] = { c, a, b, f, d, e };
406 GDALSetGeoTransform( outputDS.get(), geoTransform );
407 GDALSetProjection( outputDS.get(), mMapSettings.destinationCrs().toWkt( Qgis::CrsWktVariant::PreferredGdal ).toLocal8Bit().constData() );
408 }
409 }
410
411 if ( !skipWorldFile )
412 {
413 const QString worldFileName = info.absolutePath() + '/' + info.completeBaseName() + '.'
414 + outputSuffix.at( 0 ) + outputSuffix.at( info.suffix().size() - 1 ) + 'w';
415 QFile worldFile( worldFileName );
416
417 if ( worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) //don't use QIODevice::Text
418 {
419 QTextStream stream( &worldFile );
420 stream << QgsMapSettingsUtils::worldFileContent( mMapSettings );
421 }
422 }
423 }
424 }
425 }
426
427 mTempPainter.reset();
428 mPdfWriter.reset();
429
430 return true;
431}
432
434{
435 qDeleteAll( mAnnotations );
436 mAnnotations.clear();
437
438 if ( result )
439 emit renderingComplete();
440 else
441 emit errorOccurred( mError );
442}
443
444void QgsMapRendererTask::prepare()
445{
446 if ( mGeospatialPDF )
447 {
448 mGeospatialPdfExporter = std::make_unique< QgsMapRendererTaskGeospatialPdfExporter >( mMapSettings );
449 if ( mGeospatialPdfExportDetails.includeFeatures )
450 {
451 mRenderedFeatureHandler = std::make_unique< QgsMapRendererTaskRenderedFeatureHandler >( static_cast< QgsMapRendererTaskGeospatialPdfExporter * >( mGeospatialPdfExporter.get() ), mMapSettings );
452 mMapSettings.addRenderedFeatureHandler( mRenderedFeatureHandler.get() );
453 }
454
455 const QList< QgsMapLayer * > layers = mMapSettings.layers();
456 for ( const QgsMapLayer *layer : layers )
457 {
458 mLayerIdToLayerNameMap.insert( layer->id(), layer->name() );
459 mMapLayerOrder << layer->id();
460 }
461
463 mJob->start();
464 return;
465 }
466
467 mDestPainter = mPainter;
468
469 if ( mFileFormat == QLatin1String( "PDF" ) )
470 {
471 mPdfWriter.reset( new QPdfWriter( mFileName ) );
472 mPdfWriter->setPageOrientation( QPageLayout::Orientation::Portrait );
473 // paper size needs to be given in millimeters in order to be able to set a resolution to pass onto the map renderer
474 const QSizeF outputSize = mMapSettings.outputSize();
475 const QPageSize pageSize( outputSize * 25.4 / mMapSettings.outputDpi(), QPageSize::Unit::Millimeter );
476 mPdfWriter->setPageSize( pageSize );
477 mPdfWriter->setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
478 mPdfWriter->setResolution( static_cast<int>( mMapSettings.outputDpi() ) );
479
480 if ( !mForceRaster )
481 {
482 mTempPainter.reset( new QPainter( mPdfWriter.get() ) );
483 mDestPainter = mTempPainter.get();
484 }
485 }
486
487 if ( !mDestPainter )
488 {
489 // save rendered map to an image file
490 mImage = QImage( mMapSettings.outputSize() * mMapSettings.devicePixelRatio(), QImage::Format_ARGB32 );
491 if ( mImage.isNull() )
492 {
493 mErrored = true;
494 mError = ImageAllocationFail;
495 return;
496 }
497
498 mImage.setDevicePixelRatio( mMapSettings.devicePixelRatio() );
499 mImage.setDotsPerMeterX( 1000 * mMapSettings.outputDpi() / 25.4 );
500 mImage.setDotsPerMeterY( 1000 * mMapSettings.outputDpi() / 25.4 );
501
502 mTempPainter.reset( new QPainter( &mImage ) );
503 mDestPainter = mTempPainter.get();
504 }
505
506 if ( !mDestPainter )
507 {
508 mErrored = true;
509 return;
510 }
511
512 mJob.reset( new QgsMapRendererCustomPainterJob( mMapSettings, mDestPainter ) );
513 static_cast< QgsMapRendererCustomPainterJob *>( mJob.get() )->prepare();
514}
static QString version()
Version string.
Definition qgis.cpp:259
@ PreferredGdal
Preferred format for conversion of CRS to WKT for use with the GDAL library.
Abstract base class for Geospatial PDF exporters.
QMap< QString, QStringList > KeywordMap
Map of vocabulary string to keyword list.
Abstract base class for annotation items which are drawn over a map.
QString toWkt(Qgis::CrsWktVariant variant=Qgis::CrsWktVariant::Wkt1Gdal, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
A geometry is the spatial representation of a feature.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Interface for map decorations.
Base class for all map layer types.
Definition qgsmaplayer.h:76
Job implementation that renders everything sequentially using a custom painter.
Render job implementation that renders maps in stages, allowing different stages (e....
double currentLayerOpacity() const
Returns the opacity for the current layer about to be rendered in the next render operation.
@ RenderLabelsByMapLayer
Labels should be rendered in individual stages by map layer. This allows separation of labels belongi...
QPainter::CompositionMode currentLayerCompositionMode() const
Returns the composition mode for the current layer about to be rendered in the next render operation.
QString currentLayerId() const
Returns the ID of the current layer about to be rendered in the next render operation.
bool isFinished() const
Returns true if the job is finished, and nothing remains to render.
bool nextPart()
Iterates to the next part to render.
bool renderCurrentPart(QPainter *painter)
Renders the current part of the map to the specified painter.
void addDecorations(const QList< QgsMapDecoration * > &decorations)
Adds decorations to be rendered on the map.
bool run() override
Performs the task's operation.
void errorOccurred(int error)
Emitted when map rendering failed.
@ ImageSaveFail
Image save failure.
@ ImageAllocationFail
Image allocation failure.
QgsMapRendererTask(const QgsMapSettings &ms, const QString &fileName, const QString &fileFormat=QString("PNG"), bool forceRaster=false, QgsTask::Flags flags=QgsTask::CanCancel, bool geospatialPdf=false, const QgsAbstractGeospatialPdfExporter::ExportDetails &geospatialPdfExportDetails=QgsAbstractGeospatialPdfExporter::ExportDetails())
Constructor for QgsMapRendererTask to render a map to an image file.
void addAnnotations(const QList< QgsAnnotation * > &annotations)
Adds annotations to be rendered on the map.
void finished(bool result) override
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
~QgsMapRendererTask() override
void cancel() override
Notifies the task that it should terminate.
void renderingComplete()
Emitted when the map rendering is successfully completed.
static void worldFileParameters(const QgsMapSettings &mapSettings, double &a, double &b, double &c, double &d, double &e, double &f)
Computes the six parameters of a world file.
static QString worldFileContent(const QgsMapSettings &mapSettings)
Creates the content of a world file.
The QgsMapSettings class contains configuration for rendering of the map.
QList< QgsMapLayer * > layers(bool expandGroupLayers=false) const
Returns the list of layers which will be rendered in the map.
void addRenderedFeatureHandler(QgsRenderedFeatureHandlerInterface *handler)
Adds a rendered feature handler to use while rendering the map settings.
void setDevicePixelRatio(float dpr)
Sets the device pixel ratio.
void setOutputDpi(double dpi)
Sets the dpi (dots per inch) used for conversion between real world units (e.g.
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.
QgsRectangle extent() const
Returns geographical coordinates of the rectangle that should be rendered.
double outputDpi() const
Returns the DPI (dots per inch) used for conversion between real world units (e.g.
void setOutputSize(QSize size)
Sets the size of the resulting map image, in pixels.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
A class to represent a 2D point.
Definition qgspointxy.h:60
A rectangle specified with double values.
double xMinimum
double yMinimum
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
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
An interface for classes which provider custom handlers for features rendered as part of a map render...
virtual QSet< QString > usedAttributes(QgsVectorLayer *layer, const QgsRenderContext &context) const
Returns a list of attributes required by this handler, for the specified layer.
virtual void handleRenderedFeature(const QgsFeature &feature, const QgsGeometry &renderedBounds, const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext &context)=0
Called whenever a feature is rendered during a map render job.
Scoped object for saving and restoring a QPainter object's state.
Abstract base class for long running background tasks.
QFlags< Flag > Flags
virtual void cancel()
Notifies the task that it should terminate.
bool isCanceled() const
Will return true if task should terminate ASAP.
Represents a vector layer which manages a vector based data sets.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:6066
Contains details of a particular input component to be used during PDF composition.
QString mapLayerId
Associated map layer ID, or an empty string if this component layer is not associated with a map laye...
QString name
User-friendly name for the generated PDF layer.
QPainter::CompositionMode compositionMode
Component composition mode.
QString sourcePdfPath
File path to the (already created) PDF to use as the source for this component layer.
Contains details of a control point used during georeferencing Geospatial PDF outputs.
QList< QgsAbstractGeospatialPdfExporter::GeoReferencedSection > georeferencedSections
List of georeferenced sections.
QStringList layerOrder
Optional list of layer IDs, in the order desired to appear in the generated Geospatial PDF file.
QMap< QString, QString > layerIdToPdfLayerTreeNameMap
Optional map of map layer ID to custom layer tree name to show in the created PDF file.
QgsAbstractMetadataBase::KeywordMap keywords
Metadata keyword map.
QDateTime creationDateTime
Metadata creation datetime.
bool includeFeatures
true if feature vector information (such as attributes) should be exported.
QgsRectangle pageBoundsMm
Bounds of the georeferenced section on the page, in millimeters.
QgsCoordinateReferenceSystem crs
Coordinate reference system for georeferenced section.
QList< QgsAbstractGeospatialPdfExporter::ControlPoint > controlPoints
List of control points corresponding to this georeferenced section.
Contains information about a feature rendered inside the PDF.
Contains information relating to a single PDF layer in the Geospatial PDF export.
const QgsRenderContext & renderContext
The render context which was used while rendering feature.