31#include <QImageWriter> 
   51      const QList< QgsMapLayer * > layers = ms.
layers();
 
   54        VectorComponentDetail detail;
 
   55        detail.name = layer->name();
 
   56        detail.mapLayerId = layer->id();
 
   57        if ( 
const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer * >( layer ) )
 
   59          detail.displayAttribute = vl->displayField();
 
   61        mLayerDetails[ layer->id() ] = detail;
 
   69      return mLayerDetails.value( layerId );
 
   72    QMap< QString, VectorComponentDetail > mLayerDetails;
 
   80    QgsMapRendererTaskRenderedFeatureHandler( QgsMapRendererTaskGeoPdfExporter *exporter, 
const QgsMapSettings &settings )
 
   81      : mExporter( exporter )
 
   82      , mMapSettings( settings )
 
   85      const double pageHeightPdfUnits = settings.
outputSize().height() * 72.0 / settings.
outputDpi();
 
   86      mTransform = QTransform::fromTranslate( 0, pageHeightPdfUnits ).scale( 72.0 / mMapSettings.outputDpi(), -72.0 / mMapSettings.outputDpi() );
 
  112    QgsMapRendererTaskGeoPdfExporter *mExporter = 
nullptr;
 
  115    QTransform mTransform;
 
  123  : 
QgsTask( fileFormat == QLatin1String( 
"PDF" ) ? tr( 
"Saving as PDF" ) : tr( 
"Saving as image" ), flags )
 
  125  , mFileName( fileName )
 
  126  , mFileFormat( fileFormat )
 
  127  , mForceRaster( forceRaster )
 
  129  , mGeoPdfExportDetails( geoPdfExportDetails )
 
  135  : 
QgsTask( tr( 
"Rendering to painter" ) )
 
  146  qDeleteAll( mAnnotations );
 
  147  mAnnotations.clear();
 
  149  const auto constAnnotations = annotations;
 
  152    mAnnotations << a->clone();
 
  158  mDecorations = decorations;
 
  166    mJob->cancelWithoutBlocking();
 
  182    QList< QgsAbstractGeoPdfExporter::ComponentLayerDetail > pdfComponents;
 
  190      component.
name = QStringLiteral( 
"layer_%1" ).arg( outputLayer );
 
  194      component.
sourcePdfPath = mGeoPdfExporter->generateTemporaryFilepath( QStringLiteral( 
"layer_%1.pdf" ).arg( outputLayer ) );
 
  195      pdfComponents << component;
 
  199      printer.setOutputFormat( QPrinter::PdfFormat );
 
  200#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  201      printer.setOrientation( QPrinter::Portrait );
 
  203      QSizeF outputSize = mMapSettings.
outputSize();
 
  204      printer.setPaperSize( outputSize  * 25.4 / mMapSettings.
outputDpi(), QPrinter::Millimeter );
 
  205      printer.setPageMargins( 0, 0, 0, 0, QPrinter::Millimeter );
 
  207      printer.setPageOrientation( QPageLayout::Orientation::Portrait );
 
  209      const QSizeF outputSize = mMapSettings.
outputSize();
 
  210      const QPageSize pageSize( outputSize  * 25.4 / mMapSettings.
outputDpi(), QPageSize::Unit::Millimeter );
 
  211      printer.setPageSize( pageSize );
 
  212      printer.setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
 
  214      printer.setResolution( mMapSettings.
outputDpi() );
 
  216      QPainter p( &printer );
 
  224    const double pageWidthMM = mMapSettings.
outputSize().width() * 25.4 / mMapSettings.
outputDpi();
 
  225    const double pageHeightMM = mMapSettings.
outputSize().height() * 25.4 / mMapSettings.
outputDpi();
 
  226    exportDetails.
pageSizeMm = QSizeF( pageWidthMM, pageHeightMM );
 
  232    if ( mSaveWorldFile )
 
  246    const bool res = mGeoPdfExporter->finalize( pdfComponents, mFileName, exportDetails );
 
  247    mGeoPdfExporter.reset();
 
  248    mTempPainter.reset();
 
  257  mJob.reset( 
nullptr );
 
  266  const auto constMDecorations = mDecorations;
 
  269    decoration->render( mMapSettings, context );
 
  272  const auto constMAnnotations = mAnnotations;
 
  278    if ( !annotation || !annotation->isVisible() )
 
  282    if ( annotation->mapLayer() && !mMapSettings.
layers().contains( annotation->mapLayer() ) )
 
  291    if ( annotation->hasFixedMapPosition() )
 
  298      itemX = annotation->relativePosition().x() * mMapSettings.
outputSize().width();
 
  299      itemY = annotation->relativePosition().y() * mMapSettings.
outputSize().height();
 
  302    context.
