Skip to content

Commit b992e87

Browse files
committedDec 17, 2017
[layouts][FEATURE] Don't force the whole layout to be rasterized
when exporting to PDF If an individual layout item needs rasterisation in order to be exported correctly, it can now be individually rasterised without forcing every other item to also be rasterised. This allows exports to PDF keeping as much as possible as vectors, e.g. a map with layer opacity won't force labels, scalebars, etc to be rasterised too. To accompany this, a new "Always export as vectors" checkbox was added to layout properties. If checked, this will force the export to keep items as vectors, even when it causes the output to look different to layouts. Fixes #7885
1 parent 91179f1 commit b992e87

17 files changed

+236
-40
lines changed
 

‎python/core/layout/qgslayoutcontext.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class QgsLayoutContext : QObject
2727
FlagOutlineOnly,
2828
FlagAntialiasing,
2929
FlagUseAdvancedEffects,
30+
FlagForceVectorOutput,
3031
};
3132
typedef QFlags<QgsLayoutContext::Flag> Flags;
3233

‎python/core/layout/qgslayoutexporter.sip

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,18 @@ Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
212212

213213
bool rasterizeWholeImage;
214214
%Docstring
215-
Set to true to force whole layout to be rasterized while exporting
215+
Set to true to force whole layout to be rasterized while exporting.
216+
217+
This option is mutually exclusive with forceVectorOutput.
218+
%End
219+
220+
bool forceVectorOutput;
221+
%Docstring
222+
Set to true to force vector object exports, even when the resultant appearance will differ
223+
from the layout. If false, some items may be rasterized in order to maintain their
224+
correct appearance in the output.
225+
226+
This option is mutually exclusive with rasterizeWholeImage.
216227
%End
217228

218229
QgsLayoutContext::Flags flags;

‎python/core/layout/qgslayoutitem.sip

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,16 @@ Sets whether the item should be excluded from composer exports and prints.
827827

828828
Subclasses should ensure that implemented overrides of this method
829829
also check the base class result.
830+
831+
.. seealso:: :py:func:`requiresRasterization()`
832+
:rtype: bool
833+
%End
834+
835+
virtual bool requiresRasterization() const;
836+
%Docstring
837+
Returns true if the item is drawn in such a way that forces the whole layout
838+
to be rasterised when exporting to vector formats.
839+
.. seealso:: :py:func:`containsAdvancedEffects()`
830840
:rtype: bool
831841
%End
832842

‎python/core/layout/qgslayoutitempicture.sip

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ Forces a recalculation of the picture's frame size
296296

297297
virtual void refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties );
298298

299+
virtual bool containsAdvancedEffects() const;
300+
299301

300302
signals:
301303
void pictureRotationChanged( double newRotation );

‎src/app/layout/qgslayoutdesignerdialog.cpp

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,9 +1552,14 @@ void QgsLayoutDesignerDialog::exportToPdf()
15521552
showWmsPrintingWarning();
15531553
}
15541554

1555-
if ( containsAdvancedEffects() )
1555+
if ( requiresRasterization() )
15561556
{
1557-
showAdvancedEffectsWarning();
1557+
showRasterizationWarning();
1558+
}
1559+
1560+
if ( containsAdvancedEffects() && ( mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool() ) )
1561+
{
1562+
showForceVectorWarning();
15581563
}
15591564

15601565
QgsSettings settings;
@@ -1602,7 +1607,8 @@ void QgsLayoutDesignerDialog::exportToPdf()
16021607
QApplication::setOverrideCursor( Qt::BusyCursor );
16031608

16041609
QgsLayoutExporter::PdfExportSettings pdfSettings;
1605-
pdfSettings.rasteriseWholeImage = mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool();
1610+
pdfSettings.rasterizeWholeImage = mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool();
1611+
pdfSettings.forceVectorOutput = mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool();
16061612

16071613
QgsLayoutExporter exporter( mLayout );
16081614
switch ( exporter.exportToPdf( outputFileName, pdfSettings ) )
@@ -1783,6 +1789,19 @@ void QgsLayoutDesignerDialog::showWmsPrintingWarning()
17831789
}
17841790
}
17851791

