36#include <QImageWriter>
38#include <QSvgGenerator>
42#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
44#include <QPdfOutputIntent>
46#include <QXmlStreamWriter>
52class LayoutContextPreviewSettingRestorer
56 LayoutContextPreviewSettingRestorer( QgsLayout *layout )
58 , mPreviousSetting( layout->renderContext().mIsPreviewRender )
60 mLayout->renderContext().mIsPreviewRender =
false;
63 ~LayoutContextPreviewSettingRestorer()
65 mLayout->renderContext().mIsPreviewRender = mPreviousSetting;
68 LayoutContextPreviewSettingRestorer(
const LayoutContextPreviewSettingRestorer &other ) =
delete;
69 LayoutContextPreviewSettingRestorer &operator=(
const LayoutContextPreviewSettingRestorer &other ) =
delete;
72 QgsLayout *mLayout =
nullptr;
73 bool mPreviousSetting =
false;
80 LayoutGuideHider( QgsLayout *layout )
83 const QList< QgsLayoutGuide * > guides = mLayout->guides().guides();
84 for ( QgsLayoutGuide *guide : guides )
86 mPrevVisibility.insert( guide, guide->item()->isVisible() );
87 guide->item()->setVisible(
false );
93 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
95 it.key()->item()->setVisible( it.value() );
99 LayoutGuideHider(
const LayoutGuideHider &other ) =
delete;
100 LayoutGuideHider &operator=(
const LayoutGuideHider &other ) =
delete;
103 QgsLayout *mLayout =
nullptr;
104 QHash< QgsLayoutGuide *, bool > mPrevVisibility;
110 explicit LayoutItemHider(
const QList<QGraphicsItem *> &items )
112 mItemsToIterate.reserve( items.count() );
113 for ( QGraphicsItem *item : items )
115 const bool isVisible = item->isVisible();
116 mPrevVisibility[item] = isVisible;
118 mItemsToIterate.append( item );
119 if ( QgsLayoutItem *layoutItem =
dynamic_cast< QgsLayoutItem *
>( item ) )
120 layoutItem->setProperty(
"wasVisible", isVisible );
128 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
136 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
138 it.key()->setVisible( it.value() );
139 if ( QgsLayoutItem *layoutItem =
dynamic_cast< QgsLayoutItem *
>( it.key() ) )
140 layoutItem->setProperty(
"wasVisible", QVariant() );
144 QList< QGraphicsItem * > itemsToIterate()
const {
return mItemsToIterate; }
146 LayoutItemHider(
const LayoutItemHider &other ) =
delete;
147 LayoutItemHider &operator=(
const LayoutItemHider &other ) =
delete;
151 QList<QGraphicsItem * > mItemsToIterate;
152 QHash<QGraphicsItem *, bool> mPrevVisibility;
170 qDeleteAll( mLabelingResults );
183 if ( mLayout->pageCollection()->pageCount() <= page || page < 0 )
194 LayoutContextPreviewSettingRestorer restorer( mLayout );
197 QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
206 if ( mLayout->pageCollection()->pageCount() <= page || page < 0 )
217 LayoutContextPreviewSettingRestorer restorer( mLayout );
220 QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
222 const double imageAspectRatio =
static_cast< double >( imageSize.width() ) / imageSize.height();
223 const double paperAspectRatio = paperRect.width() / paperRect.height();
224 if ( imageSize.isValid() && ( !
qgsDoubleNear( imageAspectRatio, paperAspectRatio, 0.008 ) ) )
229 QgsMessageLog::logMessage( QObject::tr(
"Ignoring custom image size because aspect ratio %1 does not match paper ratio %2" ).arg( QString::number( imageAspectRatio,
'g', 3 ), QString::number( paperAspectRatio,
'g', 3 ) ), QStringLiteral(
"Layout" ),
Qgis::MessageLevel::Warning );
237class LayoutItemCacheSettingRestorer
241 LayoutItemCacheSettingRestorer(
QgsLayout *layout )
244 const QList< QGraphicsItem * > items = mLayout->items();
245 for ( QGraphicsItem *item : items )
247 mPrevCacheMode.insert( item, item->cacheMode() );
248 item->setCacheMode( QGraphicsItem::NoCache );
252 ~LayoutItemCacheSettingRestorer()
254 for (
auto it = mPrevCacheMode.constBegin(); it != mPrevCacheMode.constEnd(); ++it )
256 it.key()->setCacheMode( it.value() );
260 LayoutItemCacheSettingRestorer(
const LayoutItemCacheSettingRestorer &other ) =
delete;
261 LayoutItemCacheSettingRestorer &operator=(
const LayoutItemCacheSettingRestorer &other ) =
delete;
264 QgsLayout *mLayout =
nullptr;
265 QHash< QGraphicsItem *, QGraphicsItem::CacheMode > mPrevCacheMode;
272 QPaintDevice *paintDevice = painter->device();
273 if ( !paintDevice || !mLayout )
278 LayoutItemCacheSettingRestorer cacheRestorer( mLayout );
279 ( void )cacheRestorer;
280 LayoutContextPreviewSettingRestorer restorer( mLayout );
282 LayoutGuideHider guideHider( mLayout );
287 mLayout->render( painter, QRectF( 0, 0, paintDevice->width(), paintDevice->height() ), region );
295 LayoutContextPreviewSettingRestorer restorer( mLayout );
298 double resolution = mLayout->renderContext().dpi();
300 if ( imageSize.isValid() )
304 resolution = ( imageSize.width() / region.width()
305 + imageSize.height() / region.height() ) / 2.0 * oneInchInLayoutUnits;
313 int width = imageSize.isValid() ? imageSize.width()
314 :
static_cast< int >( resolution * region.width() / oneInchInLayoutUnits );
315 int height = imageSize.isValid() ? imageSize.height()
316 :
static_cast< int >( resolution * region.height() / oneInchInLayoutUnits );
318 QImage image( QSize( width, height ), QImage::Format_ARGB32 );
319 if ( !image.isNull() )
322 if ( width > 32768 || height > 32768 )
323 QgsMessageLog::logMessage( QObject::tr(
"Error: output width or height is larger than 32768 pixel, result will be clipped" ) );
324 image.setDotsPerMeterX(
static_cast< int >( std::round( resolution / 25.4 * 1000 ) ) );
325 image.setDotsPerMeterY(
static_cast< int>( std::round( resolution / 25.4 * 1000 ) ) );
326 image.fill( Qt::transparent );
327 QPainter imagePainter( &image );
329 if ( !imagePainter.isActive() )
337class LayoutContextSettingsRestorer
342 LayoutContextSettingsRestorer(
QgsLayout *layout )
344 , mPreviousDpi( layout->renderContext().dpi() )
345 , mPreviousFlags( layout->renderContext().flags() )
346 , mPreviousRasterPolicy( layout->renderContext().rasterizedRenderingPolicy() )
347 , mPreviousTextFormat( layout->renderContext().textRenderFormat() )
348 , mPreviousExportLayer( layout->renderContext().currentExportLayer() )
349 , mPreviousSimplifyMethod( layout->renderContext().simplifyMethod() )
350 , mPreviousMaskSettings( layout->renderContext().maskSettings() )
351 , mExportThemes( layout->renderContext().exportThemes() )
352 , mPredefinedScales( layout->renderContext().predefinedScales() )
357 ~LayoutContextSettingsRestorer()
359 mLayout->renderContext().setDpi( mPreviousDpi );
360 mLayout->renderContext().setFlags( mPreviousFlags );
361 mLayout->renderContext().setRasterizedRenderingPolicy( mPreviousRasterPolicy );
362 mLayout->renderContext().setTextRenderFormat( mPreviousTextFormat );
364 mLayout->renderContext().setCurrentExportLayer( mPreviousExportLayer );
366 mLayout->renderContext().setSimplifyMethod( mPreviousSimplifyMethod );
367 mLayout->renderContext().setMaskSettings( mPreviousMaskSettings );
368 mLayout->renderContext().setExportThemes( mExportThemes );
369 mLayout->renderContext().setPredefinedScales( mPredefinedScales );
372 LayoutContextSettingsRestorer(
const LayoutContextSettingsRestorer &other ) =
delete;
373 LayoutContextSettingsRestorer &operator=(
const LayoutContextSettingsRestorer &other ) =
delete;
376 QgsLayout *mLayout =
nullptr;
377 double mPreviousDpi = 0;
381 int mPreviousExportLayer = 0;
382 QgsVectorSimplifyMethod mPreviousSimplifyMethod;
383 QgsMaskRenderSettings mPreviousMaskSettings;
384 QStringList mExportThemes;
385 QVector< double > mPredefinedScales;
396 if ( settings.
dpi <= 0 )
397 settings.
dpi = mLayout->renderContext().dpi();
399 mErrorFileName.clear();
401 int worldFilePageNo = -1;
404 worldFilePageNo = referenceMap->page();
407 QFileInfo fi( filePath );
409 if ( !dir.exists( fi.absolutePath() ) )
411 dir.mkpath( fi.absolutePath() );
416 pageDetails.
baseName = fi.completeBaseName();
419 LayoutContextPreviewSettingRestorer restorer( mLayout );
421 LayoutContextSettingsRestorer dpiRestorer( mLayout );
423 mLayout->renderContext().setDpi( settings.
dpi );
424 mLayout->renderContext().setFlags( settings.
flags );
429 if ( settings.
pages.empty() )
431 for (
int page = 0; page < mLayout->pageCollection()->pageCount(); ++page )
436 for (
int page : std::as_const( settings.
pages ) )
438 if ( page >= 0 && page < mLayout->pageCollection()->pageCount() )
443 for (
int page : std::as_const( pages ) )
445 if ( !mLayout->pageCollection()->shouldExportPage( page ) )
452 QImage image = createImage( settings, page, bounds, skip );
457 pageDetails.
page = page;
460 if ( image.isNull() )
462 mErrorFileName = outputFilePath;
468 mErrorFileName = outputFilePath;
472 const bool shouldGeoreference = ( page == worldFilePageNo );
473 if ( shouldGeoreference )
475 georeferenceOutputPrivate( outputFilePath,
nullptr, bounds, settings.
dpi, shouldGeoreference );
480 double a, b,
c, d, e, f;
481 if ( bounds.isValid() )
486 QFileInfo fi( outputFilePath );
488 QString outputSuffix = fi.suffix();
489 QString worldFileName = fi.absolutePath() +
'/' + fi.completeBaseName() +
'.'
490 + outputSuffix.at( 0 ) + outputSuffix.at( fi.suffix().size() - 1 ) +
'w';
492 writeWorldFile( worldFileName, a, b,
c, d, e, f );
497 captureLabelingResults();
508 int total = iterator->
count();
509 double step = total > 0 ? 100.0 / total : 100.0;
511 while ( iterator->
next() )
516 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
518 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ) );
528 QString filePath = iterator->
filePath( baseFilePath, extension );
533 error = QObject::tr(
"Cannot write to %1. This file may be open in another application or may be an invalid path." ).arg( QDir::toNativeSeparators( filePath ) );
553 if ( !mLayout || mLayout->pageCollection()->pageCount() == 0 )
557 if ( settings.
dpi <= 0 )
558 settings.
dpi = mLayout->renderContext().dpi();
560 mErrorFileName.clear();
562 LayoutContextPreviewSettingRestorer restorer( mLayout );
564 LayoutContextSettingsRestorer contextRestorer( mLayout );
565 ( void )contextRestorer;
566 mLayout->renderContext().setDpi( settings.
dpi );
568 mLayout->renderContext().setMaskSettings( createExportMaskSettings() );
572 mLayout->renderContext().setSimplifyMethod( createExportSimplifyMethod() );
575 std::unique_ptr< QgsLayoutGeospatialPdfExporter > geospatialPdfExporter;
577 geospatialPdfExporter = std::make_unique< QgsLayoutGeospatialPdfExporter >( mLayout );
579 mLayout->renderContext().setFlags( settings.
flags );
602 mLayout->renderContext().setExportThemes( settings.
exportThemes );
614 const QList<QGraphicsItem *> items = mLayout->items( Qt::AscendingOrder );
616 QList< QgsLayoutGeospatialPdfExporter::ComponentLayerDetail > pdfComponents;
621 QSet<QString> mutuallyExclusiveGroups;
627 component.
name = layerDetail.name;
628 component.
mapLayerId = layerDetail.mapLayerId;
629 component.
opacity = layerDetail.opacity;
631 component.
group = layerDetail.groupName;
632 if ( !layerDetail.mapTheme.isEmpty() )
634 component.
group = layerDetail.mapTheme;
635 mutuallyExclusiveGroups.insert( layerDetail.mapTheme );
638 component.
sourcePdfPath = settings.writeGeoPdf ? geospatialPdfExporter->generateTemporaryFilepath( QStringLiteral(
"layer_%1.pdf" ).arg( layerId ) ) : baseDir.filePath( QStringLiteral(
"%1_%2.pdf" ).arg( baseFileName ).arg( layerId, 4, 10, QChar(
'0' ) ) );
639 pdfComponents << component;
641 preparePrintAsPdf( mLayout, &printer, component.
sourcePdfPath );
642 preparePrint( mLayout, &printer,
false );
644 if ( !p.begin( &printer ) )
652 return layerExportResult;
654 auto getExportGroupNameFunc = [](
QgsLayoutItem * item )->QString
656 return item->customProperty( QStringLiteral(
"pdfExportGroup" ) ).toString();
658 result = handleLayeredExport( items, exportFunc, getExportGroupNameFunc );
662 if ( settings.writeGeoPdf )
665 details.
dpi = settings.dpi;
667 QgsLayoutSize pageSize = mLayout->pageCollection()->page( 0 )->sizeWithUnits();
672 if ( settings.exportMetadata )
675 details.
author = mLayout->project()->metadata().author();
677 details.
creator = getCreator();
678 details.
creationDateTime = mLayout->project()->metadata().creationDateTime();
679 details.
subject = mLayout->project()->metadata().abstract();
680 details.
title = mLayout->project()->metadata().title();
681 details.
keywords = mLayout->project()->metadata().keywords();
684 const QList< QgsMapLayer * > layers = mLayout->project()->mapLayers().values();
690 if ( settings.appendGeoreference )
693 QList< QgsLayoutItemMap * > maps;
694 mLayout->layoutItems( maps );
698 georef.
crs = map->crs();
700 const QPointF topLeft = map->mapToScene( QPointF( 0, 0 ) );
701 const QPointF topRight = map->mapToScene( QPointF( map->rect().width(), 0 ) );
702 const QPointF bottomLeft = map->mapToScene( QPointF( 0, map->rect().height() ) );
703 const QPointF bottomRight = map->mapToScene( QPointF( map->rect().width(), map->rect().height() ) );
716 const QTransform t = map->layoutToMapCoordsTransform();
717 const QgsPointXY topLeftMap = t.map( topLeft );
718 const QgsPointXY topRightMap = t.map( topRight );
719 const QgsPointXY bottomLeftMap = t.map( bottomLeft );
720 const QgsPointXY bottomRightMap = t.map( bottomRight );
732 details.
layerOrder = geospatialPdfExporter->layerOrder();
737 if ( !geospatialPdfExporter->finalize( pdfComponents, filePath, details ) )
740 mErrorMessage = geospatialPdfExporter->errorMessage();
750 QPdfWriter printer = QPdfWriter( filePath );
751 preparePrintAsPdf( mLayout, &printer, filePath );
752 preparePrint( mLayout, &printer,
false );
754 if ( !p.begin( &printer ) )
763 bool shouldAppendGeoreference = settings.
appendGeoreference && mLayout && mLayout->referenceMap() && mLayout->referenceMap()->page() == 0;
766 georeferenceOutputPrivate( filePath,
nullptr, QRectF(), settings.
dpi, shouldAppendGeoreference, settings.
exportMetadata );
769 captureLabelingResults();
782 QPdfWriter printer = QPdfWriter( fileName );
785 int total = iterator->
count();
786 double step = total > 0 ? 100.0 / total : 100.0;
789 while ( iterator->
next() )
794 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
796 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ) );
808 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
810 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
811 ( void )contextRestorer;
838 preparePrintAsPdf( iterator->
layout(), &printer, fileName );
839 preparePrint( iterator->
layout(), &printer,
false );
841 if ( !p.begin( &printer ) )
855 error = QObject::tr(
"Cannot write to %1. This file may be open in another application or may be an invalid path." ).arg( QDir::toNativeSeparators( fileName ) );
882 int total = iterator->
count();
883 double step = total > 0 ? 100.0 / total : 100.0;
885 while ( iterator->
next() )
890 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
892 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ) );
901 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"pdf" ) );
908 error = QObject::tr(
"Cannot write to %1. This file may be open in another application or may be an invalid path." ).arg( QDir::toNativeSeparators( filePath ) );
926#if defined( HAVE_QTPRINTER )
933 if ( settings.
dpi <= 0 )
934 settings.
dpi = mLayout->renderContext().dpi();
936 mErrorFileName.clear();
938 LayoutContextPreviewSettingRestorer restorer( mLayout );
940 LayoutContextSettingsRestorer contextRestorer( mLayout );
941 ( void )contextRestorer;
942 mLayout->renderContext().setDpi( settings.
dpi );
944 mLayout->renderContext().setFlags( settings.
flags );
951 preparePrint( mLayout, &printer,
true );
953 if ( !p.begin( &printer ) )
962 captureLabelingResults();
977 int total = iterator->
count();
978 double step = total > 0 ? 100.0 / total : 100.0;
981 while ( iterator->
next() )
986 feedback->setProperty(
"progress", QObject::tr(
"Printing %1 of %2" ).arg( i + 1 ).arg( total ) );
988 feedback->setProperty(
"progress", QObject::tr(
"Printing section %1" ).arg( i + 1 ) );
1000 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
1002 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
1003 ( void )contextRestorer;
1012 if ( !settings.rasterizeWholeImage )
1017 preparePrint( iterator->
layout(), &printer,
true );
1019 if ( !p.begin( &printer ) )
1029 ExportResult result = exporter.printPrivate( &printer, p, !first, settings.dpi, settings.rasterizeWholeImage );
1033 error = exporter.errorMessage();
1056 if ( settings.
dpi <= 0 )
1057 settings.
dpi = mLayout->renderContext().dpi();
1059 mErrorFileName.clear();
1061 LayoutContextPreviewSettingRestorer restorer( mLayout );
1063 LayoutContextSettingsRestorer contextRestorer( mLayout );
1064 ( void )contextRestorer;
1065 mLayout->renderContext().setDpi( settings.
dpi );
1067 mLayout->renderContext().setFlags( settings.
flags );
1082 mLayout->renderContext().setMaskSettings( createExportMaskSettings() );
1086 mLayout->renderContext().setSimplifyMethod( createExportSimplifyMethod() );
1089 QFileInfo fi( filePath );
1092 pageDetails.
baseName = fi.baseName();
1093 pageDetails.
extension = fi.completeSuffix();
1097 for (
int i = 0; i < mLayout->pageCollection()->pageCount(); ++i )
1099 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1104 pageDetails.
page = i;
1111 if ( mLayout->pageCollection()->pageCount() == 1 )
1114 bounds = mLayout->layoutBounds(
true );
1119 bounds = mLayout->pageItemBounds( i,
true );
1128 bounds = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
1132 int width =
static_cast< int >( bounds.width() * settings.
dpi / inchesToLayoutUnits );
1134 int height =
static_cast< int >( bounds.height() * settings.
dpi / inchesToLayoutUnits );
1135 if ( width == 0 || height == 0 )
1144 const QRectF paperRect = QRectF( pageItem->pos().x(),
1145 pageItem->pos().y(),
1146 pageItem->rect().width(),
1147 pageItem->rect().height() );
1149 QDomNode svgDocRoot;
1150 const QList<QGraphicsItem *> items = mLayout->items( paperRect,
1151 Qt::IntersectsItemBoundingRect,
1152 Qt::AscendingOrder );
1156 return renderToLayeredSvg( settings, width, height, i, bounds, fileName, layerId, layerDetail.name, svg, svgDocRoot, settings.
exportMetadata );
1158 auto getExportGroupNameFunc = [](
QgsLayoutItem * )->QString
1162 ExportResult res = handleLayeredExport( items, exportFunc, getExportGroupNameFunc );
1167 appendMetadataToSvg( svg );
1169 QFile out( fileName );
1170 bool openOk = out.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate );
1173 mErrorFileName = fileName;
1177 out.write( svg.toByteArray() );
1183 QSvgGenerator generator;
1186 generator.setTitle( mLayout->project()->metadata().title() );
1187 generator.setDescription( mLayout->project()->metadata().abstract() );
1189 generator.setOutputDevice( &svgBuffer );
1190 generator.setSize( QSize( width, height ) );
1191 generator.setViewBox( QRect( 0, 0, width, height ) );
1192 generator.setResolution(
static_cast< int >( std::round( settings.
dpi ) ) );
1195 bool createOk = p.begin( &generator );
1198 mErrorFileName = fileName;
1211 svgBuffer.open( QIODevice::ReadOnly );
1215 if ( ! svg.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1217 mErrorFileName = fileName;
1222 appendMetadataToSvg( svg );
1224 QFile out( fileName );
1225 bool openOk = out.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate );
1228 mErrorFileName = fileName;
1232 out.write( svg.toByteArray() );
1236 captureLabelingResults();
1247 int total = iterator->
count();
1248 double step = total > 0 ? 100.0 / total : 100.0;
1250 while ( iterator->
next() )
1255 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
1257 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ) );
1267 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"svg" ) );
1274 error = QObject::tr(
"Cannot write to %1. This file may be open in another application or may be an invalid path." ).arg( QDir::toNativeSeparators( filePath ) );
1295 return mLabelingResults;
1300 QMap<QString, QgsLabelingResults *> res;
1301 std::swap( mLabelingResults, res );
1305void QgsLayoutExporter::preparePrintAsPdf(
QgsLayout *layout, QPdfWriter *device,
const QString &filePath )
1307 QFileInfo fi( filePath );
1309 if ( !dir.exists( fi.absolutePath() ) )
1311 dir.mkpath( fi.absolutePath() );
1314 updatePrinterPageSize(
layout, device, firstPageToBeExported(
layout ) );
1317 const QString title = !
layout->project() ||
layout->project()->metadata().title().isEmpty() ?
1318 fi.baseName() :
layout->project()->metadata().title();
1320 device->setTitle( title );
1322 QPagedPaintDevice::PdfVersion pdfVersion = QPagedPaintDevice::PdfVersion_1_4;
1324#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
1326 if (
const QgsProjectStyleSettings *styleSettings = (
layout->project() ?
layout->project()->styleSettings() :
nullptr ) )
1330 switch ( styleSettings->colorModel() )
1333 device->setColorModel( QPdfWriter::ColorModel::CMYK );
1337 device->setColorModel( QPdfWriter::ColorModel::RGB );
1341 const QColorSpace colorSpace = styleSettings->colorSpace();
1342 if ( colorSpace.isValid() )
1344 QPdfOutputIntent outputIntent;
1345 outputIntent.setOutputProfile( colorSpace );
1346 outputIntent.setOutputCondition( colorSpace.description() );
1350 outputIntent.setOutputConditionIdentifier( QStringLiteral(
"Unknown identifier" ) );
1351 outputIntent.setRegistryName( QStringLiteral(
"Unknown registry" ) );
1352 device->setOutputIntent( outputIntent );
1355 pdfVersion = QPagedPaintDevice::PdfVersion_X4;
1361 device->setPdfVersion( pdfVersion );
1362 setXmpMetadata( device,
layout );
1368#if defined(HAS_KDE_QT5_PDF_TRANSFORM_FIX) || QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
1375void QgsLayoutExporter::preparePrint(
QgsLayout *layout, QPagedPaintDevice *device,
bool setFirstPageSize )
1377 if ( QPdfWriter *pdf =
dynamic_cast<QPdfWriter *
>( device ) )
1379 pdf->setResolution(
static_cast< int>( std::round(
layout->renderContext().dpi() ) ) );
1381#if defined( HAVE_QTPRINTER )
1382 else if ( QPrinter *printer =
dynamic_cast<QPrinter *
>( device ) )
1384 printer->setFullPage(
true );
1385 printer->setColorMode( QPrinter::Color );
1387 printer->setResolution(
static_cast< int>( std::round(
layout->renderContext().dpi() ) ) );
1391 if ( setFirstPageSize )
1393 updatePrinterPageSize(
layout, device, firstPageToBeExported(
layout ) );
1399 if ( mLayout->pageCollection()->pageCount() == 0 )
1402 preparePrint( mLayout, device,
true );
1404 if ( !p.begin( device ) )
1410 printPrivate( device, p );
1415QgsLayoutExporter::ExportResult QgsLayoutExporter::printPrivate( QPagedPaintDevice *device, QPainter &painter,
bool startNewPage,
double dpi,
bool rasterize )
1419 int toPage = mLayout->pageCollection()->pageCount() - 1;
1421#if defined( HAVE_QTPRINTER )
1422 if ( QPrinter *printer =
dynamic_cast<QPrinter *
>( device ) )
1424 if ( printer->fromPage() >= 1 )
1425 fromPage = printer->fromPage() - 1;
1426 if ( printer->toPage() >= 1 )
1427 toPage = printer->toPage() - 1;
1431 bool pageExported =
false;
1434 for (
int i = fromPage; i <= toPage; ++i )
1436 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1441 updatePrinterPageSize( mLayout, device, i );
1442 if ( ( pageExported && i > fromPage ) || startNewPage )
1448 if ( !image.isNull() )
1450 QRectF targetArea( 0, 0, image.width(), image.height() );
1451 painter.drawImage( targetArea, image, targetArea );
1457 pageExported =
true;
1462 for (
int i = fromPage; i <= toPage; ++i )
1464 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1469 updatePrinterPageSize( mLayout, device, i );
1471 if ( ( pageExported && i > fromPage ) || startNewPage )
1476 pageExported =
true;
1482void QgsLayoutExporter::updatePrinterPageSize(
QgsLayout *layout, QPagedPaintDevice *device,
int page )
1484 QgsLayoutSize pageSize =
layout->pageCollection()->page( page )->sizeWithUnits();
1487 QPageLayout pageLayout( QPageSize( pageSizeMM.
toQSizeF(), QPageSize::Millimeter ),
1488 QPageLayout::Portrait,
1489 QMarginsF( 0, 0, 0, 0 ) );
1490 pageLayout.setMode( QPageLayout::FullPageMode );
1491 device->setPageLayout( pageLayout );
1492 device->setPageMargins( QMarginsF( 0, 0, 0, 0 ) );
1494#if defined( HAVE_QTPRINTER )
1495 if ( QPrinter *printer =
dynamic_cast<QPrinter *
>( device ) )
1497 printer->setFullPage(
true );
1502QgsLayoutExporter::ExportResult QgsLayoutExporter::renderToLayeredSvg(
const SvgExportSettings &settings,
double width,
double height,
int page,
const QRectF &bounds,
const QString &filename,
unsigned int svgLayerId,
const QString &layerName, QDomDocument &svg, QDomNode &svgDocRoot,
bool includeMetadata )
const
1506 QSvgGenerator generator;
1507 if ( includeMetadata )
1509 if (
const QgsMasterLayoutInterface *l =
dynamic_cast< const QgsMasterLayoutInterface *
>( mLayout.data() ) )
1510 generator.setTitle( l->name() );
1511 else if ( mLayout->project() )
1512 generator.setTitle( mLayout->project()->title() );
1515 generator.setOutputDevice( &svgBuffer );
1516 generator.setSize( QSize(
static_cast< int >( std::round( width ) ),
1517 static_cast< int >( std::round( height ) ) ) );
1518 generator.setViewBox( QRect( 0, 0,
1519 static_cast< int >( std::round( width ) ),
1520 static_cast< int >( std::round( height ) ) ) );
1521 generator.setResolution(
static_cast< int >( std::round( settings.dpi ) ) );
1523 QPainter svgPainter( &generator );
1524 if ( settings.cropToContents )
1535 svgBuffer.open( QIODevice::ReadOnly );
1539 if ( ! doc.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1541 mErrorFileName = filename;
1544 if ( 1 == svgLayerId )
1546 svg = QDomDocument( doc.doctype() );
1547 svg.appendChild( svg.importNode( doc.firstChild(),
false ) );
1548 svgDocRoot = svg.importNode( doc.elementsByTagName( QStringLiteral(
"svg" ) ).at( 0 ),
false );
1549 svgDocRoot.toElement().setAttribute( QStringLiteral(
"xmlns:inkscape" ), QStringLiteral(
"http://www.inkscape.org/namespaces/inkscape" ) );
1550 svg.appendChild( svgDocRoot );
1552 QDomNode mainGroup = svg.importNode( doc.elementsByTagName( QStringLiteral(
"g" ) ).at( 0 ),
true );
1553 mainGroup.toElement().setAttribute( QStringLiteral(
"id" ), layerName );
1554 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:label" ), layerName );
1555 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:groupmode" ), QStringLiteral(
"layer" ) );
1556 QDomNode defs = svg.importNode( doc.elementsByTagName( QStringLiteral(
"defs" ) ).at( 0 ),
true );
1557 svgDocRoot.appendChild( defs );
1558 svgDocRoot.appendChild( mainGroup );
1563void QgsLayoutExporter::appendMetadataToSvg( QDomDocument &svg )
const
1565 const QgsProjectMetadata &metadata = mLayout->project()->metadata();
1566 QDomElement metadataElement = svg.createElement( QStringLiteral(
"metadata" ) );
1567 QDomElement rdfElement = svg.createElement( QStringLiteral(
"rdf:RDF" ) );
1568 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdf" ), QStringLiteral(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#" ) );
1569 rdfElement.setAttribute( QStringLiteral(
"xmlns:rdfs" ), QStringLiteral(
"http://www.w3.org/2000/01/rdf-schema#" ) );
1570 rdfElement.setAttribute( QStringLiteral(
"xmlns:dc" ), QStringLiteral(
"http://purl.org/dc/elements/1.1/" ) );
1571 QDomElement descriptionElement = svg.createElement( QStringLiteral(
"rdf:Description" ) );
1572 QDomElement workElement = svg.createElement( QStringLiteral(
"cc:Work" ) );
1573 workElement.setAttribute( QStringLiteral(
"rdf:about" ), QString() );
1575 auto addTextNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1578 QDomElement element = svg.createElement( tag );
1579 QDomText t = svg.createTextNode( value );
1580 element.appendChild( t );
1581 workElement.appendChild( element );
1584 descriptionElement.setAttribute( tag, value );
1587 addTextNode( QStringLiteral(
"dc:format" ), QStringLiteral(
"image/svg+xml" ) );
1588 addTextNode( QStringLiteral(
"dc:title" ), metadata.
title() );
1589 addTextNode( QStringLiteral(
"dc:date" ), metadata.
creationDateTime().toString( Qt::ISODate ) );
1590 addTextNode( QStringLiteral(
"dc:identifier" ), metadata.
identifier() );
1591 addTextNode( QStringLiteral(
"dc:description" ), metadata.
abstract() );
1593 auto addAgentNode = [&workElement, &descriptionElement, &svg](
const QString & tag,
const QString & value )
1596 QDomElement inkscapeElement = svg.createElement( tag );
1597 QDomElement agentElement = svg.createElement( QStringLiteral(
"cc:Agent" ) );
1598 QDomElement titleElement = svg.createElement( QStringLiteral(
"dc:title" ) );
1599 QDomText t = svg.createTextNode( value );
1600 titleElement.appendChild( t );
1601 agentElement.appendChild( titleElement );
1602 inkscapeElement.appendChild( agentElement );
1603 workElement.appendChild( inkscapeElement );
1606 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1607 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1608 t = svg.createTextNode( value );
1609 liElement.appendChild( t );
1610 bagElement.appendChild( liElement );
1612 QDomElement element = svg.createElement( tag );
1613 element.appendChild( bagElement );
1614 descriptionElement.appendChild( element );
1617 addAgentNode( QStringLiteral(
"dc:creator" ), metadata.
author() );
1618 addAgentNode( QStringLiteral(
"dc:publisher" ), getCreator() );
1622 QDomElement element = svg.createElement( QStringLiteral(
"dc:subject" ) );
1623 QDomElement bagElement = svg.createElement( QStringLiteral(
"rdf:Bag" ) );
1625 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1627 const QStringList words = it.value();
1628 for (
const QString &keyword : words )
1630 QDomElement liElement = svg.createElement( QStringLiteral(
"rdf:li" ) );
1631 QDomText t = svg.createTextNode( keyword );
1632 liElement.appendChild( t );
1633 bagElement.appendChild( liElement );
1636 element.appendChild( bagElement );
1637 workElement.appendChild( element );
1638 descriptionElement.appendChild( element );
1641 rdfElement.appendChild( descriptionElement );
1642 rdfElement.appendChild( workElement );
1643 metadataElement.appendChild( rdfElement );
1644 svg.documentElement().appendChild( metadataElement );
1645 svg.documentElement().setAttribute( QStringLiteral(
"xmlns:cc" ), QStringLiteral(
"http://creativecommons.org/ns#" ) );
1648std::unique_ptr<double[]> QgsLayoutExporter::computeGeoTransform(
const QgsLayoutItemMap *map,
const QRectF ®ion,
double dpi )
const
1651 map = mLayout->referenceMap();
1657 dpi = mLayout->renderContext().dpi();
1660 QRectF exportRegion = region;
1661 if ( !exportRegion.isValid() )
1663 int pageNumber = map->
page();
1665 QgsLayoutItemPage *page = mLayout->pageCollection()->page( pageNumber );
1666 double pageY = page->pos().y();
1667 QSizeF pageSize = page->rect().size();
1668 exportRegion = QRectF( 0, pageY, pageSize.width(), pageSize.height() );
1672 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1675 double outputHeightMM = exportRegion.height();
1676 double outputWidthMM = exportRegion.width();
1679 QgsRectangle mapExtent = map->
extent();
1680 double mapXCenter = mapExtent.
center().
x();
1681 double mapYCenter = mapExtent.
center().
y();
1683 double sinAlpha = std::sin( alpha );
1684 double cosAlpha = std::cos( alpha );
1687 QPointF mapItemPos = map->pos();
1689 mapItemPos.rx() -= exportRegion.left();
1690 mapItemPos.ry() -= exportRegion.top();
1693 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1694 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1695 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1696 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1697 QgsRectangle paperExtent( xmin, ymax - outputHeightMM * yRatio, xmin + outputWidthMM * xRatio, ymax );
1700 double X0 = paperExtent.xMinimum();
1701 double Y0 = paperExtent.yMaximum();
1706 double X1 = X0 - mapXCenter;
1707 double Y1 = Y0 - mapYCenter;
1708 double X2 = X1 * cosAlpha + Y1 * sinAlpha;
1709 double Y2 = -X1 * sinAlpha + Y1 * cosAlpha;
1710 X0 = X2 + mapXCenter;
1711 Y0 = Y2 + mapYCenter;
1715 int pageWidthPixels =
static_cast< int >( dpi * outputWidthMM / 25.4 );
1716 int pageHeightPixels =
static_cast< int >( dpi * outputHeightMM / 25.4 );
1717 double pixelWidthScale = paperExtent.width() / pageWidthPixels;
1718 double pixelHeightScale = paperExtent.height() / pageHeightPixels;
1721 std::unique_ptr<double[]> t(
new double[6] );
1723 t[1] = cosAlpha * pixelWidthScale;
1724 t[2] = -sinAlpha * pixelWidthScale;
1726 t[4] = -sinAlpha * pixelHeightScale;
1727 t[5] = -cosAlpha * pixelHeightScale;
1732void QgsLayoutExporter::writeWorldFile(
const QString &worldFileName,
double a,
double b,
double c,
double d,
double e,
double f )
const
1734 QFile worldFile( worldFileName );
1735 if ( !worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
1739 QTextStream fout( &worldFile );
1743 fout << QString::number( a,
'f', 12 ) <<
"\r\n";
1744 fout << QString::number( d,
'f', 12 ) <<
"\r\n";
1745 fout << QString::number( b,
'f', 12 ) <<
"\r\n";
1746 fout << QString::number( e,
'f', 12 ) <<
"\r\n";
1747 fout << QString::number(
c,
'f', 12 ) <<
"\r\n";
1748 fout << QString::number( f,
'f', 12 ) <<
"\r\n";
1753 return georeferenceOutputPrivate( file, map, exportRegion, dpi,
false );
1756bool QgsLayoutExporter::georeferenceOutputPrivate(
const QString &file,
QgsLayoutItemMap *map,
const QRectF &exportRegion,
double dpi,
bool includeGeoreference,
bool includeMetadata )
const
1761 if ( !map && includeGeoreference )
1762 map = mLayout->referenceMap();
1764 std::unique_ptr<double[]> t;
1766 if ( map && includeGeoreference )
1769 dpi = mLayout->renderContext().dpi();
1771 t = computeGeoTransform( map, exportRegion, dpi );
1776 CPLSetConfigOption(
"GDAL_PDF_DPI", QString::number( dpi ).toUtf8().constData() );
1781 GDALSetGeoTransform( outputDS.get(), t.get() );
1783 if ( includeMetadata )
1785 QString creationDateString;
1786 const QDateTime creationDateTime = mLayout->project()->metadata().creationDateTime();
1787#if QT_FEATURE_timezone > 0
1788 if ( creationDateTime.isValid() )
1790 creationDateString = QStringLiteral(
"D:%1" ).arg( mLayout->project()->metadata().creationDateTime().toString( QStringLiteral(
"yyyyMMddHHmmss" ) ) );
1791 if ( creationDateTime.timeZone().isValid() )
1793 int offsetFromUtc = creationDateTime.timeZone().offsetFromUtc( creationDateTime );
1794 creationDateString += ( offsetFromUtc >= 0 ) ?
'+' :
'-';
1795 offsetFromUtc = std::abs( offsetFromUtc );
1796 int offsetHours = offsetFromUtc / 3600;
1797 int offsetMins = ( offsetFromUtc % 3600 ) / 60;
1798 creationDateString += QStringLiteral(
"%1'%2'" ).arg( offsetHours ).arg( offsetMins );
1802 QgsDebugError( QStringLiteral(
"Qt is built without timezone support, skipping timezone for pdf export" ) );
1804 GDALSetMetadataItem( outputDS.get(),
"CREATION_DATE", creationDateString.toUtf8().constData(),
nullptr );
1806 GDALSetMetadataItem( outputDS.get(),
"AUTHOR", mLayout->project()->metadata().author().toUtf8().constData(),
nullptr );
1807 const QString creator = getCreator();
1808 GDALSetMetadataItem( outputDS.get(),
"CREATOR", creator.toUtf8().constData(),
nullptr );
1809 GDALSetMetadataItem( outputDS.get(),
"PRODUCER", creator.toUtf8().constData(),
nullptr );
1810 GDALSetMetadataItem( outputDS.get(),
"SUBJECT", mLayout->project()->metadata().abstract().toUtf8().constData(),
nullptr );
1811 GDALSetMetadataItem( outputDS.get(),
"TITLE", mLayout->project()->metadata().title().toUtf8().constData(),
nullptr );
1814 QStringList allKeywords;
1815 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
1817 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
1819 const QString keywordString = allKeywords.join(
';' );
1820 GDALSetMetadataItem( outputDS.get(),
"KEYWORDS", keywordString.toUtf8().constData(),
nullptr );
1826 CPLSetConfigOption(
"GDAL_PDF_DPI",
nullptr );
1833 if ( items.count() == 1 )
1837 QString name = layoutItem->displayName();
1839 if ( name.startsWith(
'<' ) && name.endsWith(
'>' ) )
1840 name = name.mid( 1, name.length() - 2 );
1844 else if ( items.count() > 1 )
1846 QStringList currentLayerItemTypes;
1847 for ( QGraphicsItem *item : items )
1853 if ( !currentLayerItemTypes.contains( itemType ) && !currentLayerItemTypes.contains( itemTypePlural ) )
1854 currentLayerItemTypes << itemType;
1855 else if ( currentLayerItemTypes.contains( itemType ) )
1857 currentLayerItemTypes.replace( currentLayerItemTypes.indexOf( itemType ), itemTypePlural );
1862 if ( !currentLayerItemTypes.contains( QObject::tr(
"Other" ) ) )
1863 currentLayerItemTypes.append( QObject::tr(
"Other" ) );
1866 return currentLayerItemTypes.join( QLatin1String(
", " ) );
1868 return QObject::tr(
"Layer %1" ).arg( layerId );
1873 const std::function<QString(
QgsLayoutItem *item )> &getItemExportGroupFunc )
1875 LayoutItemHider itemHider( items );
1880 QString previousItemGroup;
1881 unsigned int layerId = 1;
1882 QgsLayoutItem::ExportLayerDetail layerDetails;
1883 itemHider.hideAll();
1884 const QList< QGraphicsItem * > itemsToIterate = itemHider.itemsToIterate();
1885 QList< QGraphicsItem * > currentLayerItems;
1886 for ( QGraphicsItem *item : itemsToIterate )
1888 QgsLayoutItem *layoutItem =
dynamic_cast<QgsLayoutItem *
>( item );
1890 bool canPlaceInExistingLayer =
false;
1891 QString thisItemExportGroupName;
1895 thisItemExportGroupName = getItemExportGroupFunc( layoutItem );
1896 if ( !thisItemExportGroupName.isEmpty() )
1898 if ( thisItemExportGroupName != previousItemGroup && !currentLayerItems.empty() )
1901 layerDetails.
groupName = thisItemExportGroupName;
1904 switch ( itemExportBehavior )
1908 switch ( prevItemBehavior )
1911 canPlaceInExistingLayer =
true;
1915 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1920 canPlaceInExistingLayer =
false;
1928 switch ( prevItemBehavior )
1932 canPlaceInExistingLayer = prevType == -1 || prevType == layoutItem->
type();
1937 canPlaceInExistingLayer =
false;
1945 canPlaceInExistingLayer =
false;
1950 canPlaceInExistingLayer =
false;
1953 prevItemBehavior = itemExportBehavior;
1954 prevType = layoutItem->
type();
1955 previousItemGroup = thisItemExportGroupName;
1960 previousItemGroup.clear();
1963 if ( canPlaceInExistingLayer )
1965 currentLayerItems << item;
1970 if ( !currentLayerItems.isEmpty() )
1974 ExportResult result = exportFunc( layerId, layerDetails );
1978 currentLayerItems.clear();
1981 itemHider.hideAll();
1986 int layoutItemLayerIdx = 0;
1988 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1994 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
1998 ExportResult result = exportFunc( layerId, layerDetails );
2003 layoutItemLayerIdx++;
2005 layerDetails.mapLayerId.clear();
2007 mLayout->renderContext().setCurrentExportLayer( -1 );
2010 currentLayerItems.clear();
2014 currentLayerItems << item;
2016 layerDetails.groupName = thisItemExportGroupName;
2019 if ( !currentLayerItems.isEmpty() )
2022 ExportResult result = exportFunc( layerId, layerDetails );
2031 QgsVectorSimplifyMethod simplifyMethod;
2037 return simplifyMethod;
2042 QgsMaskRenderSettings settings;
2060 int pageNumber = map->
page();
2062 double pageY = page->pos().y();
2063 QSizeF pageSize = page->rect().size();
2064 QRectF pageRect( 0, pageY, pageSize.width(), pageSize.height() );
2080 double destinationHeight = exportRegion.height();
2081 double destinationWidth = exportRegion.width();
2083 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
2088 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
2089 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
2091 double xCenter = mapExtent.
center().
x();
2092 double yCenter = mapExtent.
center().
y();
2095 QPointF mapItemPos = map->pos();
2097 mapItemPos.rx() -= exportRegion.left();
2098 mapItemPos.ry() -= exportRegion.top();
2100 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
2101 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
2102 QgsRectangle paperExtent( xmin, ymax - destinationHeight * yRatio, xmin + destinationWidth * xRatio, ymax );
2104 double X0 = paperExtent.
xMinimum();
2105 double Y0 = paperExtent.
yMinimum();
2108 dpi = mLayout->renderContext().dpi();
2110 int widthPx =
static_cast< int >( dpi * destinationWidth / 25.4 );
2111 int heightPx =
static_cast< int >( dpi * destinationHeight / 25.4 );
2113 double Ww = paperExtent.
width() / widthPx;
2114 double Hh = paperExtent.
height() / heightPx;
2123 s[5] = Y0 + paperExtent.
height();
2127 r[0] = std::cos( alpha );
2128 r[1] = -std::sin( alpha );
2129 r[2] = xCenter * ( 1 - std::cos( alpha ) ) + yCenter * std::sin( alpha );
2130 r[3] = std::sin( alpha );
2131 r[4] = std::cos( alpha );
2132 r[5] = - xCenter * std::sin( alpha ) + yCenter * ( 1 - std::cos( alpha ) );
2135 a = r[0] * s[0] + r[1] * s[3];
2136 b = r[0] * s[1] + r[1] * s[4];
2137 c = r[0] * s[2] + r[1] * s[5] + r[2];
2138 d = r[3] * s[0] + r[4] * s[3];
2139 e = r[3] * s[1] + r[4] * s[4];
2140 f = r[3] * s[2] + r[4] * s[5] + r[5];
2148 QList< QgsLayoutItem *> items;
2149 layout->layoutItems( items );
2154 if ( currentItem->isVisible() && currentItem->requiresRasterization() )
2165 QList< QgsLayoutItem *> items;
2166 layout->layoutItems( items );
2171 if ( currentItem->isVisible() && currentItem->containsAdvancedEffects() )
2184 if ( mLayout->pageCollection()->pageCount() == 1 )
2187 bounds = mLayout->layoutBounds(
true );
2192 bounds = mLayout->pageItemBounds( page,
true );
2194 if ( bounds.width() <= 0 || bounds.height() <= 0 )
2202 bounds = bounds.adjusted( -settings.
cropMargins.
left() * pixelToLayoutUnits,
2214int QgsLayoutExporter::firstPageToBeExported(
QgsLayout *layout )
2216 const int pageCount =
layout->pageCollection()->pageCount();
2217 for (
int i = 0; i < pageCount; ++i )
2219 if ( !
layout->pageCollection()->shouldExportPage( i ) )
2231 if ( details.
page == 0 )
2241void QgsLayoutExporter::captureLabelingResults()
2243 qDeleteAll( mLabelingResults );
2244 mLabelingResults.clear();
2246 QList< QgsLayoutItemMap * > maps;
2247 mLayout->layoutItems( maps );
2251 mLabelingResults[ map->
uuid() ] = map->mExportLabelingResults.release();
2255bool QgsLayoutExporter::saveImage(
const QImage &image,
const QString &imageFilename,
const QString &imageFormat,
QgsProject *projectForMetadata,
int quality )
2257 QImageWriter w( imageFilename, imageFormat.toLocal8Bit().constData() );
2258 if ( imageFormat.compare( QLatin1String(
"tiff" ), Qt::CaseInsensitive ) == 0 || imageFormat.compare( QLatin1String(
"tif" ), Qt::CaseInsensitive ) == 0 )
2260 w.setCompression( 1 );
2264 w.setQuality( quality );
2266 if ( projectForMetadata )
2268 w.setText( QStringLiteral(
"Author" ), projectForMetadata->
metadata().
author() );
2269 const QString creator = getCreator();
2270 w.setText( QStringLiteral(
"Creator" ), creator );
2271 w.setText( QStringLiteral(
"Producer" ), creator );
2272 w.setText( QStringLiteral(
"Subject" ), projectForMetadata->
metadata().
abstract() );
2273 w.setText( QStringLiteral(
"Created" ), projectForMetadata->
metadata().
creationDateTime().toString( Qt::ISODate ) );
2274 w.setText( QStringLiteral(
"Title" ), projectForMetadata->
metadata().
title() );
2277 QStringList allKeywords;
2278 for (
auto it = keywords.constBegin(); it != keywords.constEnd(); ++it )
2280 allKeywords.append( QStringLiteral(
"%1: %2" ).arg( it.key(), it.value().join(
',' ) ) );
2282 const QString keywordString = allKeywords.join(
';' );
2283 w.setText( QStringLiteral(
"Keywords" ), keywordString );
2285 return w.write( image );
2288QString QgsLayoutExporter::getCreator()
2293void QgsLayoutExporter::setXmpMetadata( QPdfWriter *pdfWriter,
QgsLayout *layout )
2295#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
2296 QUuid documentId = pdfWriter->documentId();
2298 QUuid documentId = QUuid::createUuid();
2302 const QDateTime creationDateTime =
layout->project() ?
layout->project()->metadata().creationDateTime() : QDateTime();
2303 const QString metaDataDate = creationDateTime.isValid() ? creationDateTime.toOffsetFromUtc( creationDateTime.offsetFromUtc() ).toString( Qt::ISODate ) : QString();
2304 const QString title = pdfWriter->title();
2305 const QString creator = getCreator();
2306 const QString producer = creator;
2307 const QString author =
layout->project() ?
layout->project()->metadata().author() : QString();
2311 const QLatin1String xmlNS(
"http://www.w3.org/XML/1998/namespace" );
2312 const QLatin1String adobeNS(
"adobe:ns:meta/" );
2313 const QLatin1String rdfNS(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#" );
2314 const QLatin1String dcNS(
"http://purl.org/dc/elements/1.1/" );
2315 const QLatin1String xmpNS(
"http://ns.adobe.com/xap/1.0/" );
2316 const QLatin1String xmpMMNS(
"http://ns.adobe.com/xap/1.0/mm/" );
2317 const QLatin1String pdfNS(
"http://ns.adobe.com/pdf/1.3/" );
2318 const QLatin1String pdfaidNS(
"http://www.aiim.org/pdfa/ns/id/" );
2320 QByteArray xmpMetadata;
2321 QBuffer output( &xmpMetadata );
2322 output.open( QIODevice::WriteOnly );
2323 output.write(
"<?xpacket begin='' ?>" );
2325 QXmlStreamWriter w( &output );
2326 w.setAutoFormatting(
true );
2327 w.writeNamespace( adobeNS,
"x" );
2328 w.writeNamespace( rdfNS,
"rdf" );
2329 w.writeNamespace( dcNS,
"dc" );
2330 w.writeNamespace( xmpNS,
"xmp" );
2331 w.writeNamespace( xmpMMNS,
"xmpMM" );
2332 w.writeNamespace( pdfNS,
"pdf" );
2333 w.writeNamespace( pdfaidNS,
"pdfaid" );
2335 w.writeStartElement( adobeNS,
"xmpmeta" );
2336 w.writeStartElement( rdfNS,
"RDF" );
2339 w.writeStartElement( rdfNS,
"Description" );
2340 w.writeAttribute( rdfNS,
"about",
"" );
2341 w.writeStartElement( dcNS,
"title" );
2342 w.writeStartElement( rdfNS,
"Alt" );
2343 w.writeStartElement( rdfNS,
"li" );
2344 w.writeAttribute( xmlNS,
"lang",
"x-default" );
2345 w.writeCharacters( title );
2346 w.writeEndElement();
2347 w.writeEndElement();
2348 w.writeEndElement();
2350 w.writeStartElement( dcNS,
"creator" );
2351 w.writeStartElement( rdfNS,
"Seq" );
2352 w.writeStartElement( rdfNS,
"li" );
2353 w.writeCharacters( author );
2354 w.writeEndElement();
2355 w.writeEndElement();
2356 w.writeEndElement();
2358 w.writeEndElement();
2361 w.writeStartElement( rdfNS,
"Description" );
2362 w.writeAttribute( rdfNS,
"about",
"" );
2363 w.writeAttribute( pdfNS,
"Producer", producer );
2364 w.writeAttribute( pdfNS,
"Trapped",
"False" );
2365 w.writeEndElement();
2368 w.writeStartElement( rdfNS,
"Description" );
2369 w.writeAttribute( rdfNS,
"about",
"" );
2370 w.writeAttribute( xmpNS,
"CreatorTool", creator );
2371 w.writeAttribute( xmpNS,
"CreateDate", metaDataDate );
2372 w.writeAttribute( xmpNS,
"ModifyDate", metaDataDate );
2373 w.writeAttribute( xmpNS,
"MetadataDate", metaDataDate );
2374 w.writeEndElement();
2377 w.writeStartElement( rdfNS,
"Description" );
2378 w.writeAttribute( rdfNS,
"about",
"" );
2379 w.writeAttribute( xmpMMNS,
"DocumentID",
"uuid:" + documentId.toString( QUuid::WithoutBraces ) );
2380 w.writeAttribute( xmpMMNS,
"VersionID",
"1" );
2381 w.writeAttribute( xmpMMNS,
"RenditionClass",
"default" );
2382 w.writeEndElement();
2384#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
2387 switch ( pdfWriter->pdfVersion() )
2389 case QPagedPaintDevice::PdfVersion_1_4:
2390 case QPagedPaintDevice::PdfVersion_A1b:
2391 case QPagedPaintDevice::PdfVersion_1_6:
2393 case QPagedPaintDevice::PdfVersion_X4:
2394 const QLatin1String pdfxidNS(
"http://www.npes.org/pdfx/ns/id/" );
2395 w.writeNamespace( pdfxidNS,
"pdfxid" );
2396 w.writeStartElement( rdfNS,
"Description" );
2397 w.writeAttribute( rdfNS,
"about",
"" );
2398 w.writeAttribute( pdfxidNS,
"GTS_PDFXVersion",
"PDF/X-4" );
2399 w.writeEndElement();
2405 w.writeEndElement();
2406 w.writeEndElement();
2408 w.writeEndDocument();
2409 output.write(
"<?xpacket end='w'?>" );
2411 pdfWriter->setDocumentXmpMetadata( xmpMetadata );
RasterizedRenderingPolicy
Policies controlling when rasterisation of content during renders is permitted.
@ Default
Allow raster-based rendering in situations where it is required for correct rendering or where it wil...
@ PreferVector
Prefer vector-based rendering, when the result will still be visually near-identical to a raster-base...
@ ForceVector
Always force vector-based rendering, even when the result will be visually different to a raster-base...
static QString version()
Version string.
@ Millimeters
Millimeters.
@ GeometrySimplification
The geometries can be simplified using the current map2pixel context state.
@ SnappedToGridGlobal
Snap to a global grid based on the tolerance. Good for consistent results for incoming vertices,...
@ Warning
Warning message.
QFlags< LayoutRenderFlag > LayoutRenderFlags
Flags for controlling how a layout is rendered.
TextRenderFormat
Options for rendering text.
@ AlwaysOutlines
Always render text using path objects (AKA outlines/curves). This setting guarantees the best quality...
@ PreferredGdal
Preferred format for conversion of CRS to WKT for use with the GDAL library.
@ SynchronousLegendGraphics
Query legend graphics synchronously.
@ LosslessImageRendering
Render images losslessly whenever possible, instead of the default lossy jpeg rendering used for some...
@ Antialiasing
Use antialiasing when drawing items.
@ RenderLabelsByMapLayer
When rendering map items to multi-layered exports, render labels belonging to different layers into s...
An abstract base class for QgsLayout based classes which can be exported by QgsLayoutExporter.
virtual bool endRender()=0
Ends the render, performing any required cleanup tasks.
virtual QgsLayout * layout()=0
Returns the layout associated with the iterator.
virtual bool next()=0
Iterates to next feature, returning false if no more features exist to iterate over.
virtual bool beginRender()=0
Called when rendering begins, before iteration commences.
virtual QString filePath(const QString &baseFilePath, const QString &extension)=0
Returns the file path for the current feature, based on a specified base file path and extension.
virtual int count() const =0
Returns the number of features to iterate over.
static QgsLayoutItemRegistry * layoutItemRegistry()
Returns the application's layout item registry, used for layout item types.
QString toWkt(Qgis::CrsWktVariant variant=Qgis::CrsWktVariant::Wkt1Gdal, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
ExportResult exportToSvg(const QString &filePath, const QgsLayoutExporter::SvgExportSettings &settings)
Exports the layout as an SVG to the filePath, using the specified export settings.
ExportResult exportToImage(const QString &filePath, const QgsLayoutExporter::ImageExportSettings &settings)
Exports the layout to the filePath, using the specified export settings.
QString errorMessage() const
Returns a string describing the last error encountered during an export.
ExportResult exportToPdf(const QString &filePath, const QgsLayoutExporter::PdfExportSettings &settings)
Exports the layout as a PDF to the filePath, using the specified export settings.
virtual ~QgsLayoutExporter()
QImage renderRegionToImage(const QRectF ®ion, QSize imageSize=QSize(), double dpi=-1) const
Renders a region of the layout to an image.
QMap< QString, QgsLabelingResults * > takeLabelingResults()
Takes the labeling results for all map items included in the export.
static bool requiresRasterization(const QgsLayout *layout)
Returns true if the specified layout contains visible items which have settings that require rasteriz...
QgsLayout * layout() const
Returns the layout linked to this exporter.
bool georeferenceOutput(const QString &file, QgsLayoutItemMap *referenceMap=nullptr, const QRectF &exportRegion=QRectF(), double dpi=-1) const
Georeferences a file (image of PDF) exported from the layout.
static const QgsSettingsEntryBool * settingOpenAfterExportingPdf
Settings entry - Whether to automatically open pdfs after exporting them.
virtual QString generateFileName(const PageExportDetails &details) const
Generates the file name for a page during export.
ExportResult
Result codes for exporting layouts.
@ Canceled
Export was canceled.
@ MemoryError
Unable to allocate memory required to export.
@ PrintError
Could not start printing to destination device.
@ IteratorError
Error iterating over layout.
@ FileError
Could not write to destination file, likely due to a lock held by another application.
@ Success
Export was successful.
@ SvgLayerError
Could not create layered SVG file.
static const QgsSettingsEntryInteger * settingImageQuality
Settings entry - Image quality for lossy formats.
QImage renderPageToImage(int page, QSize imageSize=QSize(), double dpi=-1) const
Renders a full page to an image.
QgsLayoutExporter(QgsLayout *layout)
Constructor for QgsLayoutExporter, for the specified layout.
static ExportResult exportToPdfs(QgsAbstractLayoutIterator *iterator, const QString &baseFilePath, const QgsLayoutExporter::PdfExportSettings &settings, QString &error, QgsFeedback *feedback=nullptr)
Exports a layout iterator to multiple PDF files, with the specified export settings.
void computeWorldFileParameters(double &a, double &b, double &c, double &d, double &e, double &f, double dpi=-1) const
Compute world file parameters.
void renderPage(QPainter *painter, int page) const
Renders a full page to a destination painter.
static const QgsSettingsEntryBool * settingOpenAfterExportingImage
Settings entry - Whether to automatically open images after exporting them.
static const QgsSettingsEntryBool * settingOpenAfterExportingSvg
Settings entry - Whether to automatically open svgs after exporting them.
QMap< QString, QgsLabelingResults * > labelingResults()
Returns the labeling results for all map items included in the export.
static bool containsAdvancedEffects(const QgsLayout *layout)
Returns true if the specified layout contains visible items which have settings such as opacity which...
void renderRegion(QPainter *painter, const QRectF ®ion) const
Renders a region from the layout to a painter.
Layout graphical items for displaying a map.
double mapRotation(QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the layout item, in degrees clockwise.
QgsRectangle extent() const
Returns the current map extent.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
Item representing the paper in a layout.
QgsLayoutItemAbstractMetadata * itemMetadata(int type) const
Returns the metadata for the specified item type.
Base class for graphical items within a QgsLayout.
virtual QgsLayoutItem::ExportLayerDetail exportLayerDetails() const
Returns the details for the specified current export layer.
virtual bool nextExportPart()
Moves to the next export part for a multi-layered export item, during a multi-layered export.
virtual void startLayeredExport()
Starts a multi-layer export operation.
int page() const
Returns the page the item is currently on, with the first page returning 0.
int type() const override
Returns a unique graphics item type identifier.
virtual void stopLayeredExport()
Stops a multi-layer export operation.
virtual QString uuid() const
Returns the item identification string.
ExportLayerBehavior
Behavior of item when exporting to layered outputs.
@ ItemContainsSubLayers
Item contains multiple sublayers which must be individually exported.
@ MustPlaceInOwnLayer
Item must be placed in its own individual layer.
@ CanGroupWithItemsOfSameType
Item can only be placed on layers with other items of the same type, but multiple items of this type ...
@ CanGroupWithAnyOtherItem
Item can be placed on a layer with any other item (default behavior).
virtual ExportLayerBehavior exportLayerBehavior() const
Returns the behavior of this item during exporting to layered exports (e.g.
Provides a method of storing measurements for use in QGIS layouts using a variety of different measur...
Provides a method of storing points, consisting of an x and y coordinate, for use in QGIS layouts.
double x() const
Returns x coordinate of point.
double y() const
Returns y coordinate of point.
void setDpi(double dpi)
Sets the dpi for outputting the layout.
void setSimplifyMethod(const QgsVectorSimplifyMethod &method)
Sets the simplification setting to use when rendering vector layers.
void setTextRenderFormat(Qgis::TextRenderFormat format)
Sets the text render format, which dictates how text is rendered (e.g.
Qgis::LayoutRenderFlags flags() const
Returns the current combination of flags used for rendering the layout.
void setRasterizedRenderingPolicy(Qgis::RasterizedRenderingPolicy policy)
Sets the policy controlling when rasterization of content during renders is permitted.
double dpi() const
Returns the dpi for outputting the layout.
void setPredefinedScales(const QVector< qreal > &scales)
Sets the list of predefined scales to use with the layout.
void setMaskSettings(const QgsMaskRenderSettings &settings)
Sets the mask render settings, which control how masks are drawn and behave during map renders.
void setFlags(Qgis::LayoutRenderFlags flags)
Sets the combination of flags that will be used for rendering the layout.
Provides a method of storing sizes, consisting of a width and height, for use in QGIS layouts.
QSizeF toQSizeF() const
Converts the layout size to a QSizeF.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
Line string geometry type, with support for z-dimension and m-values.
Base class for all map layer types.
double top() const
Returns the top margin.
double right() const
Returns the right margin.
double bottom() const
Returns the bottom margin.
double left() const
Returns the left margin.
Contains settings regarding how masks are calculated and handled during a map render.
void setSimplificationTolerance(double tolerance)
Sets a simplification tolerance (in painter units) to use for on-the-fly simplification of mask paths...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
static void fixEngineFlags(QPaintEngine *engine)
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
QgsProjectMetadata metadata
A rectangle specified with double values.
A boolean settings entry.
An integer settings entry.
static QgsSettingsTreeNode * sTreeLayout
Contains settings for simplifying geometries fetched from a vector layer.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported,...
void setSimplifyHints(Qgis::VectorRenderingSimplificationFlags simplifyHints)
Sets the simplification hints of the vector layer managed.
void setSimplifyAlgorithm(Qgis::VectorSimplificationAlgorithm simplifyAlgorithm)
Sets the local simplification algorithm of the vector layer managed.
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
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QString nameForLayerWithItems(const QList< QGraphicsItem * > &items, unsigned int layerId)
#define QgsDebugError(str)
Contains details of a particular input component to be used during PDF composition.
QString mapLayerId
Associated map layer ID, or an empty string if this component layer is not associated with a map laye...
QString group
Optional group name, for arranging layers in top-level groups.
double opacity
Component opacity.
QString name
User-friendly name for the generated PDF layer.
QPainter::CompositionMode compositionMode
Component composition mode.
QString sourcePdfPath
File path to the (already created) PDF to use as the source for this component layer.
Contains details of a control point used during georeferencing Geospatial PDF outputs.
QMap< QString, QString > customLayerTreeGroups
Optional map of map layer ID to custom logical layer tree group in created PDF file.
QMap< QString, bool > initialLayerVisibility
Optional map of map layer ID to initial visibility state.
QList< QgsAbstractGeospatialPdfExporter::GeoReferencedSection > georeferencedSections
List of georeferenced sections.
QStringList layerOrder
Optional list of layer IDs, in the order desired to appear in the generated Geospatial PDF file.
QMap< QString, QString > layerIdToPdfLayerTreeNameMap
Optional map of map layer ID to custom layer tree name to show in the created PDF file.
QgsAbstractMetadataBase::KeywordMap keywords
Metadata keyword map.
QString creator
Metadata creator tag.
QSizeF pageSizeMm
Page size, in millimeters.
QString author
Metadata author tag.
QString subject
Metadata subject tag.
QString title
Metadata title tag.
QStringList layerTreeGroupOrder
Specifies the ordering of layer tree groups in the generated Geospatial PDF file.
QDateTime creationDateTime
Metadata creation datetime.
bool includeFeatures
true if feature vector information (such as attributes) should be exported.
QString producer
Metadata producer tag.
bool useIso32000ExtensionFormatGeoreferencing
true if ISO32000 extension format georeferencing should be used.
QSet< QString > mutuallyExclusiveGroups
Contains a list of group names which should be considered as mutually exclusive.
QgsCoordinateReferenceSystem crs
Coordinate reference system for georeferenced section.
QList< QgsAbstractGeospatialPdfExporter::ControlPoint > controlPoints
List of control points corresponding to this georeferenced section.
QgsPolygon pageBoundsPolygon
Bounds of the georeferenced section on the page, in millimeters, as a free-form polygon.
Contains settings relating to exporting layouts to raster images.
QgsMargins cropMargins
Crop to content margins, in pixels.
QList< int > pages
List of specific pages to export, or an empty list to export all pages.
bool generateWorldFile
Set to true to generate an external world file alongside exported images.
QSize imageSize
Manual size in pixels for output image.
bool exportMetadata
Indicates whether image export should include metadata generated from the layout's project's metadata...
int quality
Image quality, typically used for JPEG compression (whose quality ranges from 1 to 100) if quality is...
Qgis::LayoutRenderFlags flags
Layout context flags, which control how the export will be created.
bool cropToContents
Set to true if image should be cropped so only parts of the layout containing items are exported.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
QVector< qreal > predefinedMapScales
A list of predefined scales to use with the layout.
Contains details of a page being exported by the class.
QString baseName
Base part of filename (i.e. file name without extension or '.').
QString extension
File suffix/extension (without the leading '.').
QString directory
Target folder.
int page
Page number, where 0 = first page.
Contains settings relating to exporting layouts to PDF.
bool forceVectorOutput
Set to true to force vector object exports, even when the resultant appearance will differ from the l...
bool rasterizeWholeImage
Set to true to force whole layout to be rasterized while exporting.
QStringList exportThemes
Optional list of map themes to export as Geospatial PDF layer groups.
bool exportMetadata
Indicates whether PDF export should include metadata generated from the layout's project's metadata.
bool appendGeoreference
Indicates whether PDF export should append georeference data.
Qgis::LayoutRenderFlags flags
Layout context flags, which control how the export will be created.
bool writeGeoPdf
true if geospatial PDF files should be created, instead of normal PDF files.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
QVector< qreal > predefinedMapScales
A list of predefined scales to use with the layout.
bool exportLayersAsSeperateFiles
true if individual layers from the layout should be rendered to separate PDF files.
bool simplifyGeometries
Indicates whether vector geometries should be simplified to avoid redundant extraneous detail,...
Qgis::TextRenderFormat textRenderFormat
Text rendering format, which controls how text should be rendered in the export (e....
Contains settings relating to printing layouts.
QVector< qreal > predefinedMapScales
A list of predefined scales to use with the layout.
Qgis::LayoutRenderFlags flags
Layout context flags, which control how the export will be created.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
bool rasterizeWholeImage
Set to true to force whole layout to be rasterized while exporting.
Contains settings relating to exporting layouts to SVG.
bool forceVectorOutput
Set to true to force vector object exports, even when the resultant appearance will differ from the l...
Qgis::LayoutRenderFlags flags
Layout context flags, which control how the export will be created.
Qgis::TextRenderFormat textRenderFormat
Text rendering format, which controls how text should be rendered in the export (e....
bool exportAsLayers
Set to true to export as a layered SVG file.
bool simplifyGeometries
Indicates whether vector geometries should be simplified to avoid redundant extraneous detail,...
bool exportMetadata
Indicates whether SVG export should include RDF metadata generated from the layout's project's metada...
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
QVector< qreal > predefinedMapScales
A list of predefined scales to use with the layout.
bool exportLabelsToSeparateLayers
Set to true to export labels to separate layers (grouped by map layer) in layered SVG exports.
bool cropToContents
Set to true if image should be cropped so only parts of the layout containing items are exported.
QgsMargins cropMargins
Crop to content margins, in layout units.
Contains details of a particular export layer relating to a layout item.
QString name
User-friendly name for the export layer.
QString groupName
Associated group name, if this layer is associated with an export group.