painter()->translate( itemX, itemY );
 
  304    annotation->render( context );
 
  307  if ( !mFileName.isEmpty() )
 
  311    if ( mFileFormat == QLatin1String( 
"PDF" ) )
 
  317        pp.begin( mPrinter.get() );
 
  318        const QRectF rect( 0, 0, mImage.width(), mImage.height() );
 
  319        pp.drawImage( rect, mImage, rect );
 
  323      if ( mSaveWorldFile || mExportMetadata )
 
  325        CPLSetThreadLocalConfigOption( 
"GDAL_PDF_DPI", QString::number( mMapSettings.
outputDpi() ).toLocal8Bit().constData() );
 
  329          if ( mSaveWorldFile )
 
  331            double a, b, 
c, d, e, f;
 
  337            double geoTransform[6] = { 
c, a, b, f, d, e };
 
  338            GDALSetGeoTransform( outputDS.get(), geoTransform );
 
  342          if ( mExportMetadata )
 
  344            QString creationDateString;
 
  346            if ( creationDateTime.isValid() )
 
  348              creationDateString = QStringLiteral( 
"D:%1" ).arg( mGeoPdfExportDetails.
creationDateTime.toString( QStringLiteral( 
"yyyyMMddHHmmss" ) ) );
 
  349              if ( creationDateTime.timeZone().isValid() )
 
  351                int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
 
  352                creationDateString += ( offsetFromUtc >= 0 ) ? 
