31 #include <QTextStream>
49 const QList< QgsMapLayer * > layers = ms.
layers();
52 VectorComponentDetail detail;
53 detail.name = layer->name();
54 detail.mapLayerId = layer->id();
55 if (
const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer * >( layer ) )
57 detail.displayAttribute = vl->displayField();
59 mLayerDetails[ layer->id() ] = detail;
67 return mLayerDetails.value( layerId );
70 QMap< QString, VectorComponentDetail > mLayerDetails;
78 QgsMapRendererTaskRenderedFeatureHandler( QgsMapRendererTaskGeoPdfExporter *exporter,
const QgsMapSettings &settings )
79 : mExporter( exporter )
80 , mMapSettings( settings )
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() );
110 QgsMapRendererTaskGeoPdfExporter *mExporter =
nullptr;
113 QTransform mTransform;
121 :
QgsTask( fileFormat == QLatin1String(
"PDF" ) ? tr(
"Saving as PDF" ) : tr(
"Saving as image" ) )
123 , mFileName( fileName )
124 , mFileFormat( fileFormat )
125 , mForceRaster( forceRaster )
127 , mGeoPdfExportDetails( geoPdfExportDetails )
133 :
QgsTask( tr(
"Rendering to painter" ) )
144 qDeleteAll( mAnnotations );
145 mAnnotations.clear();
147 const auto constAnnotations = annotations;
150 mAnnotations << a->clone();
156 mDecorations = decorations;
164 mJob->cancelWithoutBlocking();
180 QList< QgsAbstractGeoPdfExporter::ComponentLayerDetail > pdfComponents;
188 component.
name = QStringLiteral(
"layer_%1" ).arg( outputLayer );
192 component.
sourcePdfPath = mGeoPdfExporter->generateTemporaryFilepath( QStringLiteral(
"layer_%1.pdf" ).arg( outputLayer ) );
193 pdfComponents << component;
196 printer.setOutputFileName( component.sourcePdfPath );
197 printer.setOutputFormat( QPrinter::PdfFormat );
198 printer.setOrientation( QPrinter::Portrait );
200 QSizeF outputSize = mMapSettings.
outputSize();
201 printer.setPaperSize( outputSize * 25.4 / mMapSettings.
outputDpi(), QPrinter::Millimeter );
202 printer.setPageMargins( 0, 0, 0, 0, QPrinter::Millimeter );
203 printer.setResolution( mMapSettings.
outputDpi() );
205 QPainter p( &printer );
213 const double pageWidthMM = mMapSettings.
outputSize().width() * 25.4 / mMapSettings.
outputDpi();
214 const double pageHeightMM = mMapSettings.
outputSize().height() * 25.4 / mMapSettings.
outputDpi();
215 exportDetails.
pageSizeMm = QSizeF( pageWidthMM, pageHeightMM );
221 if ( mSaveWorldFile )
235 const bool res = mGeoPdfExporter->finalize( pdfComponents, mFileName, exportDetails );
236 mGeoPdfExporter.reset();
237 mTempPainter.reset();
246 mJob.reset(
nullptr );
255 const auto constMDecorations = mDecorations;
258 decoration->render( mMapSettings, context );
261 const auto constMAnnotations = mAnnotations;
267 if ( !annotation || !annotation->isVisible() )
271 if ( annotation->mapLayer() && !mMapSettings.
layers().contains( annotation->mapLayer() ) )
280 if ( annotation->hasFixedMapPosition() )
287 itemX = annotation->relativePosition().x() * mMapSettings.
outputSize().width();
288 itemY = annotation->relativePosition().y() * mMapSettings.
outputSize().height();
291 context.
painter()->translate( itemX, itemY );
293 annotation->render( context );
296 if ( !mFileName.isEmpty() )
300 if ( mFileFormat == QLatin1String(
"PDF" ) )
302 #ifndef QT_NO_PRINTER
306 pp.begin( mPrinter.get() );
307 QRectF rect( 0, 0, mImage.width(), mImage.height() );
308 pp.drawImage( rect, mImage, rect );
312 if ( mSaveWorldFile || mExportMetadata )
314 CPLSetThreadLocalConfigOption(
"GDAL_PDF_DPI", QString::number( mMapSettings.
outputDpi() ).toLocal8Bit().constData() );
318 if ( mSaveWorldFile )
320 double a, b,
c, d, e, f;
326 double geoTransform[6] = {
c, a, b, f, d, e };
327 GDALSetGeoTransform( outputDS.get(), geoTransform );
331 if ( mExportMetadata )
333 QString creationDateString;
335 if ( creationDateTime.isValid() )
337 creationDateString = QStringLiteral(
"D:%1" ).arg( mGeoPdfExportDetails.
creationDateTime.toString( QStringLiteral(
"yyyyMMddHHmmss" ) ) );
338 if ( creationDateTime.timeZone().isValid() )
340 int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
341 creationDateString += ( offsetFromUtc >= 0 ) ?
'+' :
'-';
342 offsetFromUtc = std::abs( offsetFromUtc );
343 int offsetHours = offsetFromUtc / 3600;
344 int offsetMins = ( offsetFromUtc % 3600 ) / 60;
345 creationDateString += QStringLiteral(
"%1'%2'" ).arg( offsetHours ).arg( offsetMins );
348 GDALSetMetadataItem( outputDS.get(),
"CREATION_DATE", creationDateString.toLocal8Bit().constData(),
nullptr );
350 GDALSetMetadataItem( outputDS.get(),
"AUTHOR", mGeoPdfExportDetails.
author.toLocal8Bit().constData(),
nullptr );
351 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
352 GDALSetMetadataItem( outputDS.get(),
"CREATOR", creator.toLocal8Bit().constData(),
nullptr );
353 GDALSetMetadataItem( outputDS.get(),
"PRODUCER", creator.toLocal8Bit().constData(),
nullptr );
354 GDALSetMetadataItem( outputDS.get(),
"SUBJECT", mGeoPdfExportDetails.
subject.toLocal8Bit().constData(),
nullptr );
355 GDALSetMetadataItem( outputDS.get(),
"TITLE", mGeoPdfExportDetails.
title.toLocal8Bit().constData(),
nullptr );
358 QStringList allKeywords;
359 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
361 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
363 const QString keywordString = allKeywords.join(
';' );
364 GDALSetMetadataItem( outputDS.get(),
"KEYWORDS", keywordString.toLocal8Bit().constData(),
nullptr );
367 CPLSetThreadLocalConfigOption(
"GDAL_PDF_DPI",
nullptr );
372 #endif // !QT_NO_PRINTER
374 else if ( mFileFormat != QLatin1String(
"PDF" ) )
376 bool success = mImage.save( mFileName, mFileFormat.toLocal8Bit().data() );
383 if ( mSaveWorldFile )
385 QFileInfo info = QFileInfo( mFileName );
388 QString outputSuffix = info.suffix();
389 bool skipWorldFile =
false;
390 if ( outputSuffix == QLatin1String(
"tif" ) || outputSuffix == QLatin1String(
"tiff" ) )
395 skipWorldFile =
true;
396 double a, b,
c, d, e, f;
402 double geoTransform[] = {
c, a, b, f, d, e };
403 GDALSetGeoTransform( outputDS.get(), geoTransform );
408 if ( !skipWorldFile )
410 QString worldFileName = info.absolutePath() +
'/' + info.completeBaseName() +
'.'
411 + outputSuffix.at( 0 ) + outputSuffix.at( info.suffix().size() - 1 ) +
'w';
412 QFile worldFile( worldFileName );
414 if ( worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
416 QTextStream stream( &worldFile );
424 mTempPainter.reset();
425 #ifndef QT_NO_PRINTER
434 qDeleteAll( mAnnotations );
435 mAnnotations.clear();
443 void QgsMapRendererTask::prepare()
447 mGeoPdfExporter = qgis::make_unique< QgsMapRendererTaskGeoPdfExporter >( mMapSettings );
450 mRenderedFeatureHandler = qgis::make_unique< QgsMapRendererTaskRenderedFeatureHandler >(
static_cast< QgsMapRendererTaskGeoPdfExporter *
>( mGeoPdfExporter.get() ), mMapSettings );
454 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
457 mLayerIdToLayerNameMap.insert( layer->id(), layer->name() );
458 mMapLayerOrder << layer->id();
466 mDestPainter = mPainter;
468 if ( mFileFormat == QLatin1String(
"PDF" ) )
470 #ifndef QT_NO_PRINTER
471 mPrinter.reset(
new QPrinter() );
472 mPrinter->setOutputFileName( mFileName );
473 mPrinter->setOutputFormat( QPrinter::PdfFormat );
474 mPrinter->setOrientation( QPrinter::Portrait );
476 QSizeF outputSize = mMapSettings.
outputSize();
477 mPrinter->setPaperSize( outputSize * 25.4 / mMapSettings.
outputDpi(), QPrinter::Millimeter );
478 mPrinter->setPageMargins( 0, 0, 0, 0, QPrinter::Millimeter );
479 mPrinter->setResolution( mMapSettings.
outputDpi() );
483 mTempPainter.reset(
new QPainter( mPrinter.get() ) );
484 mDestPainter = mTempPainter.get();
488 #endif // ! QT_NO_PRINTER
494 mImage = QImage( mMapSettings.
outputSize(), QImage::Format_ARGB32 );
495 if ( mImage.isNull() )
502 mImage.setDotsPerMeterX( 1000 * mMapSettings.
outputDpi() / 25.4 );
503 mImage.setDotsPerMeterY( 1000 * mMapSettings.
outputDpi() / 25.4 );
505 mTempPainter.reset(
new QPainter( &mImage ) );
506 mDestPainter = mTempPainter.get();