QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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"
19 #include "qgsannotationmanager.h"
20 #include "qgsmaprenderertask.h"
21 #include "qgsmapsettingsutils.h"
22 #include "qgsogrutils.h"
23 #include "qgslogger.h"
27 #include "qgsfeaturerequest.h"
28 #include "qgsvectorlayer.h"
29 
30 #include <QFile>
31 #include <QTextStream>
32 #ifndef QT_NO_PRINTER
33 #include <QPrinter>
34 #endif
35 
36 #include "gdal.h"
37 #include "cpl_conv.h"
38 
40 
41 class QgsMapRendererTaskGeoPdfExporter : public QgsAbstractGeoPdfExporter
42 {
43 
44  public:
45 
46  QgsMapRendererTaskGeoPdfExporter( const QgsMapSettings &ms )
47  {
48  // collect details upfront, while we are still in the main thread
49  const QList< QgsMapLayer * > layers = ms.layers();
50  for ( const QgsMapLayer *layer : layers )
51  {
52  VectorComponentDetail detail;
53  detail.name = layer->name();
54  detail.mapLayerId = layer->id();
55  if ( const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer * >( layer ) )
56  {
57  detail.displayAttribute = vl->displayField();
58  }
59  mLayerDetails[ layer->id() ] = detail;
60  }
61  }
62 
63  private:
64 
65  QgsAbstractGeoPdfExporter::VectorComponentDetail componentDetailForLayerId( const QString &layerId ) override
66  {
67  return mLayerDetails.value( layerId );
68  }
69 
70  QMap< QString, VectorComponentDetail > mLayerDetails;
71 };
72 
73 
74 class QgsMapRendererTaskRenderedFeatureHandler : public QgsRenderedFeatureHandlerInterface
75 {
76  public:
77 
78  QgsMapRendererTaskRenderedFeatureHandler( QgsMapRendererTaskGeoPdfExporter *exporter, const QgsMapSettings &settings )
79  : mExporter( exporter )
80  , mMapSettings( settings )
81  {
82  // PDF coordinate space uses a hardcoded DPI of 72, also vertical dimension is flipped from QGIS dimension
83  const double pageHeightPdfUnits = settings.outputSize().height() * 72.0 / settings.outputDpi();
84  mTransform = QTransform::fromTranslate( 0, pageHeightPdfUnits ).scale( 72.0 / mMapSettings.outputDpi(), -72.0 / mMapSettings.outputDpi() );
85  }
86 
87  void handleRenderedFeature( const QgsFeature &feature, const QgsGeometry &renderedBounds, const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext &context ) override
88  {
89  // is it a hack retrieving the layer ID from an expression context like this? possibly... BUT
90  // the alternative is adding a layer ID member to QgsRenderContext, and that's just asking for people to abuse it
91  // and use it to retrieve QgsMapLayers mid-way through a render operation. Lesser of two evils it is!
92  const QString layerId = context.renderContext.expressionContext().variable( QStringLiteral( "layer_id" ) ).toString();
93 
94  QgsGeometry transformed = renderedBounds;
95  transformed.transform( mTransform );
96 
97  // always convert to multitype, to make things consistent
98  transformed.convertToMultiType();
99 
100  mExporter->pushRenderedFeature( layerId, QgsAbstractGeoPdfExporter::RenderedFeature( feature, transformed ) );
101  }
102 
103  QSet<QString> usedAttributes( QgsVectorLayer *, const QgsRenderContext & ) const override
104  {
105  return QSet< QString >() << QgsFeatureRequest::ALL_ATTRIBUTES;
106  }
107 
108  private:
109 
110  QgsMapRendererTaskGeoPdfExporter *mExporter = nullptr;
111  QgsMapSettings mMapSettings;
113  QTransform mTransform;
114 
115 };
116 
118 
119 QgsMapRendererTask::QgsMapRendererTask( const QgsMapSettings &ms, const QString &fileName, const QString &fileFormat, const bool forceRaster,
120  const bool geoPDF, const QgsAbstractGeoPdfExporter::ExportDetails &geoPdfExportDetails )
121  : QgsTask( fileFormat == QStringLiteral( "PDF" ) ? tr( "Saving as PDF" ) : tr( "Saving as image" ) )
122  , mMapSettings( ms )
123  , mFileName( fileName )
124  , mFileFormat( fileFormat )
125  , mForceRaster( forceRaster )
126  , mGeoPDF( geoPDF && mFileFormat == QStringLiteral( "PDF" ) && QgsAbstractGeoPdfExporter::geoPDFCreationAvailable() )
127  , mGeoPdfExportDetails( geoPdfExportDetails )
128 {
129  prepare();
130 }
131 
133  : QgsTask( tr( "Rendering to painter" ) )
134  , mMapSettings( ms )
135  , mPainter( p )
136 {
137  prepare();
138 }
139 
141 
142 void QgsMapRendererTask::addAnnotations( const QList< QgsAnnotation * > &annotations )
143 {
144  qDeleteAll( mAnnotations );
145  mAnnotations.clear();
146 
147  const auto constAnnotations = annotations;
148  for ( const QgsAnnotation *a : constAnnotations )
149  {
150  mAnnotations << a->clone();
151  }
152 }
153 
154 void QgsMapRendererTask::addDecorations( const QList< QgsMapDecoration * > &decorations )
155 {
156  mDecorations = decorations;
157 }
158 
159 
161 {
162  mJobMutex.lock();
163  if ( mJob )
164  mJob->cancelWithoutBlocking();
165  mJobMutex.unlock();
166 
167  QgsTask::cancel();
168 }
169 
171 {
172  if ( mErrored )
173  return false;
174 
175  if ( mGeoPDF )
176  {
177 #ifdef QT_NO_PRINTER
178  return false;
179 #else
180  QList< QgsAbstractGeoPdfExporter::ComponentLayerDetail > pdfComponents;
181 
182  QgsMapRendererStagedRenderJob *job = static_cast< QgsMapRendererStagedRenderJob * >( mJob.get() );
183  int outputLayer = 1;
184  while ( !job->isFinished() )
185  {
187  component.name = QStringLiteral( "layer_%1" ).arg( outputLayer );
188  component.mapLayerId = job->currentLayerId();
189  component.sourcePdfPath = mGeoPdfExporter->generateTemporaryFilepath( QStringLiteral( "layer_%1.pdf" ).arg( outputLayer ) );
190  pdfComponents << component;
191 
192  QPrinter printer;
193  printer.setOutputFileName( component.sourcePdfPath );
194  printer.setOutputFormat( QPrinter::PdfFormat );
195  printer.setOrientation( QPrinter::Portrait );
196  // paper size needs to be given in millimeters in order to be able to set a resolution to pass onto the map renderer
197  QSizeF outputSize = mMapSettings.outputSize();
198  printer.setPaperSize( outputSize * 25.4 / mMapSettings.outputDpi(), QPrinter::Millimeter );
199  printer.setPageMargins( 0, 0, 0, 0, QPrinter::Millimeter );
200  printer.setResolution( mMapSettings.outputDpi() );
201 
202  QPainter p( &printer );
203  job->renderCurrentPart( &p );
204  p.end();
205 
206  outputLayer++;
207  job->nextPart();
208  }
209  QgsAbstractGeoPdfExporter::ExportDetails exportDetails = mGeoPdfExportDetails;
210  const double pageWidthMM = mMapSettings.outputSize().width() * 25.4 / mMapSettings.outputDpi();
211  const double pageHeightMM = mMapSettings.outputSize().height() * 25.4 / mMapSettings.outputDpi();
212  exportDetails.pageSizeMm = QSizeF( pageWidthMM, pageHeightMM );
213  exportDetails.dpi = mMapSettings.outputDpi();
214 
215  if ( mSaveWorldFile )
216  {
217  // setup georeferencing
219  georef.crs = mMapSettings.destinationCrs();
220  georef.pageBoundsMm = QgsRectangle( 0, 0, pageWidthMM, pageHeightMM );
221  georef.controlPoints.reserve( 4 );
223  georef.controlPoints << QgsAbstractGeoPdfExporter::ControlPoint( QgsPointXY( pageWidthMM, 0 ), mMapSettings.mapToPixel().toMapCoordinates( mMapSettings.outputSize().width(), 0 ) );
224  georef.controlPoints << QgsAbstractGeoPdfExporter::ControlPoint( QgsPointXY( pageWidthMM, pageHeightMM ), mMapSettings.mapToPixel().toMapCoordinates( mMapSettings.outputSize().width(), mMapSettings.outputSize().height() ) );
225  georef.controlPoints << QgsAbstractGeoPdfExporter::ControlPoint( QgsPointXY( 0, pageHeightMM ), mMapSettings.mapToPixel().toMapCoordinates( 0, mMapSettings.outputSize().height() ) );
226  exportDetails.georeferencedSections << georef;
227  }
228 
229  const bool res = mGeoPdfExporter->finalize( pdfComponents, mFileName, exportDetails );
230  mGeoPdfExporter.reset();
231  mTempPainter.reset();
232  mPrinter.reset();
233  return res;
234 #endif
235  }
236  else
237  static_cast< QgsMapRendererCustomPainterJob *>( mJob.get() )->renderPrepared();
238 
239  mJobMutex.lock();
240  mJob.reset( nullptr );
241  mJobMutex.unlock();
242 
243  if ( isCanceled() )
244  return false;
245 
246  QgsRenderContext context = QgsRenderContext::fromMapSettings( mMapSettings );
247  context.setPainter( mDestPainter );
248 
249  const auto constMDecorations = mDecorations;
250  for ( QgsMapDecoration *decoration : constMDecorations )
251  {
252  decoration->render( mMapSettings, context );
253  }
254 
255  const auto constMAnnotations = mAnnotations;
256  for ( QgsAnnotation *annotation : constMAnnotations )
257  {
258  if ( isCanceled() )
259  return false;
260 
261  if ( !annotation || !annotation->isVisible() )
262  {
263  continue;
264  }
265  if ( annotation->mapLayer() && !mMapSettings.layers().contains( annotation->mapLayer() ) )
266  {
267  continue;
268  }
269 
270  context.painter()->save();
271  context.painter()->setRenderHint( QPainter::Antialiasing, context.flags() & QgsRenderContext::Antialiasing );
272 
273  double itemX, itemY;
274  if ( annotation->hasFixedMapPosition() )
275  {
276  itemX = mMapSettings.outputSize().width() * ( annotation->mapPosition().x() - mMapSettings.extent().xMinimum() ) / mMapSettings.extent().width();
277  itemY = mMapSettings.outputSize().height() * ( 1 - ( annotation->mapPosition().y() - mMapSettings.extent().yMinimum() ) / mMapSettings.extent().height() );
278  }
279  else
280  {
281  itemX = annotation->relativePosition().x() * mMapSettings.outputSize().width();
282  itemY = annotation->relativePosition().y() * mMapSettings.outputSize().height();
283  }
284 
285  context.painter()->translate( itemX, itemY );
286 
287  annotation->render( context );
288  context.painter()->restore();
289  }
290 
291  if ( !mFileName.isEmpty() )
292  {
293  mDestPainter->end();
294 
295  if ( mFileFormat == QStringLiteral( "PDF" ) )
296  {
297 #ifndef QT_NO_PRINTER
298  if ( mForceRaster )
299  {
300  QPainter pp;
301  pp.begin( mPrinter.get() );
302  QRectF rect( 0, 0, mImage.width(), mImage.height() );
303  pp.drawImage( rect, mImage, rect );
304  pp.end();
305  }
306 
307  if ( mSaveWorldFile || mExportMetadata )
308  {
309  CPLSetThreadLocalConfigOption( "GDAL_PDF_DPI", QString::number( mMapSettings.outputDpi() ).toLocal8Bit().constData() );
310  gdal::dataset_unique_ptr outputDS( GDALOpen( mFileName.toLocal8Bit().constData(), GA_Update ) );
311  if ( outputDS )
312  {
313  if ( mSaveWorldFile )
314  {
315  double a, b, c, d, e, f;
316  QgsMapSettingsUtils::worldFileParameters( mMapSettings, a, b, c, d, e, f );
317  c -= 0.5 * a;
318  c -= 0.5 * b;
319  f -= 0.5 * d;
320  f -= 0.5 * e;
321  double geoTransform[6] = { c, a, b, f, d, e };
322  GDALSetGeoTransform( outputDS.get(), geoTransform );
323  GDALSetProjection( outputDS.get(), mMapSettings.destinationCrs().toWkt().toLocal8Bit().constData() );
324  }
325 
326  if ( mExportMetadata )
327  {
328  QString creationDateString;
329  const QDateTime creationDateTime = mGeoPdfExportDetails.creationDateTime;
330  if ( creationDateTime.isValid() )
331  {
332  creationDateString = QStringLiteral( "D:%1" ).arg( mGeoPdfExportDetails.creationDateTime.toString( QStringLiteral( "yyyyMMddHHmmss" ) ) );
333  if ( creationDateTime.timeZone().isValid() )
334  {
335  int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
336  creationDateString += ( offsetFromUtc >= 0 ) ? '+' : '-';
337  offsetFromUtc = std::abs( offsetFromUtc );
338  int offsetHours = offsetFromUtc / 3600;
339  int offsetMins = ( offsetFromUtc % 3600 ) / 60;
340  creationDateString += QStringLiteral( "%1'%2'" ).arg( offsetHours ).arg( offsetMins );
341  }
342  }
343  GDALSetMetadataItem( outputDS.get(), "CREATION_DATE", creationDateString.toLocal8Bit().constData(), nullptr );
344 
345  GDALSetMetadataItem( outputDS.get(), "AUTHOR", mGeoPdfExportDetails.author.toLocal8Bit().constData(), nullptr );
346  const QString creator = QStringLiteral( "QGIS %1" ).arg( Qgis::QGIS_VERSION );
347  GDALSetMetadataItem( outputDS.get(), "CREATOR", creator.toLocal8Bit().constData(), nullptr );
348  GDALSetMetadataItem( outputDS.get(), "PRODUCER", creator.toLocal8Bit().constData(), nullptr );
349  GDALSetMetadataItem( outputDS.get(), "SUBJECT", mGeoPdfExportDetails.subject.toLocal8Bit().constData(), nullptr );
350  GDALSetMetadataItem( outputDS.get(), "TITLE", mGeoPdfExportDetails.title.toLocal8Bit().constData(), nullptr );
351 
352  const QgsAbstractMetadataBase::KeywordMap keywords = mGeoPdfExportDetails.keywords;
353  QStringList allKeywords;
354  for ( auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
355  {
356  allKeywords.append( QStringLiteral( "%1: %2" ).arg( it.key(), it.value().join( ',' ) ) );
357  }
358  const QString keywordString = allKeywords.join( ';' );
359  GDALSetMetadataItem( outputDS.get(), "KEYWORDS", keywordString.toLocal8Bit().constData(), nullptr );
360  }
361  }
362  CPLSetThreadLocalConfigOption( "GDAL_PDF_DPI", nullptr );
363  }
364 #else
365  mError = ImageUnsupportedFormat;
366  return false;
367 #endif // !QT_NO_PRINTER
368  }
369  else if ( mFileFormat != QStringLiteral( "PDF" ) )
370  {
371  bool success = mImage.save( mFileName, mFileFormat.toLocal8Bit().data() );
372  if ( !success )
373  {
374  mError = ImageSaveFail;
375  return false;
376  }
377 
378  if ( mSaveWorldFile )
379  {
380  QFileInfo info = QFileInfo( mFileName );
381 
382  // build the world file name
383  QString outputSuffix = info.suffix();
384  bool skipWorldFile = false;
385  if ( outputSuffix == QStringLiteral( "tif" ) || outputSuffix == QStringLiteral( "tiff" ) )
386  {
387  gdal::dataset_unique_ptr outputDS( GDALOpen( mFileName.toLocal8Bit().constData(), GA_Update ) );
388  if ( outputDS )
389  {
390  skipWorldFile = true;
391  double a, b, c, d, e, f;
392  QgsMapSettingsUtils::worldFileParameters( mMapSettings, a, b, c, d, e, f );
393  c -= 0.5 * a;
394  c -= 0.5 * b;
395  f -= 0.5 * d;
396  f -= 0.5 * e;
397  double geoTransform[] = { c, a, b, f, d, e };
398  GDALSetGeoTransform( outputDS.get(), geoTransform );
399  GDALSetProjection( outputDS.get(), mMapSettings.destinationCrs().toWkt().toLocal8Bit().constData() );
400  }
401  }
402 
403  if ( !skipWorldFile )
404  {
405  QString worldFileName = info.absolutePath() + '/' + info.baseName() + '.'
406  + outputSuffix.at( 0 ) + outputSuffix.at( info.suffix().size() - 1 ) + 'w';
407  QFile worldFile( worldFileName );
408 
409  if ( worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) //don't use QIODevice::Text
410  {
411  QTextStream stream( &worldFile );
412  stream << QgsMapSettingsUtils::worldFileContent( mMapSettings );
413  }
414  }
415  }
416  }
417  }
418 
419  mTempPainter.reset();
420 #ifndef QT_NO_PRINTER
421  mPrinter.reset();
422 #endif
423 
424  return true;
425 }
426 
427 void QgsMapRendererTask::finished( bool result )
428 {
429  qDeleteAll( mAnnotations );
430  mAnnotations.clear();
431 
432  if ( result )
433  emit renderingComplete();
434  else
435  emit errorOccurred( mError );
436 }
437 
438 void QgsMapRendererTask::prepare()
439 {
440  if ( mGeoPDF )
441  {
442  mGeoPdfExporter = qgis::make_unique< QgsMapRendererTaskGeoPdfExporter >( mMapSettings );
443  if ( mGeoPdfExportDetails.includeFeatures )
444  {
445  mRenderedFeatureHandler = qgis::make_unique< QgsMapRendererTaskRenderedFeatureHandler >( static_cast< QgsMapRendererTaskGeoPdfExporter * >( mGeoPdfExporter.get() ), mMapSettings );
446  mMapSettings.addRenderedFeatureHandler( mRenderedFeatureHandler.get() );
447  }
449  mJob->start();
450  return;
451  }
452 
453  mDestPainter = mPainter;
454 
455  if ( mFileFormat == QStringLiteral( "PDF" ) )
456  {
457 #ifndef QT_NO_PRINTER
458  mPrinter.reset( new QPrinter() );
459  mPrinter->setOutputFileName( mFileName );
460  mPrinter->setOutputFormat( QPrinter::PdfFormat );
461  mPrinter->setOrientation( QPrinter::Portrait );
462  // paper size needs to be given in millimeters in order to be able to set a resolution to pass onto the map renderer
463  QSizeF outputSize = mMapSettings.outputSize();
464  mPrinter->setPaperSize( outputSize * 25.4 / mMapSettings.outputDpi(), QPrinter::Millimeter );
465  mPrinter->setPageMargins( 0, 0, 0, 0, QPrinter::Millimeter );
466  mPrinter->setResolution( mMapSettings.outputDpi() );
467 
468  if ( !mForceRaster )
469  {
470  mTempPainter.reset( new QPainter( mPrinter.get() ) );
471  mDestPainter = mTempPainter.get();
472  }
473 #else
474  mError = ImageUnsupportedFormat;
475 #endif // ! QT_NO_PRINTER
476  }
477 
478  if ( !mDestPainter )
479  {
480  // save rendered map to an image file
481  mImage = QImage( mMapSettings.outputSize(), QImage::Format_ARGB32 );
482  if ( mImage.isNull() )
483  {
484  mErrored = true;
485  mError = ImageAllocationFail;
486  return;
487  }
488 
489  mImage.setDotsPerMeterX( 1000 * mMapSettings.outputDpi() / 25.4 );
490  mImage.setDotsPerMeterY( 1000 * mMapSettings.outputDpi() / 25.4 );
491 
492  mTempPainter.reset( new QPainter( &mImage ) );
493  mDestPainter = mTempPainter.get();
494  }
495 
496  if ( !mDestPainter )
497  {
498  mErrored = true;
499  return;
500  }
501 
502  mJob.reset( new QgsMapRendererCustomPainterJob( mMapSettings, mDestPainter ) );
503  static_cast< QgsMapRendererCustomPainterJob *>( mJob.get() )->prepare();
504 }
Abstract base class for GeoPDF exporters.
QList< QgsAbstractGeoPdfExporter::GeoReferencedSection > georeferencedSections
List of georeferenced sections.
bool includeFeatures
true if feature vector information (such as attributes) should be exported.
void addAnnotations(const QList< QgsAnnotation *> &annotations)
Adds annotations to be rendered on the map.
const QgsRenderContext & renderContext
The render context which was used while rendering feature.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Base class for all map layer types.
Definition: qgsmaplayer.h:79
Job implementation that renders everything sequentially using a custom painter.
bool run() override
Performs the task&#39;s operation.
static const QString QGIS_VERSION
Version string.
Definition: qgis.h:52
QString currentLayerId()
Returns the ID of the current layer about to be rendered in the next render operation.
QString mapLayerId
Associated map layer ID, or an empty string if this component layer is not associated with a map laye...
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Use antialiasing while drawing.
Interface for map decorations.
A class to represent a 2D point.
Definition: qgspointxy.h:43
QgsAbstractMetadataBase::KeywordMap keywords
Metadata keyword map.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
Flags flags() const
Returns combination of flags used for rendering.
QSizeF pageSizeMm
Page size, in millimeters.
QList< QgsMapLayer * > layers() const
Gets list of layers for map rendering The layers are stored in the reverse order of how they are rend...
bool isCanceled() const
Will return true if task should terminate ASAP.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
void addDecorations(const QList< QgsMapDecoration *> &decorations)
Adds decorations to be rendered on the map.
static QString worldFileContent(const QgsMapSettings &mapSettings)
Creates the content of a world file.
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
Abstract base class for annotation items which are drawn over a map.
Definition: qgsannotation.h:49
QDateTime creationDateTime
Metadata creation datetime.
The QgsMapSettings class contains configuration for rendering of the map.
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
Contains details of a control point used during georeferencing GeoPDF outputs.
QgsRectangle extent() const
Returns geographical coordinates of the rectangle that should be rendered.
bool nextPart()
Iterates to the next part to render.
QgsMapRendererTask(const QgsMapSettings &ms, const QString &fileName, const QString &fileFormat=QString("PNG"), bool forceRaster=false, bool geoPdf=false, const QgsAbstractGeoPdfExporter::ExportDetails &geoPdfExportDetails=QgsAbstractGeoPdfExporter::ExportDetails())
Constructor for QgsMapRendererTask to render a map to an image file.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
QList< QgsAbstractGeoPdfExporter::ControlPoint > controlPoints
List of control points corresponding to this georeferenced section.
QgsCoordinateReferenceSystem crs
Coordinate reference system for georeferenced section.
An interface for classes which provider custom handlers for features rendered as part of a map render...
Contains information about a feature rendered inside the PDF.
Abstract base class for long running background tasks.
Render job implementation that renders maps in stages, allowing different stages (e.g.
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
Contains information relating to a single PDF layer in the GeoPDF export.
QgsRectangle pageBoundsMm
Bounds of the georeferenced section on the page, in millimeters.
const QgsMapToPixel & mapToPixel() const
Format is unsupported on the platform.
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.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
Contains details of a particular input component to be used during PDF composition.
QgsExpressionContext & expressionContext()
Gets the expression context.
virtual void cancel()
Notifies the task that it should terminate.
double outputDpi() const
Returns DPI used for conversion between real world units (e.g.
void finished(bool result) override
If the task is managed by a QgsTaskManager, this will be called after the task has finished (whether ...
Contains information about the context of a rendering operation.
void errorOccurred(int error)
Emitted when map rendering failed.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QPainter * painter()
Returns the destination QPainter for the render operation.
QString name
User-friendly name for the generated PDF layer.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
~QgsMapRendererTask() override
void cancel() override
Notifies the task that it should terminate.
bool renderCurrentPart(QPainter *painter)
Renders the current part of the map to the specified painter.
QMap< QString, QStringList > KeywordMap
Map of vocabulary string to keyword list.
QString sourcePdfPath
File path to the (already created) PDF to use as the source for this component layer.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
bool isFinished()
Returns true if the job is finished, and nothing remains to render.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
Definition: qgsogrutils.h:134
void addRenderedFeatureHandler(QgsRenderedFeatureHandlerInterface *handler)
Adds a rendered feature handler to use while rendering the map settings.
Represents a vector layer which manages a vector based data sets.
QSize outputSize() const
Returns the size of the resulting map image.
QgsPointXY toMapCoordinates(int x, int y) const
Transform device coordinates to map (world) coordinates.
void renderingComplete()
Emitted when the map rendering is successfully completed.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
Labels should be rendered in individual stages by map layer. This allows separation of labels belongi...