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 == QStringLiteral(
"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 );
297 if ( !mFileName.isEmpty() )
301 if ( mFileFormat == QStringLiteral(
"PDF" ) )
303 #ifndef QT_NO_PRINTER
307 pp.begin( mPrinter.get() );
308 QRectF rect( 0, 0, mImage.width(), mImage.height() );
309 pp.drawImage( rect, mImage, rect );
313 if ( mSaveWorldFile || mExportMetadata )
315 CPLSetThreadLocalConfigOption(
"GDAL_PDF_DPI", QString::number( mMapSettings.
outputDpi() ).toLocal8Bit().constData() );
319 if ( mSaveWorldFile )
321 double a, b,
c, d, e, f;
327 double geoTransform[6] = {
c, a, b, f, d, e };
328 GDALSetGeoTransform( outputDS.get(), geoTransform );
332 if ( mExportMetadata )
334 QString creationDateString;
336 if ( creationDateTime.isValid() )
338 creationDateString = QStringLiteral(
"D:%1" ).arg( mGeoPdfExportDetails.
creationDateTime.toString( QStringLiteral(
"yyyyMMddHHmmss" ) ) );
339 if ( creationDateTime.timeZone().isValid() )
341 int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
342 creationDateString += ( offsetFromUtc >= 0 ) ?
'+' :
'-';
343 offsetFromUtc = std::abs( offsetFromUtc );
344 int offsetHours = offsetFromUtc / 3600;
345 int offsetMins = ( offsetFromUtc % 3600 ) / 60;
346 creationDateString += QStringLiteral(
"%1'%2'" ).arg( offsetHours ).arg( offsetMins );
349 GDALSetMetadataItem( outputDS.get(),
"CREATION_DATE", creationDateString.toLocal8Bit().constData(),
nullptr );
351 GDALSetMetadataItem( outputDS.get(),
"AUTHOR", mGeoPdfExportDetails.
author.toLocal8Bit().constData(),
nullptr );
352 const QString creator = QStringLiteral(
"QGIS %1" ).arg(
Qgis::version() );
353 GDALSetMetadataItem( outputDS.get(),
"CREATOR", creator.toLocal8Bit().constData(),
nullptr );
354 GDALSetMetadataItem( outputDS.get(),
"PRODUCER", creator.toLocal8Bit().constData(),
nullptr );
355 GDALSetMetadataItem( outputDS.get(),
"SUBJECT", mGeoPdfExportDetails.
subject.toLocal8Bit().constData(),
nullptr );
356 GDALSetMetadataItem( outputDS.get(),
"TITLE", mGeoPdfExportDetails.
title.toLocal8Bit().constData(),
nullptr );
359 QStringList allKeywords;
360 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
362 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
364 const QString keywordString = allKeywords.join(
';' );
365 GDALSetMetadataItem( outputDS.get(),
"KEYWORDS", keywordString.toLocal8Bit().constData(),
nullptr );
368 CPLSetThreadLocalConfigOption(
"GDAL_PDF_DPI",
nullptr );
373 #endif // !QT_NO_PRINTER
375 else if ( mFileFormat != QStringLiteral(
"PDF" ) )
377 bool success = mImage.save( mFileName, mFileFormat.toLocal8Bit().data() );
384 if ( mSaveWorldFile )
386 QFileInfo info = QFileInfo( mFileName );
389 QString outputSuffix = info.suffix();
390 bool skipWorldFile =
false;
391 if ( outputSuffix == QStringLiteral(
"tif" ) || outputSuffix == QStringLiteral(
"tiff" ) )
396 skipWorldFile =
true;
397 double a, b,
c, d, e, f;
403 double geoTransform[] = {
c, a, b, f, d, e };
404 GDALSetGeoTransform( outputDS.get(), geoTransform );
409 if ( !skipWorldFile )
411 QString worldFileName = info.absolutePath() +
'/' + info.completeBaseName() +
'.'
412 + outputSuffix.at( 0 ) + outputSuffix.at( info.suffix().size() - 1 ) +
'w';
413 QFile worldFile( worldFileName );
415 if ( worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
417 QTextStream stream( &worldFile );
425 mTempPainter.reset();
426 #ifndef QT_NO_PRINTER
435 qDeleteAll( mAnnotations );
436 mAnnotations.clear();
444 void QgsMapRendererTask::prepare()
448 mGeoPdfExporter = qgis::make_unique< QgsMapRendererTaskGeoPdfExporter >( mMapSettings );
451 mRenderedFeatureHandler = qgis::make_unique< QgsMapRendererTaskRenderedFeatureHandler >(
static_cast< QgsMapRendererTaskGeoPdfExporter *
>( mGeoPdfExporter.get() ), mMapSettings );
455 const QList< QgsMapLayer * > layers = mMapSettings.
layers();
458 mLayerIdToLayerNameMap.insert( layer->id(), layer->name() );
459 mMapLayerOrder << layer->id();
467 mDestPainter = mPainter;
469 if ( mFileFormat == QStringLiteral(
"PDF" ) )
471 #ifndef QT_NO_PRINTER
472 mPrinter.reset(
new QPrinter() );
473 mPrinter->setOutputFileName( mFileName );
474 mPrinter->setOutputFormat( QPrinter::PdfFormat );
475 mPrinter->setOrientation( QPrinter::Portrait );
477 QSizeF outputSize = mMapSettings.
outputSize();
478 mPrinter->setPaperSize( outputSize * 25.4 / mMapSettings.
outputDpi(), QPrinter::Millimeter );
479 mPrinter->setPageMargins( 0, 0, 0, 0, QPrinter::Millimeter );
480 mPrinter->setResolution( mMapSettings.
outputDpi() );
484 mTempPainter.reset(
new QPainter( mPrinter.get() ) );
485 mDestPainter = mTempPainter.get();
489 #endif // ! QT_NO_PRINTER
495 mImage = QImage( mMapSettings.
outputSize(), QImage::Format_ARGB32 );
496 if ( mImage.isNull() )
503 mImage.setDotsPerMeterX( 1000 * mMapSettings.
outputDpi() / 25.4 );
504 mImage.setDotsPerMeterY( 1000 * mMapSettings.
outputDpi() / 25.4 );
506 mTempPainter.reset(
new QPainter( &mImage ) );
507 mDestPainter = mTempPainter.get();