31 #include <QImageWriter>
32 #include <QTextStream>
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;
198 printer.setOutputFileName( component.sourcePdfPath );
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" ) )
313 #ifndef QT_NO_PRINTER
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 );
383 #endif // !QT_NO_PRINTER
385 else if ( mFileFormat != QLatin1String(
"PDF" ) )
387 QImageWriter writer( mFileName, mFileFormat.toLocal8Bit().data() );
388 if ( mFileFormat == QLatin1String(
"TIF" ) || mFileFormat == QLatin1String(
"TIFF" ) )
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 == QLatin1String(
"tif" ) || outputSuffix == QLatin1String(
"tiff" ) )
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();
442 #ifndef QT_NO_PRINTER
451 qDeleteAll( mAnnotations );
452 mAnnotations.clear();
460 void 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" ) )
487 #ifndef QT_NO_PRINTER
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();
514 #endif // ! QT_NO_PRINTER
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();