'+' : 
'-';
 
  353                offsetFromUtc = std::abs( offsetFromUtc );
 
  354                const int offsetHours = offsetFromUtc / 3600;
 
  355                const int offsetMins = ( offsetFromUtc % 3600 ) / 60;
 
  356                creationDateString += QStringLiteral( 
"%1'%2'" ).arg( offsetHours ).arg( offsetMins );
 
  359            GDALSetMetadataItem( outputDS.get(), 
"CREATION_DATE", creationDateString.toUtf8().constData(), 
nullptr );
 
  361            GDALSetMetadataItem( outputDS.get(), 
"AUTHOR", mGeoPdfExportDetails.
author.toUtf8().constData(), 
nullptr );
 
  362            const QString creator = QStringLiteral( 
"QGIS %1" ).arg( 
Qgis::version() );
 
  363            GDALSetMetadataItem( outputDS.get(), 
"CREATOR", creator.toUtf8().constData(), 
nullptr );
 
  364            GDALSetMetadataItem( outputDS.get(), 
"PRODUCER", creator.toUtf8().constData(), 
nullptr );
 
  365            GDALSetMetadataItem( outputDS.get(), 
"SUBJECT", mGeoPdfExportDetails.
subject.toUtf8().constData(), 
nullptr );
 
  366            GDALSetMetadataItem( outputDS.get(), 
"TITLE", mGeoPdfExportDetails.
title.toUtf8().constData(), 
nullptr );
 
  369            QStringList allKeywords;
 
  370            for ( 
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
 
  372              allKeywords.append( QStringLiteral( 
"%1: %2" ).arg( it.key(), it.value().join( 
',' ) ) );
 
  374            const QString keywordString = allKeywords.join( 
';' );
 
  375            GDALSetMetadataItem( outputDS.get(), 
"KEYWORDS", keywordString.toUtf8().constData(), 
nullptr );
 
  378        CPLSetThreadLocalConfigOption( 
"GDAL_PDF_DPI", 
nullptr );
 
  385    else if ( mFileFormat != QLatin1String( 
"PDF" ) )
 
  387      QImageWriter writer( mFileName, mFileFormat.toLocal8Bit().data() );
 
  388      if ( mFileFormat.compare( QLatin1String( 
"TIF" ), Qt::CaseInsensitive ) == 0 || mFileFormat.compare( QLatin1String( 
"TIFF" ), Qt::CaseInsensitive ) == 0 )
 
  391        writer.setCompression( 1 );
 
  393      const bool success = writer.write( mImage );
 
  400      if ( mSaveWorldFile )
 
  402        const QFileInfo info  = QFileInfo( mFileName );
 
  405        const QString outputSuffix = info.suffix();
 
  406        bool skipWorldFile = 
false;
 
  407        if ( outputSuffix.compare( QLatin1String( 
"TIF" ), Qt::CaseInsensitive ) == 0 || outputSuffix.compare( QLatin1String( 
"TIFF" ), Qt::CaseInsensitive ) == 0 )
 
  412            skipWorldFile = 
true;
 
  413            double a, b, 
c, d, e, f;
 
  419            double geoTransform[] = { 
c, a, b, f, d, e };
 
  420            GDALSetGeoTransform( outputDS.get(), geoTransform );
 
  425        if ( !skipWorldFile )
 
  427          const QString worldFileName = info.absolutePath() + 
'/' + info.completeBaseName() + 
'.' 
  428                                        + outputSuffix.at( 0 ) + outputSuffix.at( info.suffix().size() - 1 ) + 
'w';
 
  429          QFile worldFile( worldFileName );
 
  431          if ( worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) 
 
  433            QTextStream stream( &worldFile );
 
  441  mTempPainter.reset();
 
  451  qDeleteAll( mAnnotations );
 
  452  mAnnotations.clear();
 
  460void QgsMapRendererTask::prepare()
 
  464    mGeoPdfExporter = std::make_unique< QgsMapRendererTaskGeoPdfExporter >( mMapSettings );
 
  467      mRenderedFeatureHandler = std::make_unique< QgsMapRendererTaskRenderedFeatureHandler >( 
static_cast< QgsMapRendererTaskGeoPdfExporter * 
>( mGeoPdfExporter.get() ), mMapSettings );
 
  471    const QList< QgsMapLayer * > layers = mMapSettings.
layers();
 
  474      mLayerIdToLayerNameMap.insert( layer->id(), layer->name() );
 
  475      mMapLayerOrder << layer->id();
 
  483  mDestPainter = mPainter;
 
  485  if ( mFileFormat == QLatin1String( 
"PDF" ) )
 
  488    mPrinter.reset( 
new QPrinter() );
 
  489    mPrinter->setOutputFileName( mFileName );
 
  490    mPrinter->setOutputFormat( QPrinter::PdfFormat );
 
  491#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  492    mPrinter->setOrientation( QPrinter::Portrait );
 
  494    QSizeF outputSize = mMapSettings.
outputSize();
 
  495    mPrinter->setPaperSize( outputSize  * 25.4 / mMapSettings.
outputDpi(), QPrinter::Millimeter );
 
  496    mPrinter->setPageMargins( 0, 0, 0, 0, QPrinter::Millimeter );
 
  498    mPrinter->setPageOrientation( QPageLayout::Orientation::Portrait );
 
  500    const QSizeF outputSize = mMapSettings.
outputSize();
 
  501    const QPageSize pageSize( outputSize  * 25.4 / mMapSettings.
outputDpi(), QPageSize::Unit::Millimeter );
 
  502    mPrinter->setPageSize( pageSize );
 
  503    mPrinter->setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
 
  505    mPrinter->setResolution( mMapSettings.
outputDpi() );
 
  509      mTempPainter.reset( 
new QPainter( mPrinter.get() ) );
 
  510      mDestPainter = mTempPainter.get();
 
  520    mImage = QImage( mMapSettings.
outputSize(), QImage::Format_ARGB32 );
 
  521    if ( mImage.isNull() )
 
  528    mImage.setDotsPerMeterX( 1000 * mMapSettings.
outputDpi() / 25.4 );
 
  529    mImage.setDotsPerMeterY( 1000 * mMapSettings.
outputDpi() / 25.4 );
 
  531    mTempPainter.reset( 
new QPainter( &mImage ) );
 
  532    mDestPainter = mTempPainter.get();
 
static QString version()
Version string.
Abstract base class for GeoPDF exporters.
Abstract base class for annotation items which are drawn over a map.
@ WKT_PREFERRED_GDAL
Preferred format for conversion of CRS to WKT for use with the GDAL library.
QString toWkt(WktVariant variant=WKT1_GDAL, 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...
A geometry is the spatial representation of a feature.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
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.
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.
QgsMapRendererTask(const QgsMapSettings &ms, const QString &fileName, const QString &fileFormat=QString("PNG"), bool forceRaster=false, QgsTask::Flags flags=QgsTask::CanCancel, bool geoPdf=false, const QgsAbstractGeoPdfExporter::ExportDetails &geoPdfExportDetails=QgsAbstractGeoPdfExporter::ExportDetails())
Constructor for QgsMapRendererTask to render a map to an image file.
@ ImageUnsupportedFormat
Format is unsupported on the platform.
@ ImageSaveFail
Image save failure.
@ ImageAllocationFail
Image allocation failure.
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.
const QgsMapToPixel & mapToPixel() const
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.
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.
A rectangle specified with double values.
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).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
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.
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
Contains details of a particular input component to be used during PDF composition.
QString sourcePdfPath
File path to the (already created) PDF to use as the source for this component layer.
QString mapLayerId
Associated map layer ID, or an empty string if this component layer is not associated with a map laye...
QPainter::CompositionMode compositionMode
Component composition mode.
QString name
User-friendly name for the generated PDF layer.
double opacity
Component opacity.
Contains details of a control point used during georeferencing GeoPDF outputs.
QgsAbstractMetadataBase::KeywordMap keywords
Metadata keyword map.
QMap< QString, QString > layerIdToPdfLayerTreeNameMap
Optional map of map layer ID to custom layer tree name to show in the created PDF file.
QDateTime creationDateTime
Metadata creation datetime.
QSizeF pageSizeMm
Page size, in millimeters.
QList< QgsAbstractGeoPdfExporter::GeoReferencedSection > georeferencedSections
List of georeferenced sections.
QString author
Metadata author tag.
bool includeFeatures
true if feature vector information (such as attributes) should be exported.
QStringList layerOrder
Optional list of layer IDs, in the order desired to appear in the generated GeoPDF file.
QString subject
Metadata subject tag.
QString title
Metadata title tag.
QgsRectangle pageBoundsMm
Bounds of the georeferenced section on the page, in millimeters.
QgsCoordinateReferenceSystem crs
Coordinate reference system for georeferenced section.
QList< QgsAbstractGeoPdfExporter::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 GeoPDF export.
const QgsRenderContext & renderContext
The render context which was used while rendering feature.