1792+
bool QgsLayoutDesignerDialog::requiresRasterization() const
1793+
{
1794+
QList< QgsLayoutItem *> items;
1795+
mLayout->layoutItems( items );
1796+
1797+
for ( QgsLayoutItem *currentItem : qgis::as_const( items ) )
1798+
{
1799+
if ( currentItem->requiresRasterization() )
1800+
return true;
1801+
}
1802+
return false;
1803+
}
1804+
17861805
bool QgsLayoutDesignerDialog::containsAdvancedEffects() const
17871806
{
17881807
QList< QgsLayoutItem *> items;
@@ -1796,10 +1815,11 @@ bool QgsLayoutDesignerDialog::containsAdvancedEffects() const
17961815
return false;
17971816
}
17981817

1799-
void QgsLayoutDesignerDialog::showAdvancedEffectsWarning()
1818+
void QgsLayoutDesignerDialog::showRasterizationWarning()
18001819
{
1801-
bool rasterize = mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool();
1802-
if ( rasterise )
1820+
1821+
if ( mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool() ||
1822+
mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool() )
18031823
return;
18041824

18051825
QgsMessageViewer *m = new QgsMessageViewer( this, QgsGuiUtils::ModalDialogFlags, false );
@@ -1817,6 +1837,27 @@ void QgsLayoutDesignerDialog::showAdvancedEffectsWarning()
18171837
delete m;
18181838
}
18191839

1840+
void QgsLayoutDesignerDialog::showForceVectorWarning()
1841+
{
1842+
QgsSettings settings;
1843+
if ( settings.value( QStringLiteral( "LayoutDesigner/hideForceVectorWarning" ), false, QgsSettings::App ).toBool() )
1844+
return;
1845+
1846+
QgsMessageViewer *m = new QgsMessageViewer( this, QgsGuiUtils::ModalDialogFlags, false );
1847+
m->setWindowTitle( tr( "Force Vector" ) );
1848+
m->setMessage( tr( "This layout has the \"Always export as vectors\" option enabled, but the layout contains effects such as blend modes or vector layer transparency, which cannot be printed as vectors. The generated file will differ from the layout contents." ), QgsMessageOutput::MessageText );
1849+
m->setCheckBoxText( tr( "Never show this message again" ) );
1850+
m->setCheckBoxState( Qt::Unchecked );
1851+
m->setCheckBoxVisible( true );
1852+
m->showMessage( true );
1853+
1854+
if ( m->checkBoxState() == Qt::Checked )
1855+
{
1856+
settings.setValue( QStringLiteral( "LayoutDesigner/hideForceVectorWarning" ), true, QgsSettings::App );
1857+
}
1858+
delete m;
1859+
}
1860+
18201861
void QgsLayoutDesignerDialog::selectItems( const QList<QgsLayoutItem *> items )
18211862
{
18221863
for ( QGraphicsItem *item : items )

‎src/app/layout/qgslayoutdesignerdialog.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,10 +371,13 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
371371
void showWmsPrintingWarning();
372372

373373
//! True if the layout contains advanced effects, such as blend modes
374+
bool requiresRasterization() const;
375+
374376
bool containsAdvancedEffects() const;
375377

376378
//! Displays a warning because of incompatibility between blend modes and QPrinter
377-
void showAdvancedEffectsWarning();
379+
void showRasterizationWarning();
380+
void showForceVectorWarning();
378381
};
379382

380383
#endif // QGSLAYOUTDESIGNERDIALOG_H

