26 #include <QImageWriter> 28 #include <QSvgGenerator> 34 class LayoutContextPreviewSettingRestorer
38 LayoutContextPreviewSettingRestorer(
QgsLayout *layout )
40 , mPreviousSetting( layout->renderContext().mIsPreviewRender )
42 mLayout->renderContext().mIsPreviewRender =
false;
45 ~LayoutContextPreviewSettingRestorer()
47 mLayout->renderContext().mIsPreviewRender = mPreviousSetting;
52 bool mPreviousSetting =
false;
55 class LayoutGuideHider
62 const QList< QgsLayoutGuide * > guides = mLayout->guides().guides();
65 mPrevVisibility.insert( guide, guide->item()->isVisible() );
66 guide->item()->setVisible(
false );
72 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
74 it.key()->item()->setVisible( it.value() );
80 QHash< QgsLayoutGuide *, bool > mPrevVisibility;
86 explicit LayoutItemHider(
const QList<QGraphicsItem *> &items )
88 for ( QGraphicsItem *item : items )
90 mPrevVisibility[item] = item->isVisible();
97 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
105 for (
auto it = mPrevVisibility.constBegin(); it != mPrevVisibility.constEnd(); ++it )
107 it.key()->setVisible( it.value() );
113 QHash<QGraphicsItem *, bool> mPrevVisibility;
134 if ( mLayout->pageCollection()->pageCount() <= page || page < 0 )
145 LayoutContextPreviewSettingRestorer restorer( mLayout );
148 QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
157 if ( mLayout->pageCollection()->pageCount() <= page || page < 0 )
168 LayoutContextPreviewSettingRestorer restorer( mLayout );
171 QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
176 class LayoutItemCacheSettingRestorer
180 LayoutItemCacheSettingRestorer(
QgsLayout *layout )
183 const QList< QGraphicsItem * > items = mLayout->items();
184 for ( QGraphicsItem *item : items )
186 mPrevCacheMode.insert( item, item->cacheMode() );
187 item->setCacheMode( QGraphicsItem::NoCache );
191 ~LayoutItemCacheSettingRestorer()
193 for (
auto it = mPrevCacheMode.constBegin(); it != mPrevCacheMode.constEnd(); ++it )
195 it.key()->setCacheMode( it.value() );
201 QHash< QGraphicsItem *, QGraphicsItem::CacheMode > mPrevCacheMode;
208 QPaintDevice *paintDevice = painter->device();
209 if ( !paintDevice || !mLayout )
214 LayoutItemCacheSettingRestorer cacheRestorer( mLayout );
215 ( void )cacheRestorer;
216 LayoutContextPreviewSettingRestorer restorer( mLayout );
218 LayoutGuideHider guideHider( mLayout );
223 mLayout->render( painter, QRectF( 0, 0, paintDevice->width(), paintDevice->height() ), region );
231 LayoutContextPreviewSettingRestorer restorer( mLayout );
234 double resolution = mLayout->renderContext().dpi();
236 if ( imageSize.isValid() )
240 resolution = ( imageSize.width() / region.width()
241 + imageSize.height() / region.height() ) / 2.0 * oneInchInLayoutUnits;
249 int width = imageSize.isValid() ? imageSize.width()
250 :
static_cast< int >( resolution * region.width() / oneInchInLayoutUnits );
251 int height = imageSize.isValid() ? imageSize.height()
252 :
static_cast< int >( resolution * region.height() / oneInchInLayoutUnits );
254 QImage image( QSize( width, height ), QImage::Format_ARGB32 );
255 if ( !image.isNull() )
257 image.setDotsPerMeterX( resolution / 25.4 * 1000 );
258 image.setDotsPerMeterY( resolution / 25.4 * 1000 );
259 image.fill( Qt::transparent );
260 QPainter imagePainter( &image );
262 if ( !imagePainter.isActive() )
270 class LayoutContextSettingsRestorer
274 LayoutContextSettingsRestorer(
QgsLayout *layout )
282 ~LayoutContextSettingsRestorer()
284 mLayout->renderContext().setDpi( mPreviousDpi );
285 mLayout->renderContext().setFlags( mPreviousFlags );
286 mLayout->renderContext().setCurrentExportLayer( mPreviousExportLayer );
291 double mPreviousDpi = 0;
292 QgsLayoutRenderContext::Flags mPreviousFlags = 0;
293 int mPreviousExportLayer = 0;
303 if ( settings.
dpi <= 0 )
304 settings.
dpi = mLayout->renderContext().dpi();
306 mErrorFileName.clear();
308 int worldFilePageNo = -1;
311 worldFilePageNo = referenceMap->page();
314 QFileInfo fi( filePath );
318 pageDetails.
baseName = fi.baseName();
319 pageDetails.
extension = fi.completeSuffix();
321 LayoutContextPreviewSettingRestorer restorer( mLayout );
323 LayoutContextSettingsRestorer dpiRestorer( mLayout );
325 mLayout->renderContext().setDpi( settings.
dpi );
326 mLayout->renderContext().setFlags( settings.
flags );
329 if ( settings.
pages.empty() )
331 for (
int page = 0; page < mLayout->pageCollection()->pageCount(); ++page )
336 for (
int page : qgis::as_const( settings.
pages ) )
338 if ( page >= 0 && page < mLayout->pageCollection()->pageCount() )
343 for (
int page : qgis::as_const( pages ) )
345 if ( !mLayout->pageCollection()->shouldExportPage( page ) )
352 QImage image = createImage( settings, page, bounds, skip );
357 pageDetails.
page = page;
360 if ( image.isNull() )
362 mErrorFileName = outputFilePath;
366 if ( !saveImage( image, outputFilePath, pageDetails.
extension ) )
368 mErrorFileName = outputFilePath;
372 if ( page == worldFilePageNo )
379 double a, b, c, d, e,
f;
380 if ( bounds.isValid() )
385 QFileInfo fi( outputFilePath );
387 QString outputSuffix = fi.suffix();
388 QString worldFileName = fi.absolutePath() +
'/' + fi.baseName() +
'.' 389 + outputSuffix.at( 0 ) + outputSuffix.at( fi.suffix().size() - 1 ) +
'w';
391 writeWorldFile( worldFileName, a, b, c, d, e, f );
406 int total = iterator->
count();
407 double step = total > 0 ? 100.0 / total : 100.0;
409 while ( iterator->
next() )
414 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
416 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
426 QString filePath = iterator->
filePath( baseFilePath, extension );
427 ExportResult result = exporter.exportToImage( filePath, settings );
431 error = QObject::tr(
"Cannot write to %1. This file may be open in another application." ).arg( filePath );
453 if ( settings.
dpi <= 0 )
454 settings.
dpi = mLayout->renderContext().dpi();
456 mErrorFileName.clear();
458 LayoutContextPreviewSettingRestorer restorer( mLayout );
460 LayoutContextSettingsRestorer contextRestorer( mLayout );
461 ( void )contextRestorer;
462 mLayout->renderContext().setDpi( settings.
dpi );
472 preparePrintAsPdf( mLayout, printer, filePath );
473 preparePrint( mLayout, printer,
false );
475 if ( !p.begin( &printer ) )
484 if ( mLayout->pageCollection()->pageCount() == 1 )
503 int total = iterator->
count();
504 double step = total > 0 ? 100.0 / total : 100.0;
507 while ( iterator->
next() )
512 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
514 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
526 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
528 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
529 ( void )contextRestorer;
541 preparePrintAsPdf( iterator->
layout(), printer, fileName );
542 preparePrint( iterator->
layout(), printer, false );
544 if ( !p.begin( &printer ) )
557 error = QObject::tr(
"Cannot write to %1. This file may be open in another application." ).arg( fileName );
581 int total = iterator->
count();
582 double step = total > 0 ? 100.0 / total : 100.0;
584 while ( iterator->
next() )
589 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
591 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
600 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"pdf" ) );
607 error = QObject::tr(
"Cannot write to %1. This file may be open in another application." ).arg( filePath );
629 if ( settings.
dpi <= 0 )
630 settings.
dpi = mLayout->renderContext().dpi();
632 mErrorFileName.clear();
634 LayoutContextPreviewSettingRestorer restorer( mLayout );
636 LayoutContextSettingsRestorer contextRestorer( mLayout );
637 ( void )contextRestorer;
638 mLayout->renderContext().setDpi( settings.
dpi );
645 preparePrint( mLayout, printer,
true );
647 if ( !p.begin( &printer ) )
670 int total = iterator->
count();
671 double step = total > 0 ? 100.0 / total : 100.0;
674 while ( iterator->
next() )
679 feedback->setProperty(
"progress", QObject::tr(
"Printing %1 of %2" ).arg( i + 1 ).arg( total ) );
681 feedback->setProperty(
"progress", QObject::tr(
"Printing section %1" ).arg( i + 1 ).arg( total ) );
693 LayoutContextPreviewSettingRestorer restorer( iterator->
layout() );
695 LayoutContextSettingsRestorer contextRestorer( iterator->
layout() );
696 ( void )contextRestorer;
706 preparePrint( iterator->
layout(), printer, true );
708 if ( !p.begin( &printer ) )
742 if ( settings.
dpi <= 0 )
743 settings.
dpi = mLayout->renderContext().dpi();
745 mErrorFileName.clear();
747 LayoutContextPreviewSettingRestorer restorer( mLayout );
749 LayoutContextSettingsRestorer contextRestorer( mLayout );
750 ( void )contextRestorer;
751 mLayout->renderContext().setDpi( settings.
dpi );
755 QFileInfo fi( filePath );
758 pageDetails.
baseName = fi.baseName();
759 pageDetails.
extension = fi.completeSuffix();
763 for (
int i = 0; i < mLayout->pageCollection()->pageCount(); ++i )
765 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
770 pageDetails.
page = i;
777 if ( mLayout->pageCollection()->pageCount() == 1 )
780 bounds = mLayout->layoutBounds(
true );
785 bounds = mLayout->pageItemBounds( i,
true );
794 bounds = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
798 int width = ( int )( bounds.width() * settings.
dpi / inchesToLayoutUnits );
800 int height = ( int )( bounds.height() * settings.
dpi / inchesToLayoutUnits );
801 if ( width == 0 || height == 0 )
809 const QRectF paperRect = QRectF( pageItem->pos().x(),
811 pageItem->rect().width(),
812 pageItem->rect().height() );
815 const QList<QGraphicsItem *> items = mLayout->items( paperRect,
816 Qt::IntersectsItemBoundingRect,
817 Qt::AscendingOrder );
819 LayoutItemHider itemHider( items );
822 int layoutItemLayerIdx = 0;
823 auto it = items.constBegin();
824 for (
unsigned svgLayerId = 1; it != items.constEnd(); ++svgLayerId )
828 QString layerName = QObject::tr(
"Layer %1" ).arg( svgLayerId );
832 mLayout->renderContext().setCurrentExportLayer( layoutItemLayerIdx );
833 ++layoutItemLayerIdx;
838 for ( ; it != items.constEnd(); ++it )
852 ExportResult result = renderToLayeredSvg( settings, width, height, i, bounds, fileName, svgLayerId, layerName, svg, svgDocRoot );
858 mLayout->renderContext().setCurrentExportLayer( -1 );
859 layoutItemLayerIdx = 0;
864 QFile out( fileName );
865 bool openOk = out.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate );
868 mErrorFileName = fileName;
872 out.write( svg.toByteArray() );
876 QSvgGenerator generator;
877 generator.setTitle( mLayout->project()->title() );
878 generator.setFileName( fileName );
879 generator.setSize( QSize( width, height ) );
880 generator.setViewBox( QRect( 0, 0, width, height ) );
881 generator.setResolution( settings.
dpi );
884 bool createOk = p.begin( &generator );
887 mErrorFileName = fileName;
910 int total = iterator->
count();
911 double step = total > 0 ? 100.0 / total : 100.0;
913 while ( iterator->
next() )
918 feedback->setProperty(
"progress", QObject::tr(
"Exporting %1 of %2" ).arg( i + 1 ).arg( total ) );
920 feedback->setProperty(
"progress", QObject::tr(
"Exporting section %1" ).arg( i + 1 ).arg( total ) );
930 QString filePath = iterator->
filePath( baseFilePath, QStringLiteral(
"svg" ) );
937 error = QObject::tr(
"Cannot write to %1. This file may be open in another application." ).arg( filePath );
954 void QgsLayoutExporter::preparePrintAsPdf(
QgsLayout *layout, QPrinter &printer,
const QString &filePath )
956 printer.setOutputFileName( filePath );
963 printer.setOutputFormat( QPrinter::PdfFormat );
965 updatePrinterPageSize( layout, printer, 0 );
974 void QgsLayoutExporter::preparePrint(
QgsLayout *layout, QPrinter &printer,
bool setFirstPageSize )
976 printer.setFullPage(
true );
977 printer.setColorMode( QPrinter::Color );
982 if ( setFirstPageSize )
984 updatePrinterPageSize( layout, printer, 0 );
990 preparePrint( mLayout, printer,
true );
992 if ( !p.begin( &printer ) )
998 printPrivate( printer, p );
1003 QgsLayoutExporter::ExportResult QgsLayoutExporter::printPrivate( QPrinter &printer, QPainter &painter,
bool startNewPage,
double dpi,
bool rasterize )
1006 int fromPage = ( printer.fromPage() < 1 ) ? 0 : printer.fromPage() - 1;
1007 int toPage = ( printer.toPage() < 1 ) ? mLayout->pageCollection()->pageCount() - 1 : printer.toPage() - 1;
1009 bool pageExported =
false;
1012 for (
int i = fromPage; i <= toPage; ++i )
1014 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1019 updatePrinterPageSize( mLayout, printer, i );
1020 if ( ( pageExported && i > fromPage ) || startNewPage )
1026 if ( !image.isNull() )
1028 QRectF targetArea( 0, 0, image.width(), image.height() );
1029 painter.drawImage( targetArea, image, targetArea );
1035 pageExported =
true;
1040 for (
int i = fromPage; i <= toPage; ++i )
1042 if ( !mLayout->pageCollection()->shouldExportPage( i ) )
1047 updatePrinterPageSize( mLayout, printer, i );
1049 if ( ( pageExported && i > fromPage ) || startNewPage )
1054 pageExported =
true;
1060 void QgsLayoutExporter::updatePrinterPageSize(
QgsLayout *layout, QPrinter &printer,
int page )
1064 printer.setOrientation( QPrinter::Portrait );
1067 printer.setPaperSize( pageSizeMM.
toQSizeF(), QPrinter::Millimeter );
1070 QgsLayoutExporter::ExportResult QgsLayoutExporter::renderToLayeredSvg(
const SvgExportSettings &settings,
double width,
double height,
int page, QRectF bounds,
const QString &filename,
int svgLayerId,
const QString &layerName, QDomDocument &svg, QDomNode &svgDocRoot )
const 1074 QSvgGenerator generator;
1076 generator.setTitle( l->name() );
1077 else if ( mLayout->project() )
1078 generator.setTitle( mLayout->project()->title() );
1080 generator.setOutputDevice( &svgBuffer );
1081 generator.setSize( QSize( width, height ) );
1082 generator.setViewBox( QRect( 0, 0, width, height ) );
1083 generator.setResolution( settings.
dpi );
1085 QPainter svgPainter( &generator );
1097 svgBuffer.open( QIODevice::ReadOnly );
1101 if ( ! doc.setContent( &svgBuffer,
false, &errorMsg, &errorLine ) )
1103 mErrorFileName = filename;
1106 if ( 1 == svgLayerId )
1108 svg = QDomDocument( doc.doctype() );
1109 svg.appendChild( svg.importNode( doc.firstChild(), false ) );
1110 svgDocRoot = svg.importNode( doc.elementsByTagName( QStringLiteral(
"svg" ) ).at( 0 ), false );
1111 svgDocRoot.toElement().setAttribute( QStringLiteral(
"xmlns:inkscape" ), QStringLiteral(
"http://www.inkscape.org/namespaces/inkscape" ) );
1112 svg.appendChild( svgDocRoot );
1114 QDomNode mainGroup = svg.importNode( doc.elementsByTagName( QStringLiteral(
"g" ) ).at( 0 ), true );
1115 mainGroup.toElement().setAttribute( QStringLiteral(
"id" ), layerName );
1116 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:label" ), layerName );
1117 mainGroup.toElement().setAttribute( QStringLiteral(
"inkscape:groupmode" ), QStringLiteral(
"layer" ) );
1118 QDomNode defs = svg.importNode( doc.elementsByTagName( QStringLiteral(
"defs" ) ).at( 0 ), true );
1119 svgDocRoot.appendChild( defs );
1120 svgDocRoot.appendChild( mainGroup );
1125 std::unique_ptr<double[]> QgsLayoutExporter::computeGeoTransform(
const QgsLayoutItemMap *map,
const QRectF ®ion,
double dpi )
const 1128 map = mLayout->referenceMap();
1134 dpi = mLayout->renderContext().dpi();
1137 QRectF exportRegion = region;
1138 if ( !exportRegion.isValid() )
1140 int pageNumber = map->
page();
1143 double pageY = page->pos().y();
1144 QSizeF pageSize = page->rect().size();
1145 exportRegion = QRectF( 0, pageY, pageSize.width(), pageSize.height() );
1149 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1152 double outputHeightMM = exportRegion.height();
1153 double outputWidthMM = exportRegion.width();
1157 double mapXCenter = mapExtent.
center().
x();
1158 double mapYCenter = mapExtent.
center().
y();
1160 double sinAlpha = std::sin( alpha );
1161 double cosAlpha = std::cos( alpha );
1164 QPointF mapItemPos = map->pos();
1166 mapItemPos.rx() -= exportRegion.left();
1167 mapItemPos.ry() -= exportRegion.top();
1170 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1171 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1172 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1173 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1174 QgsRectangle paperExtent( xmin, ymax - outputHeightMM * yRatio, xmin + outputWidthMM * xRatio, ymax );
1177 double X0 = paperExtent.
xMinimum();
1178 double Y0 = paperExtent.
yMaximum();
1183 double X1 = X0 - mapXCenter;
1184 double Y1 = Y0 - mapYCenter;
1185 double X2 = X1 * cosAlpha + Y1 * sinAlpha;
1186 double Y2 = -X1 * sinAlpha + Y1 * cosAlpha;
1187 X0 = X2 + mapXCenter;
1188 Y0 = Y2 + mapYCenter;
1192 int pageWidthPixels =
static_cast< int >( dpi * outputWidthMM / 25.4 );
1193 int pageHeightPixels =
static_cast< int >( dpi * outputHeightMM / 25.4 );
1194 double pixelWidthScale = paperExtent.
width() / pageWidthPixels;
1195 double pixelHeightScale = paperExtent.
height() / pageHeightPixels;
1198 std::unique_ptr<double[]> t(
new double[6] );
1200 t[1] = cosAlpha * pixelWidthScale;
1201 t[2] = -sinAlpha * pixelWidthScale;
1203 t[4] = -sinAlpha * pixelHeightScale;
1204 t[5] = -cosAlpha * pixelHeightScale;
1209 void QgsLayoutExporter::writeWorldFile(
const QString &worldFileName,
double a,
double b,
double c,
double d,
double e,
double f )
const 1211 QFile worldFile( worldFileName );
1212 if ( !worldFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
1216 QTextStream fout( &worldFile );
1220 fout << QString::number( a,
'f', 12 ) <<
"\r\n";
1221 fout << QString::number( d,
'f', 12 ) <<
"\r\n";
1222 fout << QString::number( b,
'f', 12 ) <<
"\r\n";
1223 fout << QString::number( e,
'f', 12 ) <<
"\r\n";
1224 fout << QString::number( c,
'f', 12 ) <<
"\r\n";
1225 fout << QString::number( f,
'f', 12 ) <<
"\r\n";
1234 map = mLayout->referenceMap();
1240 dpi = mLayout->renderContext().dpi();
1242 std::unique_ptr<double[]> t = computeGeoTransform( map, exportRegion, dpi );
1248 CPLSetConfigOption(
"GDAL_PDF_DPI", QString::number( dpi ).toLocal8Bit().constData() );
1252 GDALSetGeoTransform( outputDS.get(), t.get() );
1255 GDALSetMetadataItem( outputDS,
"AUTHOR",
"me",
nullptr );
1257 GDALSetProjection( outputDS.get(), map->
crs().
toWkt().toLocal8Bit().constData() );
1259 CPLSetConfigOption(
"GDAL_PDF_DPI",
nullptr );
1275 int pageNumber = map->
page();
1277 double pageY = page->pos().y();
1278 QSizeF pageSize = page->rect().size();
1279 QRectF pageRect( 0, pageY, pageSize.width(), pageSize.height() );
1295 double destinationHeight = exportRegion.height();
1296 double destinationWidth = exportRegion.width();
1298 QRectF mapItemSceneRect = map->mapRectToScene( map->rect() );
1303 double xRatio = mapExtent.
width() / mapItemSceneRect.width();
1304 double yRatio = mapExtent.
height() / mapItemSceneRect.height();
1306 double xCenter = mapExtent.
center().
x();
1307 double yCenter = mapExtent.
center().
y();
1310 QPointF mapItemPos = map->pos();
1312 mapItemPos.rx() -= exportRegion.left();
1313 mapItemPos.ry() -= exportRegion.top();
1315 double xmin = mapExtent.
xMinimum() - mapItemPos.x() * xRatio;
1316 double ymax = mapExtent.
yMaximum() + mapItemPos.y() * yRatio;
1317 QgsRectangle paperExtent( xmin, ymax - destinationHeight * yRatio, xmin + destinationWidth * xRatio, ymax );
1319 double X0 = paperExtent.
xMinimum();
1320 double Y0 = paperExtent.
yMinimum();
1323 dpi = mLayout->renderContext().dpi();
1325 int widthPx =
static_cast< int >( dpi * destinationWidth / 25.4 );
1326 int heightPx =
static_cast< int >( dpi * destinationHeight / 25.4 );
1328 double Ww = paperExtent.
width() / widthPx;
1329 double Hh = paperExtent.
height() / heightPx;
1338 s[5] = Y0 + paperExtent.
height();
1342 r[0] = std::cos( alpha );
1343 r[1] = -std::sin( alpha );
1344 r[2] = xCenter * ( 1 - std::cos( alpha ) ) + yCenter * std::sin( alpha );
1345 r[3] = std::sin( alpha );
1346 r[4] = std::cos( alpha );
1347 r[5] = - xCenter * std::sin( alpha ) + yCenter * ( 1 - std::cos( alpha ) );
1350 a = r[0] * s[0] + r[1] * s[3];
1351 b = r[0] * s[1] + r[1] * s[4];
1352 c = r[0] * s[2] + r[1] * s[5] + r[2];
1353 d = r[3] * s[0] + r[4] * s[3];
1354 e = r[3] * s[1] + r[4] * s[4];
1355 f = r[3] * s[2] + r[4] * s[5] + r[5];
1365 if ( mLayout->pageCollection()->pageCount() == 1 )
1368 bounds = mLayout->layoutBounds(
true );
1373 bounds = mLayout->pageItemBounds( page,
true );
1375 if ( bounds.width() <= 0 || bounds.height() <= 0 )
1383 bounds = bounds.adjusted( -settings.
cropMargins.
left() * pixelToLayoutUnits,
1397 if ( details.
page == 0 )
1407 bool QgsLayoutExporter::saveImage(
const QImage &image,
const QString &imageFilename,
const QString &imageFormat )
1409 QImageWriter w( imageFilename, imageFormat.toLocal8Bit().constData() );
1410 if ( imageFormat.compare( QLatin1String(
"tiff" ), Qt::CaseInsensitive ) == 0 || imageFormat.compare( QLatin1String(
"tif" ), Qt::CaseInsensitive ) == 0 )
1412 w.setCompression( 1 );
1414 return w.write( image );
bool cropToContents
Set to true if image should be cropped so only parts of the layout containing items are exported...
double right() const
Returns the right margin.
void setDpi(double dpi)
Sets the dpi for outputting the layout.
A rectangle specified with double values.
void renderRegion(QPainter *painter, const QRectF ®ion) const
Renders a region from the layout to a painter.
Contains settings relating to printing layouts.
Base class for graphical items within a QgsLayout.
QgsMargins cropMargins
Crop to content margins, in layout units.
Unable to allocate memory required to export.
virtual bool endRender()=0
Ends the render, performing any required cleanup tasks.
Contains the configuration for a single snap guide used by a layout.
Could not write to destination file, likely due to a lock held by another application.
ExportResult exportToImage(const QString &filePath, const QgsLayoutExporter::ImageExportSettings &settings)
Exports the layout to the a filePath, using the specified export settings.
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
void setProgress(double progress)
Sets the current progress for the feedback object.
virtual bool next()=0
Iterates to next feature, returning false if no more features exist to iterate over.
QgsMargins cropMargins
Crop to content margins, in pixels.
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.
QgsLayoutMeasurement convert(const QgsLayoutMeasurement &measurement, const QgsUnitTypes::LayoutUnit targetUnits) const
Converts a measurement from one unit to another.
QImage renderRegionToImage(const QRectF ®ion, QSize imageSize=QSize(), double dpi=0) const
Renders a region of the layout to an image.
ExportResult print(QPrinter &printer, const QgsLayoutExporter::PrintExportSettings &settings)
Prints the layout to a printer, using the specified export settings.
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
int currentExportLayer() const
Returns the current item layer to draw while exporting.
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.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
QList< int > pages
List of specific pages to export, or an empty list to export all pages.
QString directory
Target folder.
QgsLayoutExporter(QgsLayout *layout)
Constructor for QgsLayoutExporter, for the specified layout.
Base class for feedback objects to be used for cancelation of something running in a worker thread...
QSizeF toQSizeF() const
Converts the layout size to a QSizeF.
Contains details of a page being exported by the class.
QSize imageSize
Manual size in pixels for output image.
QgsRectangle extent() const
Returns the current map extent.
Layout graphical items for displaying a map.
QgsLayoutItemPage * page(int pageNumber)
Returns a specific page (by pageNumber) from the collection.
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
virtual QString generateFileName(const PageExportDetails &details) const
Generates the file name for a page during export.
bool exportAsLayers
Set to true to export as a layered SVG file.
An abstract base class for QgsLayout based classes which can be exported by QgsLayoutExporter.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout's page collection, which stores and manages page items in the layout...
void computeWorldFileParameters(double &a, double &b, double &c, double &d, double &e, double &f, double dpi=-1) const
Compute world file parameters.
double bottom() const
Returns the bottom margin.
QgsLayoutRenderContext::Flags flags() const
Returns the current combination of flags used for rendering the layout.
double dpi() const
Returns the dpi for outputting the layout.
double width() const
Returns the width of the rectangle.
bool rasterizeWholeImage
Set to true to force whole layout to be rasterized while exporting.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
bool forceVectorOutput
Set to true to force vector object exports, even when the resultant appearance will differ from the l...
virtual int numberExportLayers() const
Returns the number of layers that this item requires for exporting during layered exports (e...
virtual int count()=0
Returns the number of features to iterate over.
QString extension
File suffix/extension (without the leading '.')
virtual QgsLayout * layout()=0
Returns the layout associated with the iterator.
double top() const
Returns the top margin.
QString baseName
Base part of filename (i.e. file name without extension or '.')
Could not create layered SVG file.
int page() const
Returns the page the item is currently on, with the first page returning 0.
ExportResult exportToSvg(const QString &filePath, const QgsLayoutExporter::SvgExportSettings &settings)
Exports the layout as an SVG to the a filePath, using the specified export settings.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
std::unique_ptr< void, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
Use antialiasing when drawing items.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Handles rendering and exports of layouts to various formats.
Contains settings relating to exporting layouts to PDF.
bool generateWorldFile
Set to true to generate an external world file alongside exported images.
double mapRotation(QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the layout item, in degrees clockwise.
Force output in vector format where possible, even if items require rasterization to keep their corre...
const QgsLayoutMeasurementConverter & measurementConverter() const
Returns the layout measurement converter to be used in the layout.
Contains settings relating to exporting layouts to raster images.
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.
QImage renderPageToImage(int page, QSize imageSize=QSize(), double dpi=0) const
Renders a full page to an image.
bool isCanceled() const
Tells whether the operation has been canceled already.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
Enable advanced effects such as blend modes.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
ExportResult exportToPdf(const QString &filePath, const QgsLayoutExporter::PdfExportSettings &settings)
Exports the layout as a PDF to the a filePath, using the specified export settings.
static void fixEngineFlags(QPaintEngine *engine)
QString toWkt() const
Returns a WKT representation of this CRS.
int page
Page number, where 0 = first page.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
void setFlag(const QgsLayoutRenderContext::Flag flag, const bool on=true)
Enables or disables a particular rendering flag for the layout.
Could not start printing to destination device.
QgsPointXY center() const
Returns the center point of the rectangle.
bool cropToContents
Set to true if image should be cropped so only parts of the layout containing items are exported...
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Interface for master layout type objects, such as print layouts and reports.
double dpi
Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
Contains settings relating to exporting layouts to SVG.
virtual bool beginRender()=0
Called when rendering begins, before iteration commences.
double left() const
Returns the left margin.
QgsLayout * layout() const
Returns the layout linked to this exporter.
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...
double height() const
Returns the height of the rectangle.
Item representing the paper in a layout.
QgsLayoutRenderContext::Flags flags
Layout context flags, which control how the export will be created.
ExportResult
Result codes for exporting layouts.
void renderPage(QPainter *painter, int page) const
Renders a full page to a destination painter.
Error iterating over layout.