‎src/app/layout/qgslayoutpropertieswidget.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ QgsLayoutPropertiesWidget::QgsLayoutPropertiesWidget( QWidget *parent, QgsLayout
5959
connect( mGenerateWorldFileCheckBox, &QCheckBox::toggled, this, &QgsLayoutPropertiesWidget::worldFileToggled );
6060

6161
connect( mRasterizeCheckBox, &QCheckBox::toggled, this, &QgsLayoutPropertiesWidget::rasteriseToggled );
62+
connect( mForceVectorCheckBox, &QCheckBox::toggled, this, &QgsLayoutPropertiesWidget::forceVectorToggled );
6263

6364
mTopMarginSpinBox->setValue( topMargin );
6465
mMarginUnitsComboBox->linkToWidget( mTopMarginSpinBox );
@@ -93,6 +94,19 @@ void QgsLayoutPropertiesWidget::updateGui()
9394

9495
bool rasterise = mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool();
9596
whileBlocking( mRasterizeCheckBox )->setChecked( rasterise );
97+
98+
bool forceVectors = mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool();
99+
whileBlocking( mForceVectorCheckBox )->setChecked( forceVectors );
100+
101+
if ( rasterise )
102+
{
103+
mForceVectorCheckBox->setChecked( false );
104+
mForceVectorCheckBox->setEnabled( false );
105+
}
106+
else
107+
{
108+
mForceVectorCheckBox->setEnabled( true );
109+
}
96110
}
97111

98112
void QgsLayoutPropertiesWidget::updateSnappingElements()
@@ -197,6 +211,21 @@ void QgsLayoutPropertiesWidget::worldFileToggled()
197211
void QgsLayoutPropertiesWidget::rasteriseToggled()
198212
{
199213
mLayout->setCustomProperty( QStringLiteral( "rasterise" ), mRasterizeCheckBox->isChecked() );
214+
215+
if ( mRasterizeCheckBox->isChecked() )
216+
{
217+
mForceVectorCheckBox->setChecked( false );
218+
mForceVectorCheckBox->setEnabled( false );
219+
}
220+
else
221+
{
222+
mForceVectorCheckBox->setEnabled( true );
223+
}
224+
}
225+
226+
void QgsLayoutPropertiesWidget::forceVectorToggled()
227+
{
228+
mLayout->setCustomProperty( QStringLiteral( "forceVector" ), mForceVectorCheckBox->isChecked() );
200229
}
201230

202231
void QgsLayoutPropertiesWidget::blockSignals( bool block )

‎src/app/layout/qgslayoutpropertieswidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class QgsLayoutPropertiesWidget: public QgsPanelWidget, private Ui::QgsLayoutWid
4747
void dpiChanged( int value );
4848
void worldFileToggled();
4949
void rasteriseToggled();
50+
void forceVectorToggled();
5051

5152
private:
5253

‎src/core/layout/qgslayoutcontext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class CORE_EXPORT QgsLayoutContext : public QObject
4545
FlagOutlineOnly = 1 << 2, //!< Render items as outlines only.
4646
FlagAntialiasing = 1 << 3, //!< Use antialiasing when drawing items.
4747
FlagUseAdvancedEffects = 1 << 4, //!< Enable advanced effects such as blend modes.
48+
FlagForceVectorOutput = 1 << 5, //!< Force output in vector format where possible, even if items require rasterization to keep their correct appearance.
4849
};
4950
Q_DECLARE_FLAGS( Flags, Flag )
5051

‎src/core/layout/qgslayoutexporter.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,9 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToPdf( const QString &f
310310
// If we are not printing as raster, temporarily disable advanced effects
311311
// as QPrinter does not support composition modes and can result
312312
// in items missing from the output
313-
mLayout->context().setFlag( QgsLayoutContext::FlagUseAdvancedEffects, settings.rasteriseWholeImage );
313+
mLayout->context().setFlag( QgsLayoutContext::FlagUseAdvancedEffects, !settings.forceVectorOutput );
314+
315+
mLayout->context().setFlag( QgsLayoutContext::FlagForceVectorOutput, settings.forceVectorOutput );
314316

315317
QPrinter printer;
316318
preparePrintAsPdf( printer, filePath );
@@ -322,7 +324,7 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToPdf( const QString &f
322324
return PrintError;
323325
}
324326

325-
ExportResult result = printPrivate( printer, p, false, settings.dpi, settings.rasteriseWholeImage );
327+
ExportResult result = printPrivate( printer, p, false, settings.dpi, settings.rasterizeWholeImage );
326328
p.end();
327329

328330
#if 0//TODO

‎src/core/layout/qgslayoutexporter.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,22 @@ class CORE_EXPORT QgsLayoutExporter
216216
//! Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
217217
double dpi = -1;
218218

219-
//! Set to true to force whole layout to be rasterized while exporting
219+
/**
220+
* Set to true to force whole layout to be rasterized while exporting.
221+
*
222+
* This option is mutually exclusive with forceVectorOutput.
223+
*/
220224
bool rasterizeWholeImage = false;
221225

226+
/**
227+
* Set to true to force vector object exports, even when the resultant appearance will differ
228+
* from the layout. If false, some items may be rasterized in order to maintain their
229+
* correct appearance in the output.
230+
*
231+
* This option is mutually exclusive with rasterizeWholeImage.
232+
*/
233+
bool forceVectorOutput = false;
234+
222235
/**
223236
* Layout context flags, which control how the export will be created.
224237
*/

‎src/core/layout/qgslayoutitem.cpp

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -242,18 +242,32 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it
242242
return;
243243
}
244244

245-
double destinationDpi = itemStyle->matrix.m11() * 25.4;
245+
bool previewRender = !mLayout || mLayout->context().isPreviewRender();
246+
double destinationDpi = previewRender ? itemStyle->matrix.m11() * 25.4 : mLayout->context().dpi();
246247
bool useImageCache = false;
248+
bool forceRasterOutput = containsAdvancedEffects() && ( !mLayout || !( mLayout->context().flags() & QgsLayoutContext::FlagForceVectorOutput ) );
247249

248-
if ( useImageCache )
250+
if ( useImageCache || forceRasterOutput )
249251
{
250-
double widthInPixels = boundingRect().width() * itemStyle->matrix.m11();
251-
double heightInPixels = boundingRect().height() * itemStyle->matrix.m11();
252+
double widthInPixels = 0;
253+
double heightInPixels = 0;
254+
255+
if ( previewRender )
256+
{
257+
widthInPixels = boundingRect().width() * itemStyle->matrix.m11();
258+
heightInPixels = boundingRect().height() * itemStyle->matrix.m11();
259+
}
260+
else
261+
{
262+
double layoutUnitsToPixels = mLayout ? mLayout->convertFromLayoutUnits( 1, QgsUnitTypes::LayoutPixels ).length() : destinationDpi / 25.4;
263+
widthInPixels = boundingRect().width() * layoutUnitsToPixels;
264+
heightInPixels = boundingRect().height() * layoutUnitsToPixels;
265+
}
252266

253267
// limit size of image for better performance
254-
double scale = 1.0;
255-
if ( widthInPixels > CACHE_SIZE_LIMIT || heightInPixels > CACHE_SIZE_LIMIT )
268+
if ( previewRender && ( widthInPixels > CACHE_SIZE_LIMIT || heightInPixels > CACHE_SIZE_LIMIT ) )
256269
{
270+
double scale = 1.0;
257271
if ( widthInPixels > heightInPixels )
258272
{
259273
scale = widthInPixels / CACHE_SIZE_LIMIT;
@@ -269,7 +283,7 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it
269283
destinationDpi = destinationDpi / scale;
270284
}
271285

272-
if ( !mItemCachedImage.isNull() && qgsDoubleNear( mItemCacheDpi, destinationDpi ) )
286+
if ( previewRender && !mItemCachedImage.isNull() && qgsDoubleNear( mItemCacheDpi, destinationDpi ) )
273287
{
274288
// can reuse last cached image
275289
QgsRenderContext context = QgsLayoutUtils::createRenderContextForMap( nullptr, painter, destinationDpi );
@@ -284,13 +298,11 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it
284298
}
285299
else
286300
{
287-
mItemCacheDpi = destinationDpi;
288-
289-
mItemCachedImage = QImage( widthInPixels, heightInPixels, QImage::Format_ARGB32 );
290-
mItemCachedImage.fill( Qt::transparent );
291-
mItemCachedImage.setDotsPerMeterX( 1000 * destinationDpi * 25.4 );
292-
mItemCachedImage.setDotsPerMeterY( 1000 * destinationDpi * 25.4 );
293-
QPainter p( &mItemCachedImage );
301+
QImage image = QImage( widthInPixels, heightInPixels, QImage::Format_ARGB32 );
302+
image.fill( Qt::transparent );
303+
image.setDotsPerMeterX( 1000 * destinationDpi * 25.4 );
304+
image.setDotsPerMeterY( 1000 * destinationDpi * 25.4 );
305+
QPainter p( &image );
294306

295307
preparePainter( &p );
296308
QgsRenderContext context = QgsLayoutUtils::createRenderContextForLayout( nullptr, &p, destinationDpi );
@@ -306,8 +318,14 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it
306318
// scale painter from mm to dots
307319
painter->scale( 1.0 / context.scaleFactor(), 1.0 / context.scaleFactor() );
308320
painter->drawImage( boundingRect().x() * context.scaleFactor(),
309-
boundingRect().y() * context.scaleFactor(), mItemCachedImage );
321+
boundingRect().y() * context.scaleFactor(), image );
310322
painter->restore();
323+
324+
if ( previewRender )
325+
{
326+
mItemCacheDpi = destinationDpi;
327+
mItemCachedImage = image;
328+
}
311329
}
312330
}
313331
else
@@ -842,7 +860,12 @@ void QgsLayoutItem::setExcludeFromExports( bool exclude )
842860

843861
bool QgsLayoutItem::containsAdvancedEffects() const
844862
{
845-
return blendMode() != QPainter::CompositionMode_SourceOver;
863+
return false;
864+
}
865+
866+
bool QgsLayoutItem::requiresRasterization() const
867+
{
868+
return itemOpacity() < 1.0 || blendMode() != QPainter::CompositionMode_SourceOver;
846869
}
847870

848871
double QgsLayoutItem::estimatedFrameBleed() const

‎src/core/layout/qgslayoutitem.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,9 +748,18 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
748748
*
749749
* Subclasses should ensure that implemented overrides of this method
750750
* also check the base class result.
751+
*
752+
* \see requiresRasterization()
751753
*/
752754
virtual bool containsAdvancedEffects() const;
753755

756+
/**
757+
* Returns true if the item is drawn in such a way that forces the whole layout
758+
* to be rasterised when exporting to vector formats.
759+
* \see containsAdvancedEffects()
760+
*/
761+
virtual bool requiresRasterization() const;
762+
754763
/**
755764
* Returns the estimated amount the item's frame bleeds outside the item's
756765
* actual rectangle. For instance, if the item has a 2mm frame stroke, then

‎src/core/layout/qgslayoutitemmap.cpp

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -798,19 +798,46 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem
798798
}
799799

800800
QgsRectangle cExtent = extent();
801-
802801
QSizeF size( cExtent.width() * mapUnitsToLayoutUnits(), cExtent.height() * mapUnitsToLayoutUnits() );
803802

804-
painter->save();
805-
painter->translate( mXOffset, mYOffset );
803+
if ( containsAdvancedEffects() && ( !mLayout || !( mLayout->context().flags() & QgsLayoutContext::FlagForceVectorOutput ) ) )
804+
{
805+
// rasterise
806+
double destinationDpi = mLayout ? mLayout->context().dpi() : style->matrix.m11() * 25.4;
807+
808+
double layoutUnitsToPixels = mLayout ? mLayout->convertFromLayoutUnits( 1, QgsUnitTypes::LayoutPixels ).length() : destinationDpi / 25.4;
809+
double widthInPixels = boundingRect().width() * layoutUnitsToPixels;
810+
double heightInPixels = boundingRect().height() * layoutUnitsToPixels;
811+
QImage image = QImage( widthInPixels, heightInPixels, QImage::Format_ARGB32 );
812+
813+
image.fill( Qt::transparent );
814+
image.setDotsPerMeterX( 1000 * destinationDpi / 25.4 );
815+
image.setDotsPerMeterY( 1000 * destinationDpi / 25.4 );
816+
QPainter p( &image );
817+
double dotsPerMM = image.logicalDpiX() / 25.4;
818+
drawMap( &p, cExtent, image.size(), destinationDpi );
819+
p.end();
820+
821+
dotsPerMM = paintDevice->logicalDpiX() / 25.4;
822+
painter->save();
823+
painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
824+
painter->drawImage( 0, 0, image );
825+
painter->restore();
826+
827+
}
828+
else
829+
{
830+
painter->save();
831+
painter->translate( mXOffset, mYOffset );
832+
833+
double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
834+
size *= dotsPerMM; // output size will be in dots (pixels)
835+
painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
836+
drawMap( painter, cExtent, size, paintDevice->logicalDpiX() );
806837

807-
double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
808-
size *= dotsPerMM; // output size will be in dots (pixels)
809-
painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
810-
drawMap( painter, cExtent, size, paintDevice->logicalDpiX() );
838+
painter->restore();
839+
}
811840

812-
//restore rotation
813-
painter->restore();
814841
mDrawing = false;
815842
}
816843

‎src/core/layout/qgslayoutitempicture.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,14 @@ void QgsLayoutItemPicture::refreshDataDefinedProperty( const QgsLayoutObject::Da
666666
QgsLayoutItem::refreshDataDefinedProperty( property );
667667
}
668668

669+
bool QgsLayoutItemPicture::containsAdvancedEffects() const
670+
{
671+
if ( QgsLayoutItem::containsAdvancedEffects() )
672+
return true;
673+
674+
return mMode == FormatSVG && itemOpacity() < 1.0;
675+
}
676+
669677
void QgsLayoutItemPicture::setPicturePath( const QString &path )
670678
{
671679
mSourcePath = path;

‎src/core/layout/qgslayoutitempicture.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ class CORE_EXPORT QgsLayoutItemPicture: public QgsLayoutItem
265265
void recalculateSize();
266266

267267
void refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties ) override;
268+
bool containsAdvancedEffects() const override;
268269

269270
signals:
270271
//! Is emitted on picture rotation change

‎src/ui/layout/qgslayoutwidgetbase.ui

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@
5353
<property name="geometry">
5454
<rect>
5555
<x>0</x>
56-
<y>0</y>
56+
<y>-316</y>
5757
<width>297</width>
58-
<height>778</height>
58+
<height>810</height>
5959
</rect>
6060
</property>
6161
<layout class="QVBoxLayout" name="verticalLayout_2">
@@ -210,7 +210,7 @@
210210
<string>Export settings</string>
211211
</property>
212212
<layout class="QGridLayout" name="gridLayout_3">
213-
<item row="3" column="0" colspan="2">
213+
<item row="4" column="0" colspan="2">
214214
<widget class="QCheckBox" name="mGenerateWorldFileCheckBox">
215215
<property name="sizePolicy">
216216
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@@ -251,8 +251,21 @@
251251
</item>
252252
<item row="2" column="0" colspan="2">
253253
<widget class="QCheckBox" name="mRasterizeCheckBox">
254+
<property name="toolTip">
255+
<string>If checked, exports from this layout will be rasterized.</string>
256+
</property>
257+
<property name="text">
258+
<string>Print as raster</string>
259+
</property>
260+
</widget>
261+
</item>
262+
<item row="3" column="0" colspan="2">
263+
<widget class="QCheckBox" name="mForceVectorCheckBox">
264+
<property name="toolTip">
265+
<string>If checked, the layout will always be kept as vector objects when exported to a compatible format, even if the appearance of the resultant file does not match the layouts settings. If unchecked, some elements in the layout may be rasterised in order to keep their appearance intact.</string>
266+
</property>
254267
<property name="text">
255-
<string>Export as raster</string>
268+
<string>Always export as vectors</string>
256269
</property>
257270
</widget>
258271
</item>
@@ -445,6 +458,7 @@
445458
<tabstop>mSnapToleranceSpinBox</tabstop>
446459
<tabstop>mResolutionSpinBox</tabstop>
447460
<tabstop>mRasterizeCheckBox</tabstop>
461+
<tabstop>mForceVectorCheckBox</tabstop>
448462
<tabstop>mGenerateWorldFileCheckBox</tabstop>
449463
<tabstop>mMarginUnitsComboBox</tabstop>
450464
<tabstop>mTopMarginSpinBox</tabstop>

0 commit comments

Comments
 (0)
Please sign in to comment.